From d2a3e3235968a05fff68f307f94f9a9894623cb6 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Mon, 29 Dec 2025 23:21:28 +0100 Subject: [PATCH 01/26] Initialize branch --- .coderabbit.yaml | 35 + .github/FUNDING.yml | 3 + .github/workflows/firmware.yml | 107 + .gitmodules | 3 + CHANGELOG.md | 9 + CMakeLists.txt | 5 + README.md | 1 + components/ESP32-Lepton | 1 + main/Application/Manager/Devices/ADC/adc.cpp | 122 + main/Application/Manager/Devices/ADC/adc.h | 38 + main/Application/Manager/Devices/I2C/i2c.cpp | 140 + main/Application/Manager/Devices/I2C/i2c.h | 78 + .../Devices/PortExpander/portexpander.cpp | 272 + .../Devices/PortExpander/portexpander.h | 47 + main/Application/Manager/Devices/RTC/rtc.cpp | 453 + main/Application/Manager/Devices/RTC/rtc.h | 143 + main/Application/Manager/Devices/SPI/spi.cpp | 234 + main/Application/Manager/Devices/SPI/spi.h | 83 + main/Application/Manager/Devices/devices.h | 31 + .../Manager/Devices/devicesManager.cpp | 245 + .../Manager/Devices/devicesManager.h | 63 + .../Network/Provisioning/provisioning.cpp | 380 + .../Network/Provisioning/provisioning.h | 70 + .../Application/Manager/Network/SNTP/sntp.cpp | 128 + main/Application/Manager/Network/SNTP/sntp.h | 47 + .../Manager/Network/Server/Websocket.md | 445 + .../Manager/Network/Server/http_server.cpp | 623 + .../Manager/Network/Server/http_server.h | 67 + .../Manager/Network/Server/image_encoder.cpp | 265 + .../Manager/Network/Server/image_encoder.h | 63 + .../Manager/Network/Server/server.h | 125 + .../Network/Server/websocket_handler.cpp | 794 + .../Network/Server/websocket_handler.h | 92 + .../Manager/Network/VISA/CMakeLists.txt | 5 + .../Manager/Network/VISA/README.md | 554 + .../Manager/Network/VISA/visa_commands.cpp | 510 + .../Manager/Network/VISA/visa_commands.h | 76 + .../Manager/Network/VISA/visa_server.cpp | 339 + .../Manager/Network/VISA/visa_server.h | 74 + .../Manager/Network/networkManager.cpp | 774 + .../Manager/Network/networkManager.h | 138 + .../Manager/Network/network_types.h | 248 + main/Application/Manager/SD/sdManager.cpp | 438 + main/Application/Manager/SD/sdManager.h | 83 + .../Manager/Settings/settingsManager.cpp | 451 + .../Manager/Settings/settingsManager.h | 120 + .../Manager/Settings/settings_types.h | 107 + main/Application/Manager/Time/timeManager.cpp | 400 + main/Application/Manager/Time/timeManager.h | 125 + main/Application/Manager/Time/time_types.h | 41 + main/Application/Manager/managers.h | 33 + .../Application/Tasks/Devices/devicesTask.cpp | 244 + main/Application/Tasks/Devices/devicesTask.h | 44 + .../Tasks/GUI/Export/CMakeLists.txt | 13 + .../GUI/Export/components/ui_comp_hook.c | 5 + .../Application/Tasks/GUI/Export/filelist.txt | 11 + .../Tasks/GUI/Export/fonts/ui_font_fa.c | 17288 ++++++++++++++++ .../GUI/Export/images/ui_img_logo_80x44_png.c | 136 + .../Export/images/ui_img_text_218x40_png.c | 298 + .../Application/Tasks/GUI/Export/project.info | 9 + .../Tasks/GUI/Export/screens/ui_Info.c | 757 + .../Tasks/GUI/Export/screens/ui_Info.h | 66 + .../Tasks/GUI/Export/screens/ui_Main.c | 440 + .../Tasks/GUI/Export/screens/ui_Main.h | 55 + .../Tasks/GUI/Export/screens/ui_Menu.c | 85 + .../Tasks/GUI/Export/screens/ui_Menu.h | 28 + .../Tasks/GUI/Export/screens/ui_Splash.c | 127 + .../Tasks/GUI/Export/screens/ui_Splash.h | 30 + main/Application/Tasks/GUI/Export/ui.c | 47 + main/Application/Tasks/GUI/Export/ui.h | 48 + .../Tasks/GUI/Export/ui_events.cpp | 196 + main/Application/Tasks/GUI/Export/ui_events.h | 22 + .../Application/Tasks/GUI/Export/ui_helpers.c | 347 + .../Application/Tasks/GUI/Export/ui_helpers.h | 147 + .../Tasks/GUI/Private/guiHelper.cpp | 333 + .../Application/Tasks/GUI/Private/guiHelper.h | 140 + main/Application/Tasks/GUI/guiTask.cpp | 1182 ++ main/Application/Tasks/GUI/guiTask.h | 52 + main/Application/Tasks/Lepton/leptonTask.cpp | 532 + main/Application/Tasks/Lepton/leptonTask.h | 51 + .../Application/Tasks/Network/networkTask.cpp | 437 + main/Application/Tasks/Network/networkTask.h | 45 + main/Application/Tasks/tasks.h | 32 + main/Application/application.h | 134 + main/Application/bitmap.h | 122 + main/CMakeLists.txt | 13 + main/Kconfig.projbuild | 237 + main/idf_component.yml | 15 + main/main.cpp | 101 + partitions.csv | 8 + platformio.ini | 62 + scripts/astyle.cfg | 33 + scripts/clean.py | 6 + scripts/format.py | 83 + sdkconfig.debug | 3495 ++++ ui/PyroVision.sll | 37 + ui/PyroVision.slp | 12 + ui/PyroVision.spj | 15306 ++++++++++++++ ui/PyroVision_events.py | 48 + ui/Themes.slt | 8 + ui/assets/Font-Awesome | 1 + ui/assets/Logo_80x44.png | Bin 0 -> 6604 bytes ui/assets/Text_218x40.png | Bin 0 -> 11137 bytes ui/project.info | 7 + 104 files changed, 52703 insertions(+) create mode 100644 .coderabbit.yaml create mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/firmware.yml create mode 100644 .gitmodules create mode 100644 CHANGELOG.md create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 160000 components/ESP32-Lepton create mode 100644 main/Application/Manager/Devices/ADC/adc.cpp create mode 100644 main/Application/Manager/Devices/ADC/adc.h create mode 100644 main/Application/Manager/Devices/I2C/i2c.cpp create mode 100644 main/Application/Manager/Devices/I2C/i2c.h create mode 100644 main/Application/Manager/Devices/PortExpander/portexpander.cpp create mode 100644 main/Application/Manager/Devices/PortExpander/portexpander.h create mode 100644 main/Application/Manager/Devices/RTC/rtc.cpp create mode 100644 main/Application/Manager/Devices/RTC/rtc.h create mode 100644 main/Application/Manager/Devices/SPI/spi.cpp create mode 100644 main/Application/Manager/Devices/SPI/spi.h create mode 100644 main/Application/Manager/Devices/devices.h create mode 100644 main/Application/Manager/Devices/devicesManager.cpp create mode 100644 main/Application/Manager/Devices/devicesManager.h create mode 100644 main/Application/Manager/Network/Provisioning/provisioning.cpp create mode 100644 main/Application/Manager/Network/Provisioning/provisioning.h create mode 100644 main/Application/Manager/Network/SNTP/sntp.cpp create mode 100644 main/Application/Manager/Network/SNTP/sntp.h create mode 100644 main/Application/Manager/Network/Server/Websocket.md create mode 100644 main/Application/Manager/Network/Server/http_server.cpp create mode 100644 main/Application/Manager/Network/Server/http_server.h create mode 100644 main/Application/Manager/Network/Server/image_encoder.cpp create mode 100644 main/Application/Manager/Network/Server/image_encoder.h create mode 100644 main/Application/Manager/Network/Server/server.h create mode 100644 main/Application/Manager/Network/Server/websocket_handler.cpp create mode 100644 main/Application/Manager/Network/Server/websocket_handler.h create mode 100644 main/Application/Manager/Network/VISA/CMakeLists.txt create mode 100644 main/Application/Manager/Network/VISA/README.md create mode 100644 main/Application/Manager/Network/VISA/visa_commands.cpp create mode 100644 main/Application/Manager/Network/VISA/visa_commands.h create mode 100644 main/Application/Manager/Network/VISA/visa_server.cpp create mode 100644 main/Application/Manager/Network/VISA/visa_server.h create mode 100644 main/Application/Manager/Network/networkManager.cpp create mode 100644 main/Application/Manager/Network/networkManager.h create mode 100644 main/Application/Manager/Network/network_types.h create mode 100644 main/Application/Manager/SD/sdManager.cpp create mode 100644 main/Application/Manager/SD/sdManager.h create mode 100644 main/Application/Manager/Settings/settingsManager.cpp create mode 100644 main/Application/Manager/Settings/settingsManager.h create mode 100644 main/Application/Manager/Settings/settings_types.h create mode 100644 main/Application/Manager/Time/timeManager.cpp create mode 100644 main/Application/Manager/Time/timeManager.h create mode 100644 main/Application/Manager/Time/time_types.h create mode 100644 main/Application/Manager/managers.h create mode 100644 main/Application/Tasks/Devices/devicesTask.cpp create mode 100644 main/Application/Tasks/Devices/devicesTask.h create mode 100644 main/Application/Tasks/GUI/Export/CMakeLists.txt create mode 100644 main/Application/Tasks/GUI/Export/components/ui_comp_hook.c create mode 100644 main/Application/Tasks/GUI/Export/filelist.txt create mode 100644 main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c create mode 100644 main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c create mode 100644 main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c create mode 100644 main/Application/Tasks/GUI/Export/project.info create mode 100644 main/Application/Tasks/GUI/Export/screens/ui_Info.c create mode 100644 main/Application/Tasks/GUI/Export/screens/ui_Info.h create mode 100644 main/Application/Tasks/GUI/Export/screens/ui_Main.c create mode 100644 main/Application/Tasks/GUI/Export/screens/ui_Main.h create mode 100644 main/Application/Tasks/GUI/Export/screens/ui_Menu.c create mode 100644 main/Application/Tasks/GUI/Export/screens/ui_Menu.h create mode 100644 main/Application/Tasks/GUI/Export/screens/ui_Splash.c create mode 100644 main/Application/Tasks/GUI/Export/screens/ui_Splash.h create mode 100644 main/Application/Tasks/GUI/Export/ui.c create mode 100644 main/Application/Tasks/GUI/Export/ui.h create mode 100644 main/Application/Tasks/GUI/Export/ui_events.cpp create mode 100644 main/Application/Tasks/GUI/Export/ui_events.h create mode 100644 main/Application/Tasks/GUI/Export/ui_helpers.c create mode 100644 main/Application/Tasks/GUI/Export/ui_helpers.h create mode 100644 main/Application/Tasks/GUI/Private/guiHelper.cpp create mode 100644 main/Application/Tasks/GUI/Private/guiHelper.h create mode 100644 main/Application/Tasks/GUI/guiTask.cpp create mode 100644 main/Application/Tasks/GUI/guiTask.h create mode 100644 main/Application/Tasks/Lepton/leptonTask.cpp create mode 100644 main/Application/Tasks/Lepton/leptonTask.h create mode 100644 main/Application/Tasks/Network/networkTask.cpp create mode 100644 main/Application/Tasks/Network/networkTask.h create mode 100644 main/Application/Tasks/tasks.h create mode 100644 main/Application/application.h create mode 100644 main/Application/bitmap.h create mode 100644 main/CMakeLists.txt create mode 100644 main/Kconfig.projbuild create mode 100644 main/idf_component.yml create mode 100644 main/main.cpp create mode 100644 partitions.csv create mode 100644 platformio.ini create mode 100644 scripts/astyle.cfg create mode 100644 scripts/clean.py create mode 100644 scripts/format.py create mode 100644 sdkconfig.debug create mode 100644 ui/PyroVision.sll create mode 100644 ui/PyroVision.slp create mode 100644 ui/PyroVision.spj create mode 100644 ui/PyroVision_events.py create mode 100644 ui/Themes.slt create mode 160000 ui/assets/Font-Awesome create mode 100644 ui/assets/Logo_80x44.png create mode 100644 ui/assets/Text_218x40.png create mode 100644 ui/project.info diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000..48c7c23 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +language: "en-US" +reviews: + profile: "chill" + high_level_summary: true + poem: false + collapse_walkthrough: true + sequence_diagrams: false + auto_review: + enabled: true + drafts: true + in_progress_fortune: false + tools: + github-checks: + enabled: false + cppcheck: + enabled: true + pylint: + enabled: true + yamllint: + enabled: false + markdownlint: + enabled: true + finishing_touches: + docstrings: + enabled: false + unit_tests: + enabled: false + pre_merge_checks: + docstrings: + mode: "off" + title: + mode: "off" +chat: + art: false diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..97f18d6 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [Kampi] diff --git a/.github/workflows/firmware.yml b/.github/workflows/firmware.yml new file mode 100644 index 0000000..52f7f77 --- /dev/null +++ b/.github/workflows/firmware.yml @@ -0,0 +1,107 @@ +name: Firmware + +on: [push] + +jobs: + release: + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + ref: ${{ github.ref }} + + - name: ZIP artifact + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y zip + zip -r ${GITHUB_REF_NAME}.zip . + -x "*.git*" \ + -x "*node_modules*" \ + -x "*.pio*" \ + -x "*__pycache__*" \ + -x "*.vscode*" \ + -x "*build*" \ + -x "*.platformio*" + + - name: Release + uses: docker://antonyurchenko/git-release:v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CHANGELOG_FILE: CHANGELOG.md + with: + args: | + ${GITHUB_REF_NAME}.zip + + build: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: actions/cache@v4 + with: + path: | + ~/.platformio + key: ${{ runner.os }}-pio + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y astyle + + - name: Install PlatformIO Core + run: | + pip install --upgrade platformio + + - name: Format source code + working-directory: firmware + run: | + pio run -t format + + - name: Get release version + run: | + BRANCH_NAME="${GITHUB_REF_NAME}" + echo "BRANCH_NAME=${BRANCH_NAME}" + BASE_VERSION="${BRANCH_NAME%%_*}" + + IFS='.' read -r MAJOR MINOR BUILD <<< "${BASE_VERSION}" + + echo "MAJOR=${MAJOR}" >> ${GITHUB_ENV} + echo "MINOR=${MINOR}" >> ${GITHUB_ENV} + echo "BUILD=${BUILD}" >> ${GITHUB_ENV} + echo "VERSION=${BASE_VERSION}" >> ${GITHUB_ENV} + + - name: Update version numbers + working-directory: firmware + shell: bash + run: | + echo "Using version: ${{ env.VERSION }}" + sed -i -E "s/(PYROVISION_VERSION_MAJOR=)[0-9]+/\1${{ env.MAJOR }}/" CMakeLists.txt + sed -i -E "s/(PYROVISION_VERSION_MINOR=)[0-9]+/\1${{ env.MINOR }}/" CMakeLists.txt + sed -i -E "s/(PYROVISION_VERSION_BUILD=)[0-9]+/\1${{ env.BUILD }}/" CMakeLists.txt + sed -i "s/^## \[Unreleased\]/## [${{ env.VERSION }}] - $(date +'%Y-%m-%d')/" CHANGELOG.md + + - name: Build PlatformIO Project + working-directory: firmware + run: | + pio run + + - name: Prepare upload + working-directory: firmware + run: | + mkdir -p debug + + - name: Upload Firmware + uses: actions/upload-artifact@v4.3.3 + with: + name: debug + path: | + firmware/debug + if-no-files-found: ignore \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..748d293 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ui/assets/Font-Awesome"] + path = ui/assets/Font-Awesome + url = https://github.com/FortAwesome/Font-Awesome.git diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c08ba23 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# CHANGELOG + +## [1.0.0] - + +**Added:** + +**Changed:** + +**Removed:** diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e15039d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.16.0) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(PyroVision) diff --git a/README.md b/README.md new file mode 100644 index 0000000..1adac03 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# PyroVision - Firmware \ No newline at end of file diff --git a/components/ESP32-Lepton b/components/ESP32-Lepton new file mode 160000 index 0000000..6d6d932 --- /dev/null +++ b/components/ESP32-Lepton @@ -0,0 +1 @@ +Subproject commit 6d6d932df55577a86c5ad8ea701370ab8ab1edbf diff --git a/main/Application/Manager/Devices/ADC/adc.cpp b/main/Application/Manager/Devices/ADC/adc.cpp new file mode 100644 index 0000000..982d0e2 --- /dev/null +++ b/main/Application/Manager/Devices/ADC/adc.cpp @@ -0,0 +1,122 @@ +/* + * adc.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: ADC driver implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "adc.h" +#include "../PortExpander/portexpander.h" + +#include + +static bool _ADC_Calib_Done = false; + +static adc_cali_handle_t _ADC_Calib_Handle; +static adc_oneshot_unit_handle_t _ADC_Handle; +static adc_oneshot_unit_init_cfg_t _ADC_Init_Config = { + .unit_id = ADC_UNIT_1, + .clk_src = ADC_RTC_CLK_SRC_RC_FAST, + .ulp_mode = ADC_ULP_MODE_DISABLE, +}; +static adc_oneshot_chan_cfg_t config = { + .atten = ADC_ATTEN_DB_0, + .bitwidth = ADC_BITWIDTH_DEFAULT, +}; + +const char *TAG = "ADC"; + +esp_err_t ADC_Init(void) +{ + esp_err_t Error; + + ESP_ERROR_CHECK(adc_oneshot_new_unit(&_ADC_Init_Config, &_ADC_Handle)); + ESP_ERROR_CHECK(adc_oneshot_config_channel(_ADC_Handle, ADC_CHANNEL_0, &config)); + + _ADC_Calib_Done = false; + + if (_ADC_Calib_Done == false) { + ESP_LOGD(TAG, "calibration scheme version is %s", "Curve Fitting"); + adc_cali_curve_fitting_config_t CaliConfig = { + .unit_id = _ADC_Init_Config.unit_id, + .chan = ADC_CHANNEL_0, + .atten = config.atten, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + + Error = adc_cali_create_scheme_curve_fitting(&CaliConfig, &_ADC_Calib_Handle); + if (Error == ESP_OK) { + _ADC_Calib_Done = true; + } + } + + if (Error == ESP_OK) { + ESP_LOGD(TAG, "Calibration Success"); + } else if ((Error == ESP_ERR_NOT_SUPPORTED) || (_ADC_Calib_Done == false)) { + ESP_LOGW(TAG, "eFuse not burnt, skip software calibration"); + } else { + ESP_LOGE(TAG, "Invalid arg or no memory"); + return ESP_FAIL; + } + + ESP_LOGD(TAG, "ADC Initialized"); + + return ESP_OK; +} + +esp_err_t ADC_Deinit(void) +{ + ESP_ERROR_CHECK(adc_oneshot_del_unit(_ADC_Handle)); + + if (_ADC_Calib_Done) { + return adc_cali_delete_scheme_curve_fitting(_ADC_Calib_Handle); + } + + return ESP_OK; +} + +esp_err_t ADC_ReadBattery(int *p_Voltage) +{ + int Raw; + + if (p_Voltage == NULL) { + return ESP_ERR_INVALID_ARG; + } + + ESP_ERROR_CHECK(adc_oneshot_read(_ADC_Handle, ADC_CHANNEL_0, &Raw)); + + if (_ADC_Calib_Done) { + ESP_ERROR_CHECK(adc_cali_raw_to_voltage(_ADC_Calib_Handle, Raw, p_Voltage)); + } else { + *p_Voltage = Raw; + } + + ESP_LOGD(TAG, "ADC%d Channel%d raw data: %d", ADC_UNIT_1, ADC_CHANNEL_0, Raw); + ESP_LOGD(TAG, "ADC%d Channel%d cali voltage: %d mV", ADC_UNIT_1, ADC_CHANNEL_0, *p_Voltage); + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/Devices/ADC/adc.h b/main/Application/Manager/Devices/ADC/adc.h new file mode 100644 index 0000000..6f3c201 --- /dev/null +++ b/main/Application/Manager/Devices/ADC/adc.h @@ -0,0 +1,38 @@ +/* + * adc.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: ADC driver interface for battery voltage monitoring. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef ADC_H_ +#define ADC_H_ + +#include +#include + +#include + +esp_err_t ADC_Init(void); + +esp_err_t ADC_Deinit(void); + +esp_err_t ADC_ReadBattery(int *p_Voltage); + +#endif /* ADC_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/I2C/i2c.cpp b/main/Application/Manager/Devices/I2C/i2c.cpp new file mode 100644 index 0000000..5e40152 --- /dev/null +++ b/main/Application/Manager/Devices/I2C/i2c.cpp @@ -0,0 +1,140 @@ +/* + * i2c.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: I2C bus manager implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include +#include +#include +#include + +#include "i2c.h" + +#include + +#define I2C_READ_ADDR(Addr) ((Addr << 0x01) | I2C_MASTER_READ) +#define I2C_WRITE_ADDR(Addr) ((Addr << 0x01) | I2C_MASTER_WRITE) +#define I2C_WAIT 100 / portTICK_PERIOD_MS + +static SemaphoreHandle_t _I2C_Mutex; + +static const char *TAG = "I2C"; + +/** @brief Initialize I2C master bus. + * @param p_Config Pointer to I2C bus configuration + * @param p_Bus_Handle Pointer to store bus handle + * @return ESP_OK on success, error code otherwise + */ +int32_t I2CM_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_Bus_Handle) +{ + _I2C_Mutex = xSemaphoreCreateMutex(); + if (_I2C_Mutex == NULL) { + ESP_LOGE(TAG, "Failed to create I2C mutex!"); + return ESP_ERR_NO_MEM; + } + return i2c_new_master_bus(p_Config, p_Bus_Handle); +} + +/** @brief Deinitialize I2C master bus. + * @param Bus_Handle I2C bus handle + * @return ESP_OK on success, error code otherwise + */ +int32_t I2CM_Deinit(i2c_master_bus_handle_t Bus_Handle) +{ + vSemaphoreDelete(_I2C_Mutex); + return i2c_del_master_bus(Bus_Handle); +} + +/** @brief Write data to I2C device. + * @param p_Dev_Handle Pointer to device handle + * @param p_Data Pointer to data to write + * @param Length Number of bytes to write + * @return ESP_OK on success, error code otherwise + */ +int32_t I2CM_Write(i2c_master_dev_handle_t *p_Dev_Handle, const uint8_t *p_Data, uint32_t Length) +{ + esp_err_t Error; + if ((p_Dev_Handle == NULL) || (*p_Dev_Handle == NULL) || (p_Data == NULL)) { + ESP_LOGE(TAG, "I2C Write: Invalid handle or data pointer"); + return ESP_ERR_INVALID_ARG; + } else if (Length == 0) { + return ESP_OK; + } + ESP_LOGD(TAG, "Write %u bytes:", static_cast(Length)); + for (uint8_t i = 0; i < Length; i++) { + ESP_LOGD(TAG, " Byte %u: 0x%02X", static_cast(i), *(p_Data + i)); + } + Error = ESP_FAIL; + if (xSemaphoreTake(_I2C_Mutex, portMAX_DELAY) == pdTRUE) { + Error = i2c_master_transmit(*p_Dev_Handle, p_Data, Length, I2C_WAIT); + xSemaphoreGive(_I2C_Mutex); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "I2C transmit failed: %d", Error); + } + } + return Error; +} + +/** @brief Read data from I2C device. + * @param p_Dev_Handle Pointer to device handle + * @param p_Data Pointer to buffer for received data + * @param Length Number of bytes to read + * @return ESP_OK on success, error code otherwise + */ +int32_t I2CM_Read(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t *p_Data, uint32_t Length) +{ + esp_err_t Error; + if ((p_Dev_Handle == NULL) || (*p_Dev_Handle == NULL) || (p_Data == NULL)) { + ESP_LOGE(TAG, "I2C Read: Invalid handle or data pointer"); + return ESP_ERR_INVALID_ARG; + } else if (Length == 0) { + return ESP_OK; + } + ESP_LOGD(TAG, "Read %u bytes:", static_cast(Length)); + for (uint8_t i = 0; i < Length; i++) { + ESP_LOGD(TAG, " Byte %u: 0x%02X", static_cast(i), *(p_Data + i)); + } + Error = ESP_FAIL; + if (xSemaphoreTake(_I2C_Mutex, portMAX_DELAY) == pdTRUE) { + Error = i2c_master_receive(*p_Dev_Handle, p_Data, Length, I2C_WAIT); + xSemaphoreGive(_I2C_Mutex); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "I2C receive failed: %d", Error); + } + } + return Error; +} + +int32_t I2CM_ModifyRegister(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Register, uint8_t Mask, uint8_t Value) +{ + int32_t Error; + uint8_t Data[2] = {Register, 0xFF}; + Error = I2CM_Write(p_Dev_Handle, &Data[0], 1) || I2CM_Read(p_Dev_Handle, &Data[1], 1); + if (Error) { + return Error; + } + Data[1] &= ~Mask; + Data[1] |= Value; + ESP_LOGD(TAG, "Modify Register 0x%02X with mask 0x%02X: 0x%02X", Register, Mask, Data[1]); + return I2CM_Write(p_Dev_Handle, Data, sizeof(Data)); +} \ No newline at end of file diff --git a/main/Application/Manager/Devices/I2C/i2c.h b/main/Application/Manager/Devices/I2C/i2c.h new file mode 100644 index 0000000..93bc158 --- /dev/null +++ b/main/Application/Manager/Devices/I2C/i2c.h @@ -0,0 +1,78 @@ +/* + * i2c.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: I2C master driver interface. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef I2C_H_ +#define I2C_H_ + +#include +#include + +#include + +#include + +/** @brief Initialize the I2C driver. + * @param p_Config Pointer to configuration options + * @param p_Bus_Handle Pointer to store the created bus handle + * @return ESP_OK when successful + */ +int32_t I2CM_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_Bus_Handle); + +/** @brief Deinitialize the I2C driver. + * @param Bus_Handle I2C bus handle + * @return ESP_OK when successful + */ +int32_t I2CM_Deinit(i2c_master_bus_handle_t Bus_Handle); + +/** @brief Transmit data over the I2C interface. + * @param p_Dev_Handle Pointer to I2C device handle + * @param p_Data Pointer to data + * @param Length Length of data in bytes + * @return ESP_OK when successful + * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function + * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized + */ +int32_t I2CM_Write(i2c_master_dev_handle_t *p_Dev_Handle, const uint8_t *p_Data, uint32_t Length); + +/** @brief Receive data from the I2C interface. + * @param p_Dev_Handle Pointer to I2C device handle + * @param p_Data Pointer to data + * @param Length Length of data in bytes + * @return ESP_OK when successful + * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function + * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized + */ +int32_t I2CM_Read(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t *p_Data, uint32_t Length); + +/** @brief Modify the content of a register. + * @param p_Dev_Handle Pointer to I2C device handle + * @param Register Register address + * @param Mask Bit mask + * @param Value Bit level + * @return ESP_OK when successful + * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function + * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized + */ +int32_t I2CM_ModifyRegister(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Register, uint8_t Mask, uint8_t Value); + +#endif /* I2C_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/PortExpander/portexpander.cpp b/main/Application/Manager/Devices/PortExpander/portexpander.cpp new file mode 100644 index 0000000..fbd6dc1 --- /dev/null +++ b/main/Application/Manager/Devices/PortExpander/portexpander.cpp @@ -0,0 +1,272 @@ +/* + * portexpander.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Port Expander driver implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include +#include + +#include "portexpander.h" + +#include + +#define ADDR_PCAL6416AHF 0x20 + +#define PORT_EXPANDER_ADDR_INPUT0 0x00 +#define PORT_EXPANDER_ADDR_INPUT1 0x01 +#define PORT_EXPANDER_ADDR_OUTPUT0 0x02 +#define PORT_EXPANDER_ADDR_OUTPUT1 0x03 +#define PORT_EXPANDER_ADDR_POL0 0x04 +#define PORT_EXPANDER_ADDR_POL1 0x05 +#define PORT_EXPANDER_ADDR_CONF0 0x06 +#define PORT_EXPANDER_ADDR_CONF1 0x07 +#define PORT_EXPANDER_ADDR_STRENGTH0_0 0x40 +#define PORT_EXPANDER_ADDR_STRENGTH0_1 0x41 +#define PORT_EXPANDER_ADDR_STRENGTH1_0 0x42 +#define PORT_EXPANDER_ADDR_STRENGTH1_1 0x43 +#define PORT_EXPANDER_ADDR_LATCH0 0x44 +#define PORT_EXPANDER_ADDR_LATCH1 0x45 +#define PORT_EXPANDER_ADDR_PULL_EN0 0x46 +#define PORT_EXPANDER_ADDR_PULL_EN1 0x47 +#define PORT_EXPANDER_ADDR_PULL_SEL0 0x48 +#define PORT_EXPANDER_ADDR_PULL_SEL1 0x49 +#define PORT_EXPANDER_ADDR_INT_MASK0 0x4A +#define PORT_EXPANDER_ADDR_INT_MASK1 0x4B +#define PORT_EXPANDER_ADDR_INT_STATUS0 0x4C +#define PORT_EXPANDER_ADDR_INT_STATUS1 0x4D +#define PORT_EXPANDER_ADDR_OUT_CONFIG 0x4F + +#define PORT_EXPANDER_INPUT 0x01 +#define PORT_EXPANDER_OUTPUT 0x00 + +/** @brief Battery voltage enable pin connected to port 0, pin 0. + */ +#define PIN_BATTERY_VOLTAGE_ENABLE 0 + +/** @brief The LDO are connected with port 0, pin 1. + */ +#define PIN_CAMERA 1 + +/** @brief The LED is connected with port 0, pin 2. + */ +#define PIN_LED 2 + +/** @brief Port expander port number declaration. + */ +typedef enum { + PORT_0 = 0x00, + PORT_1 = 0x01, +} PortDefinition_t; + +/** @brief Port expander pull option declaration. + */ +typedef enum { + PULL_PULLDOWN = 0x00, + PULL_PULLUP = 0x01, +} PullDefinition_t; + +/** @brief Port expander polarity configuration declaration. + */ +typedef enum { + POL_NORMAL = 0x00, + POL_INVERT = 0x01, +} PolDefinition_t; + +/** @brief Default input polarity inversion configuration for the Port Expander. + */ +static uint8_t DefaultPolarityConfig[] = { // Byte 0 + PORT_EXPANDER_ADDR_POL0, + + // Byte 1 (Polarity 0) + 0x00, + + // Byte 2 (Polarity 1) + 0x00, +}; + +/** @brief Default input latch configuration for the Port Expander. + */ +static uint8_t DefaultLatchConfig[] = { // Byte 0 + PORT_EXPANDER_ADDR_LATCH0, + + // Byte 1 (Latch 0) + 0x00, + + // Byte 2 (Latch 1) + 0x00, +}; + +/** @brief Default pull-up / pull-down configuration for the Port Expander. + */ +static uint8_t DefaultPullConfig[] = { // Byte 0 + PORT_EXPANDER_ADDR_PULL_EN0, + + // Byte 1 (Enable 0) + 0x00, + + // Byte 2 (Enable 1) + 0x00, + + // Byte 3 (Select 0) + 0x00, + + // Byte 4 (Select 1) + 0x00, +}; + +/** @brief Default output pin configuration for the Port Expander. + */ +static uint8_t DefaultPortConfiguration[] = { // Byte 0 + PORT_EXPANDER_ADDR_CONF0, + + // Byte 1 (Config 0) + (PORT_EXPANDER_OUTPUT << PIN_BATTERY_VOLTAGE_ENABLE) | (PORT_EXPANDER_OUTPUT << PIN_CAMERA) | + (PORT_EXPANDER_OUTPUT << PIN_LED), + + // Byte 2 (Config 1) + 0x00, +}; + +/** @brief Default output pin level for the Port Expander. + */ +static uint8_t DefaultPinConfiguration[] = { // Byte 0 + PORT_EXPANDER_ADDR_OUTPUT0, + + // Byte 1 (Output 0) + // Enable camera power by default (active high for PIN_CAMERA) + // Battery voltage measurement and LED are off + (0x01 << PIN_CAMERA), + + // Byte 2 (Output 1) + 0x00, +}; + +static i2c_device_config_t _Expander_I2C_Config = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = ADDR_PCAL6416AHF, + .scl_speed_hz = 400000, + .scl_wait_us = 0, + .flags = { + .disable_ack_check = 0, + }, +}; + +static i2c_master_dev_handle_t _Expander_Dev_Handle; + +static const char *TAG = "PortExpander"; + +/** @brief Set the pin level of the pins of a given port. + * @param Port Target port + * @param Mask Pin mask + * @param Level Pin level + * @return ESP_OK when successful + * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function + * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized + */ +static esp_err_t PortExpander_SetPinLevel(PortDefinition_t Port, uint8_t Mask, uint8_t Level) +{ + return I2CM_ModifyRegister(&_Expander_Dev_Handle, PORT_EXPANDER_ADDR_OUTPUT0 + static_cast(Port), Mask, Level); +} + +/** @brief Enable the interrupts for given pins. + * @param Port Target port + * @param Mask Pin mask + * @param EnableMask Interrupt enable mask + * @return ESP_OK when successful + * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function + * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized + */ +static esp_err_t PortExpander_SetInterruptMask(PortDefinition_t Port, uint8_t Mask, uint8_t EnableMask) +{ + return I2CM_ModifyRegister(&_Expander_Dev_Handle, PORT_EXPANDER_ADDR_INT_MASK0 + static_cast(Port), Mask, + ~EnableMask); +} + +#ifdef DEBUG +void PortExpander_DumpRegister(void) +{ + uint8_t Data; + + ESP_LOGI(TAG, "Register dump:"); + + for (uint8_t i = 0x00; i < 0x08; i++) { + I2CM_Write(&_Expander_Dev_Handle, &i, sizeof(i)); + I2CM_Read(&_Expander_Dev_Handle, &Data, sizeof(Data)); + ESP_LOGI(TAG, " Register 0x%X: 0x%X", i, Data); + } + + for (uint8_t i = 0x40; i < 0x4F; i++) { + I2CM_Write(&_Expander_Dev_Handle, &i, sizeof(i)); + I2CM_Read(&_Expander_Dev_Handle, &Data, sizeof(Data)); + ESP_LOGI(TAG, " Register 0x%X: 0x%X", i, Data); + } +} +#endif + +esp_err_t PortExpander_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *Bus_Handle) +{ + esp_err_t Error; + + Error = i2c_master_bus_add_device(*Bus_Handle, &_Expander_I2C_Config, &_Expander_Dev_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to add I2C device: %d!", Error); + return Error; + } + + ESP_LOGI(TAG, "Configure Port Expander..."); + + return I2CM_Write(&_Expander_Dev_Handle, DefaultPortConfiguration, sizeof(DefaultPortConfiguration)) || + I2CM_Write(&_Expander_Dev_Handle, DefaultPinConfiguration, sizeof(DefaultPinConfiguration)) || + I2CM_Write(&_Expander_Dev_Handle, DefaultPullConfig, sizeof(DefaultPullConfig)) || + I2CM_Write(&_Expander_Dev_Handle, DefaultLatchConfig, sizeof(DefaultLatchConfig)) || + I2CM_Write(&_Expander_Dev_Handle, DefaultPolarityConfig, sizeof(DefaultPolarityConfig)); +} + +esp_err_t PortExpander_Deinit(void) +{ + if (_Expander_Dev_Handle != NULL) { + esp_err_t Error = i2c_master_bus_rm_device(_Expander_Dev_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to remove I2C device: %d!", Error); + return Error; + } + + _Expander_Dev_Handle = NULL; + } + + return ESP_OK; +} + +esp_err_t PortExpander_EnableCamera(bool Enable) +{ + return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_CAMERA), (!Enable << PIN_CAMERA)); +} + +esp_err_t PortExpander_EnableLED(bool Enable) +{ + return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_LED), (Enable << PIN_LED)); +} + +esp_err_t PortExpander_EnableBatteryVoltage(bool Enable) +{ + return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_BATTERY_VOLTAGE_ENABLE), (!Enable << PIN_BATTERY_VOLTAGE_ENABLE)); +} diff --git a/main/Application/Manager/Devices/PortExpander/portexpander.h b/main/Application/Manager/Devices/PortExpander/portexpander.h new file mode 100644 index 0000000..3d90a95 --- /dev/null +++ b/main/Application/Manager/Devices/PortExpander/portexpander.h @@ -0,0 +1,47 @@ +/* + * portexpander.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: GPIO port expander driver interface. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef PORTEXPANDER_H_ +#define PORTEXPANDER_H_ + +#include + +#include "../I2C/i2c.h" + +esp_err_t PortExpander_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *Bus_Handle); + +esp_err_t PortExpander_Deinit(void); + +#ifdef DEBUG +/** @brief Dump the content of the registers from the Port Expander. + */ +void PortExpander_DumpRegister(void); +#endif + +esp_err_t PortExpander_DefaultConfig(void); + +esp_err_t PortExpander_EnableLED(bool Enable); + +esp_err_t PortExpander_EnableBatteryVoltage(bool Enable); + +#endif /* PORTEXPANDER_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/RTC/rtc.cpp b/main/Application/Manager/Devices/RTC/rtc.cpp new file mode 100644 index 0000000..edabbcf --- /dev/null +++ b/main/Application/Manager/Devices/RTC/rtc.cpp @@ -0,0 +1,453 @@ +/* + * rtc.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: RV8263-C8 Real-Time Clock driver implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include +#include +#include + +#include "rtc.h" + +#include + +/* RV8263-C8 I2C Address */ +#define ADDR_RV8263C8 0x51 + +/* RV8263-C8 Register Addresses */ +#define RV8263_REG_CONTROL1 0x00 +#define RV8263_REG_CONTROL2 0x01 +#define RV8263_REG_OFFSET 0x02 +#define RV8263_REG_RAM 0x03 +#define RV8263_REG_SECONDS 0x04 +#define RV8263_REG_MINUTES 0x05 +#define RV8263_REG_HOURS 0x06 +#define RV8263_REG_DATE 0x07 +#define RV8263_REG_WEEKDAY 0x08 +#define RV8263_REG_MONTH 0x09 +#define RV8263_REG_YEAR 0x0A +#define RV8263_REG_SECONDS_ALARM 0x0B +#define RV8263_REG_MINUTES_ALARM 0x0C +#define RV8263_REG_HOURS_ALARM 0x0D +#define RV8263_REG_DATE_ALARM 0x0E +#define RV8263_REG_WEEKDAY_ALARM 0x0F +#define RV8263_REG_TIMER_VALUE 0x10 +#define RV8263_REG_TIMER_MODE 0x11 + +/* Control1 Register Bits */ +#define RV8263_CTRL1_CAP_SEL (1 << 0) /* Oscillator capacitance selection */ +#define RV8263_CTRL1_STOP (1 << 5) /* Stop RTC clock */ +#define RV8263_CTRL1_SR (1 << 7) /* Software reset */ + +/* Control2 Register Bits */ +#define RV8263_CTRL2_CLKIE (1 << 0) /* Clock output interrupt enable */ +#define RV8263_CTRL2_TIE (1 << 1) /* Timer interrupt enable */ +#define RV8263_CTRL2_AIE (1 << 2) /* Alarm interrupt enable */ +#define RV8263_CTRL2_TF (1 << 3) /* Timer flag */ +#define RV8263_CTRL2_AF (1 << 4) /* Alarm flag */ +#define RV8263_CTRL2_CTAIE (1 << 5) /* Countdown timer A interrupt enable */ +#define RV8263_CTRL2_CTBIE (1 << 6) /* Countdown timer B interrupt enable */ +#define RV8263_CTRL2_CTAF (1 << 7) /* Countdown timer A flag */ + +/* Timer Mode Register Bits */ +#define RV8263_TIMER_TE (1 << 2) /* Timer enable */ +#define RV8263_TIMER_TIE (1 << 3) /* Timer interrupt enable */ +#define RV8263_TIMER_TI_TP (1 << 4) /* Timer interrupt mode (pulse/level) */ +#define RV8263_TIMER_TD_MASK 0x03 /* Timer clock frequency mask */ +#define RV8263_TIMER_TD_4096HZ 0x00 /* 4096 Hz */ +#define RV8263_TIMER_TD_64HZ 0x01 /* 64 Hz */ +#define RV8263_TIMER_TD_1HZ 0x02 /* 1 Hz */ +#define RV8263_TIMER_TD_1_60HZ 0x03 /* 1/60 Hz */ + +/* Alarm Register Bits */ +#define RV8263_ALARM_AE (1 << 7) /* Alarm enable (0 = enabled) */ + +/* Seconds Register */ +#define RV8263_SECONDS_OS (1 << 7) /* Oscillator stop flag */ + +/* Month Register */ +#define RV8263_MONTH_CENTURY (1 << 7) /* Century bit */ + +#define MAX_RTC_REGS 64 + +static i2c_device_config_t _RTC_I2C_Config = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = ADDR_RV8263C8, + .scl_speed_hz = 400000, + .scl_wait_us = 0, + .flags = { + .disable_ack_check = 0, + }, +}; + +static i2c_master_dev_handle_t *_RTC_Dev_Handle = NULL; + +static const char *TAG = "RTC"; + +/** @brief Convert BCD to binary. + * @param BCD BCD value + * @return Binary value + */ +static uint8_t RTC_BCD2Bin(uint8_t BCD) +{ + return ((BCD >> 4) * 10) + (BCD & 0x0F); +} + +/** @brief Convert binary to BCD. + * @param Bin Binary value + * @return BCD value + */ +static uint8_t RTC_Bin2BCD(uint8_t Bin) +{ + return ((Bin / 10) << 4) | (Bin % 10); +} + +/** @brief Read a single register from the RTC. + * @param Register Register address + * @param p_Data Pointer to store the read value + * @return ESP_OK when successful + */ +static esp_err_t RTC_ReadRegister(uint8_t Register, uint8_t *p_Data) +{ + esp_err_t Error; + + Error = I2CM_Write(_RTC_Dev_Handle, &Register, 1); + if (Error != ESP_OK) { + return Error; + } + + return I2CM_Read(_RTC_Dev_Handle, p_Data, 1); +} + +/** @brief Write a single register to the RTC. + * @param Register Register address + * @param Data Data to write + * @return ESP_OK when successful + */ +static esp_err_t RTC_WriteRegister(uint8_t Register, uint8_t Data) +{ + uint8_t Buffer[2] = {Register, Data}; + + return I2CM_Write(_RTC_Dev_Handle, Buffer, sizeof(Buffer)); +} + +/** @brief Read multiple consecutive registers from the RTC. + * @param Register Starting register address + * @param p_Data Pointer to store the read values + * @param Length Number of bytes to read + * @return ESP_OK when successful + */ +static esp_err_t RTC_ReadRegisters(uint8_t Register, uint8_t *p_Data, uint8_t Length) +{ + esp_err_t Error; + + Error = I2CM_Write(_RTC_Dev_Handle, &Register, 1); + if (Error != ESP_OK) { + return Error; + } + + return I2CM_Read(_RTC_Dev_Handle, p_Data, Length); +} + +/** @brief Write multiple consecutive registers to the RTC. + * @param Register Starting register address + * @param p_Data Pointer to data to write + * @param Length Number of bytes to write + * @return ESP_OK when successful + */ +static esp_err_t RTC_WriteRegisters(uint8_t Register, const uint8_t *p_Data, uint8_t Length) +{ + uint8_t Buffer[MAX_RTC_REGS + 1]; + + if (Length > MAX_RTC_REGS) { + return ESP_ERR_INVALID_SIZE; + } + + Buffer[0] = Register; + memcpy(&Buffer[1], p_Data, Length); + + return I2CM_Write(_RTC_Dev_Handle, Buffer, Length + 1); +} + +esp_err_t RTC_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_Bus_Handle, + i2c_master_dev_handle_t *p_Dev_Handle) +{ + (void)p_Config; + + esp_err_t Error; + uint8_t Control1; + uint8_t Seconds; + + Error = i2c_master_bus_add_device(*p_Bus_Handle, &_RTC_I2C_Config, p_Dev_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to add I2C device: %d", Error); + return Error; + } + + _RTC_Dev_Handle = p_Dev_Handle; + + ESP_LOGD(TAG, "Initialize RV8263-C8 RTC..."); + + /* Check oscillator stop flag */ + Error = RTC_ReadRegister(RV8263_REG_SECONDS, &Seconds); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read seconds register: %d", Error); + return Error; + } + + if (Seconds & RV8263_SECONDS_OS) { + ESP_LOGW(TAG, "Oscillator was stopped - time may be invalid!"); + /* Clear OS flag by writing seconds register */ + Error = RTC_WriteRegister(RV8263_REG_SECONDS, Seconds & ~RV8263_SECONDS_OS); + if (Error != ESP_OK) { + return Error; + } + } + + /* Read Control1 register */ + Error = RTC_ReadRegister(RV8263_REG_CONTROL1, &Control1); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read control register: %d", Error); + return Error; + } + + /* Ensure oscillator is running */ + if (Control1 & RV8263_CTRL1_STOP) { + ESP_LOGD(TAG, "Starting RTC oscillator..."); + Control1 &= ~RV8263_CTRL1_STOP; + Error = RTC_WriteRegister(RV8263_REG_CONTROL1, Control1); + if (Error != ESP_OK) { + return Error; + } + } + + ESP_LOGD(TAG, "RV8263-C8 RTC initialized successfully"); + + return ESP_OK; +} + +esp_err_t RTC_Deinit(void) +{ + if (_RTC_Dev_Handle != NULL) { + esp_err_t Error; + + Error = i2c_master_bus_rm_device(*_RTC_Dev_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to remove I2C device: %d!", Error); + return Error; + } + + _RTC_Dev_Handle = NULL; + } + + return ESP_OK; +} + +esp_err_t RTC_GetTime(struct tm *p_Time) +{ + esp_err_t Error; + uint8_t Buffer[7]; + + if ((p_Time == NULL) || (_RTC_Dev_Handle == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Read time registers (Seconds to Year) */ + Error = RTC_ReadRegisters(RV8263_REG_SECONDS, Buffer, sizeof(Buffer)); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read time: %d!", Error); + return Error; + } + + /* Convert BCD to binary and map to struct tm format */ + p_Time->tm_sec = RTC_BCD2Bin(Buffer[0] & 0x7F); /* Seconds (0-59) */ + p_Time->tm_min = RTC_BCD2Bin(Buffer[1] & 0x7F); /* Minutes (0-59) */ + p_Time->tm_hour = RTC_BCD2Bin(Buffer[2] & 0x3F); /* Hours (0-23) */ + p_Time->tm_mday = RTC_BCD2Bin(Buffer[3] & 0x3F); /* Day of month (1-31) */ + p_Time->tm_wday = Buffer[4] & 0x07; /* Day of week (0-6) */ + p_Time->tm_mon = RTC_BCD2Bin(Buffer[5] & 0x1F) - 1; /* Month (0-11, struct tm uses 0-based) */ + p_Time->tm_year = RTC_BCD2Bin(Buffer[6]) + 100; /* Years since 1900 (2000 = 100) */ + + /* Check century bit */ + if (Buffer[5] & RV8263_MONTH_CENTURY) { + p_Time->tm_year += 100; + } + + /* Calculate day of year */ + p_Time->tm_yday = 0; + + /* Unknown DST status */ + p_Time->tm_isdst = -1; + + return ESP_OK; +} + +esp_err_t RTC_SetTime(const struct tm *p_Time) +{ + uint8_t Buffer[7]; + int Year; + int Month; + + if ((p_Time == NULL) || (_RTC_Dev_Handle == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Convert struct tm format to RTC values */ + Year = p_Time->tm_year + 1900; /* tm_year is years since 1900 */ + Month = p_Time->tm_mon + 1; /* tm_mon is 0-11, RTC needs 1-12 */ + + /* Validate input */ + if ((p_Time->tm_sec > 59) || (p_Time->tm_min > 59) || (p_Time->tm_hour > 23) || + (p_Time->tm_mday < 1) || (p_Time->tm_mday > 31) || (Month < 1) || (Month > 12) || + (p_Time->tm_wday > 6)) { + ESP_LOGE(TAG, "Invalid time values!"); + + return ESP_ERR_INVALID_ARG; + } + + /* Convert binary to BCD */ + Buffer[0] = RTC_Bin2BCD(p_Time->tm_sec); + Buffer[1] = RTC_Bin2BCD(p_Time->tm_min); + Buffer[2] = RTC_Bin2BCD(p_Time->tm_hour); + Buffer[3] = RTC_Bin2BCD(p_Time->tm_mday); + Buffer[4] = p_Time->tm_wday; + Buffer[5] = RTC_Bin2BCD(Month); + Buffer[6] = RTC_Bin2BCD(Year % 100); + + /* Set century bit if year >= 2100 */ + if (Year >= 2100) { + Buffer[5] |= RV8263_MONTH_CENTURY; + } + + ESP_LOGD(TAG, "Setting time: %04d-%02d-%02d %02d:%02d:%02d", + Year, Month, p_Time->tm_mday, + p_Time->tm_hour, p_Time->tm_min, p_Time->tm_sec); + + return RTC_WriteRegisters(RV8263_REG_SECONDS, Buffer, sizeof(Buffer)); +} + +esp_err_t RTC_SetAlarm(const RTC_Alarm_t *p_Alarm) +{ + uint8_t Buffer[5]; + + if ((p_Alarm == NULL) || (_RTC_Dev_Handle == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Configure alarm registers - set AE bit to 1 to disable, 0 to enable */ + Buffer[0] = p_Alarm->EnableSeconds ? RTC_Bin2BCD(p_Alarm->Seconds) : RV8263_ALARM_AE; + Buffer[1] = p_Alarm->EnableMinutes ? RTC_Bin2BCD(p_Alarm->Minutes) : RV8263_ALARM_AE; + Buffer[2] = p_Alarm->EnableHours ? RTC_Bin2BCD(p_Alarm->Hours) : RV8263_ALARM_AE; + Buffer[3] = p_Alarm->EnableDay ? RTC_Bin2BCD(p_Alarm->Day) : RV8263_ALARM_AE; + Buffer[4] = p_Alarm->EnableWeekday ? p_Alarm->Weekday : RV8263_ALARM_AE; + + return RTC_WriteRegisters(RV8263_REG_SECONDS_ALARM, Buffer, sizeof(Buffer)); +} + +esp_err_t RTC_EnableAlarmInterrupt(bool Enable) +{ + return I2CM_ModifyRegister(_RTC_Dev_Handle, RV8263_REG_CONTROL2, RV8263_CTRL2_AIE, + Enable ? RV8263_CTRL2_AIE : 0); +} + +esp_err_t RTC_ClearAlarmFlag(void) +{ + return I2CM_ModifyRegister(_RTC_Dev_Handle, RV8263_REG_CONTROL2, RV8263_CTRL2_AF, 0); +} + +bool RTC_IsAlarmTriggered(void) +{ + uint8_t Control2; + + if (RTC_ReadRegister(RV8263_REG_CONTROL2, &Control2) != ESP_OK) { + ESP_LOGE(TAG, "Failed to read Control2 register for alarm status"); + return false; + } + + return (Control2 & RV8263_CTRL2_AF) != 0; +} + +esp_err_t RTC_SetTimer(uint8_t Value, RTC_TimerFreq_t Frequency, bool InterruptEnable) +{ + esp_err_t Error; + uint8_t TimerMode; + + if (_RTC_Dev_Handle == NULL) { + return ESP_ERR_INVALID_STATE; + } + + /* Set timer value */ + Error = RTC_WriteRegister(RV8263_REG_TIMER_VALUE, Value); + if (Error != ESP_OK) { + return Error; + } + + /* Configure timer mode */ + TimerMode = RV8263_TIMER_TE | (static_cast(Frequency) & RV8263_TIMER_TD_MASK); + if (InterruptEnable) { + TimerMode |= RV8263_TIMER_TIE; + } + + return RTC_WriteRegister(RV8263_REG_TIMER_MODE, TimerMode); +} + +esp_err_t RTC_StopTimer(void) +{ + return RTC_WriteRegister(RV8263_REG_TIMER_MODE, 0); +} + +esp_err_t RTC_SoftwareReset(void) +{ + ESP_LOGD(TAG, "Performing software reset..."); + + return RTC_WriteRegister(RV8263_REG_CONTROL1, RV8263_CTRL1_SR); +} + +esp_err_t RTC_WriteRAM(uint8_t Data) +{ + return RTC_WriteRegister(RV8263_REG_RAM, Data); +} + +esp_err_t RTC_ReadRAM(uint8_t *p_Data) +{ + if (p_Data == NULL) { + return ESP_ERR_INVALID_ARG; + } + + return RTC_ReadRegister(RV8263_REG_RAM, p_Data); +} + +#ifdef DEBUG +void RTC_DumpRegisters(void) +{ + uint8_t Data; + + ESP_LOGI(TAG, "Register dump:"); + + for (uint8_t i = 0x00; i <= 0x11; i++) { + if (RTC_ReadRegister(i, &Data) == ESP_OK) { + ESP_LOGI(TAG, " Register 0x%02X: 0x%02X", i, Data); + } + } +} +#endif \ No newline at end of file diff --git a/main/Application/Manager/Devices/RTC/rtc.h b/main/Application/Manager/Devices/RTC/rtc.h new file mode 100644 index 0000000..a84ad9b --- /dev/null +++ b/main/Application/Manager/Devices/RTC/rtc.h @@ -0,0 +1,143 @@ +/* + * rtc.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: RV8263-C8 Real-Time Clock driver header. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef RTC_H_ +#define RTC_H_ + +#include +#include +#include + +#include + +#include "../I2C/i2c.h" + +/** @brief Alarm configuration structure. + */ +typedef struct { + uint8_t Seconds; /**< Alarm seconds (0-59) */ + uint8_t Minutes; /**< Alarm minutes (0-59) */ + uint8_t Hours; /**< Alarm hours (0-23) */ + uint8_t Day; /**< Alarm day of month (1-31) */ + uint8_t Weekday; /**< Alarm weekday (0-6) */ + bool EnableSeconds; /**< Enable seconds matching */ + bool EnableMinutes; /**< Enable minutes matching */ + bool EnableHours; /**< Enable hours matching */ + bool EnableDay; /**< Enable day matching */ + bool EnableWeekday; /**< Enable weekday matching */ +} RTC_Alarm_t; + +/** @brief Timer frequency options. + */ +typedef enum { + RTC_TIMER_FREQ_4096HZ = 0, /**< 4096 Hz (244 µs resolution) */ + RTC_TIMER_FREQ_64HZ = 1, /**< 64 Hz (15.625 ms resolution) */ + RTC_TIMER_FREQ_1HZ = 2, /**< 1 Hz (1 second resolution) */ + RTC_TIMER_FREQ_1_60HZ = 3, /**< 1/60 Hz (1 minute resolution) */ +} RTC_TimerFreq_t; + +/** @brief Initialize the RV8263-C8 RTC. + * @param p_Config Pointer to I2C bus configuration + * @param p_Bus_Handle Pointer to I2C bus handle + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK when successful + */ +esp_err_t RTC_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_Bus_Handle, + i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Deinitialize the RTC driver. + * @return ESP_OK when successful + */ +esp_err_t RTC_Deinit(void); + +/** @brief Get the current time from the RTC. + * @param p_Time Pointer to store the time + * @return ESP_OK when successful + */ +esp_err_t RTC_GetTime(struct tm *p_Time); + +/** @brief Set the time on the RTC. + * @param p_Time Pointer to the time to set + * @return ESP_OK when successful + */ +esp_err_t RTC_SetTime(const struct tm *p_Time); + +/** @brief Configure the alarm. + * @param p_Alarm Pointer to alarm configuration + * @return ESP_OK when successful + */ +esp_err_t RTC_SetAlarm(const RTC_Alarm_t *p_Alarm); + +/** @brief Enable or disable the alarm interrupt. + * @param Enable true to enable, false to disable + * @return ESP_OK when successful + */ +esp_err_t RTC_EnableAlarmInterrupt(bool Enable); + +/** @brief Clear the alarm flag. + * @return ESP_OK when successful + */ +esp_err_t RTC_ClearAlarmFlag(void); + +/** @brief Check if the alarm has been triggered. + * @return true if alarm flag is set + */ +bool RTC_IsAlarmTriggered(void); + +/** @brief Configure and start the countdown timer. + * @param Value Timer countdown value (0-255) + * @param Frequency Timer clock frequency + * @param InterruptEnable Enable timer interrupt + * @return ESP_OK when successful + */ +esp_err_t RTC_SetTimer(uint8_t Value, RTC_TimerFreq_t Frequency, bool InterruptEnable); + +/** @brief Stop the countdown timer. + * @return ESP_OK when successful + */ +esp_err_t RTC_StopTimer(void); + +/** @brief Perform a software reset of the RTC. + * @return ESP_OK when successful + */ +esp_err_t RTC_SoftwareReset(void); + +/** @brief Write a byte to the RAM register. + * @param Data Byte to write + * @return ESP_OK when successful + */ +esp_err_t RTC_WriteRAM(uint8_t Data); + +/** @brief Read a byte from the RAM register. + * @param p_Data Pointer to store the read byte + * @return ESP_OK when successful + */ +esp_err_t RTC_ReadRAM(uint8_t *p_Data); + +#ifdef DEBUG +/** @brief Dump all RTC registers for debugging. + */ +void RTC_DumpRegisters(void); +#endif + +#endif /* RTC_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/SPI/spi.cpp b/main/Application/Manager/Devices/SPI/spi.cpp new file mode 100644 index 0000000..8e2cca4 --- /dev/null +++ b/main/Application/Manager/Devices/SPI/spi.cpp @@ -0,0 +1,234 @@ +/* + * spi.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Central SPI bus manager for shared SPI peripherals. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include +#include +#include + +#include "spi.h" + +#include + +typedef struct { + bool isInitialized; + SemaphoreHandle_t Mutex; + uint32_t DeviceCount; +} SPI_Bus_State_t; + +static SPI_Bus_State_t _SPI_State[SOC_SPI_PERIPH_NUM]; + +static const char *TAG = "spi-manager"; + +/** @brief Initialize SPI bus. + * @param p_Config Pointer to SPI bus configuration + * @param Host SPI host device + * @param DMA_Channel DMA channel to use + * @return ESP_OK on success, error code otherwise + */ +esp_err_t SPIM_Init(const spi_bus_config_t *p_Config, spi_host_device_t Host, int DMA_Channel) +{ + esp_err_t Error; + + if (p_Config == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (Host >= SOC_SPI_PERIPH_NUM) { + ESP_LOGE(TAG, "Invalid SPI host: %d", Host); + return ESP_ERR_INVALID_ARG; + } + + /* Check if already initialized */ + if (_SPI_State[Host].isInitialized) { + ESP_LOGW(TAG, "SPI%d already initialized", Host + 1); + return ESP_ERR_INVALID_STATE; + } + + /* Create mutex for bus access */ + _SPI_State[Host].Mutex = xSemaphoreCreateMutex(); + if (_SPI_State[Host].Mutex == NULL) { + ESP_LOGE(TAG, "Failed to create SPI%d mutex!", Host + 1); + return ESP_ERR_NO_MEM; + } + + /* Initialize the SPI bus */ + Error = spi_bus_initialize(Host, p_Config, DMA_Channel); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize SPI%d bus: %d", Host + 1, Error); + vSemaphoreDelete(_SPI_State[Host].Mutex); + _SPI_State[Host].Mutex = NULL; + return Error; + } + + _SPI_State[Host].isInitialized = true; + _SPI_State[Host].DeviceCount = 0; + + ESP_LOGI(TAG, "SPI%d bus initialized successfully", Host + 1); + + return ESP_OK; +} + +/** @brief Deinitialize SPI bus. + * @param Host SPI host device + * @return ESP_OK on success, error code otherwise + */ +esp_err_t SPIM_Deinit(spi_host_device_t Host) +{ + esp_err_t Error; + + if (Host >= SOC_SPI_PERIPH_NUM) { + return ESP_ERR_INVALID_ARG; + } + + if (_SPI_State[Host].isInitialized == false) { + return ESP_OK; + } + + if (_SPI_State[Host].DeviceCount > 0) { + ESP_LOGW(TAG, "SPI%d still has %d devices attached", Host + 1, _SPI_State[Host].DeviceCount); + } + + if (_SPI_State[Host].Mutex != NULL) { + vSemaphoreDelete(_SPI_State[Host].Mutex); + _SPI_State[Host].Mutex = NULL; + } + + xSemaphoreTake(_SPI_State[Host].Mutex, portMAX_DELAY); + Error = spi_bus_free(Host); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to free SPI%d bus: %d!", Host + 1, Error); + xSemaphoreGive(_SPI_State[Host].Mutex); + return Error; + } + xSemaphoreGive(_SPI_State[Host].Mutex); + + _SPI_State[Host].isInitialized = false; + _SPI_State[Host].DeviceCount = 0; + + ESP_LOGI(TAG, "SPI%d bus deinitialized", Host + 1); + + return ESP_OK; +} + +esp_err_t SPIM_AddDevice(spi_host_device_t Host, const spi_device_interface_config_t *p_Dev_Config, + spi_device_handle_t *p_Handle) +{ + esp_err_t Error; + + if ((p_Dev_Config == NULL) || (p_Handle == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + if (Host >= SOC_SPI_PERIPH_NUM) { + ESP_LOGE(TAG, "Invalid SPI host: %d", Host); + return ESP_ERR_INVALID_ARG; + } + + if (_SPI_State[Host].isInitialized == false) { + ESP_LOGE(TAG, "SPI%d bus not initialized!", Host + 1); + return ESP_ERR_INVALID_STATE; + } + + xSemaphoreTake(_SPI_State[Host].Mutex, portMAX_DELAY); + Error = spi_bus_add_device(Host, p_Dev_Config, p_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to add device to SPI%d: %d!", Host + 1, Error); + xSemaphoreGive(_SPI_State[Host].Mutex); + return Error; + } + + _SPI_State[Host].DeviceCount++; + xSemaphoreGive(_SPI_State[Host].Mutex); + + ESP_LOGI(TAG, "Device added to SPI%d (total: %d devices)", Host + 1, _SPI_State[Host].DeviceCount); + + return ESP_OK; +} + +esp_err_t SPIM_RemoveDevice(spi_host_device_t Host, spi_device_handle_t Handle) +{ + esp_err_t Error; + + if (Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_SPI_State[Host].Mutex, portMAX_DELAY); + Error = spi_bus_remove_device(Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to remove SPI device: %d!", Error); + xSemaphoreGive(_SPI_State[Host].Mutex); + return Error; + } + + /* Decrement device count for the host (we don't track which host, so decrement all) */ + for (int i = 0; i < SOC_SPI_PERIPH_NUM; i++) { + if (_SPI_State[i].DeviceCount > 0) { + _SPI_State[i].DeviceCount--; + break; + } + } + xSemaphoreGive(_SPI_State[Host].Mutex); + + ESP_LOGI(TAG, "SPI device removed"); + + return ESP_OK; +} + +bool SPIM_IsInitialized(spi_host_device_t Host) +{ + if (Host >= SOC_SPI_PERIPH_NUM) { + return false; + } + + return _SPI_State[Host].isInitialized; +} + +esp_err_t SPIM_Transmit(spi_host_device_t Host, spi_device_handle_t Handle, uint8_t *p_Tx_Data, uint8_t *p_Rx_Data, + size_t Length) +{ + esp_err_t Error; + spi_transaction_t trans; + + if (Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(&trans, 0, sizeof(trans)); + trans.tx_buffer = p_Tx_Data; + trans.rx_buffer = p_Rx_Data; + trans.length = Length * 8; + + xSemaphoreTake(_SPI_State[Host].Mutex, portMAX_DELAY); + Error = spi_device_polling_transmit(Handle, &trans); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "SPI transmit failed: %d!", Error); + xSemaphoreGive(_SPI_State[Host].Mutex); + return Error; + } + xSemaphoreGive(_SPI_State[Host].Mutex); + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/Devices/SPI/spi.h b/main/Application/Manager/Devices/SPI/spi.h new file mode 100644 index 0000000..f241b20 --- /dev/null +++ b/main/Application/Manager/Devices/SPI/spi.h @@ -0,0 +1,83 @@ +/* + * spi.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Central SPI bus manager for shared SPI peripherals. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef SPI_H_ +#define SPI_H_ + +#include +#include + +#include +#include + +#include + +/** @brief Initialize the SPI bus. + * @param p_Config Pointer to SPI bus configuration + * @param Host SPI host device (SPI2_HOST or SPI3_HOST) + * @param DMA_Channel DMA channel (SPI_DMA_CH_AUTO recommended) + * @return ESP_OK when successful + * ESP_ERR_INVALID_STATE if bus already initialized + */ +esp_err_t SPIM_Init(const spi_bus_config_t *p_Config, spi_host_device_t Host, int DMA_Channel); + +/** @brief Deinitialize the SPI bus. + * @param Host SPI host device to deinitialize + * @return ESP_OK when successful + */ +esp_err_t SPIM_Deinit(spi_host_device_t Host); + +/** @brief Add a device to the SPI bus. + * @param Host SPI host device + * @param p_Dev_Config Device configuration + * @param p_Handle Pointer to store device handle + * @return ESP_OK when successful + */ +esp_err_t SPIM_AddDevice(spi_host_device_t Host, const spi_device_interface_config_t *p_Dev_Config, + spi_device_handle_t *p_Handle); + +/** @brief Remove a device from the SPI bus. + * @param Host SPI host device + * @param Handle Device handle to remove + * @return ESP_OK when successful + */ +esp_err_t SPIM_RemoveDevice(spi_host_device_t Host, spi_device_handle_t Handle); + +/** @brief Check if SPI host is initialized. + * @param Host SPI host device + * @return true if bus is initialized, false otherwise + */ +bool SPIM_IsInitialized(spi_host_device_t Host); + +/** @brief Transmit data over SPI. + * @param Host SPI host device + * @param Handle Device handle + * @param p_Tx_Data Pointer to data to transmit + * @param p_Rx_Data Pointer to buffer for received data (or NULL if not needed) + * @param Length Length of data to transmit/receive in bytes + * @return ESP_OK when successful + */ +esp_err_t SPIM_Transmit(spi_host_device_t Host, spi_device_handle_t Handle, uint8_t *p_Tx_Data, uint8_t *p_Rx_Data, + size_t Length); + +#endif /* SPI_H_ */ diff --git a/main/Application/Manager/Devices/devices.h b/main/Application/Manager/Devices/devices.h new file mode 100644 index 0000000..41cff11 --- /dev/null +++ b/main/Application/Manager/Devices/devices.h @@ -0,0 +1,31 @@ +/* + * devices.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Device hardware abstraction layer includes. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef DEVICES_H_ +#define DEVICES_H_ + +#include "ADC/adc.h" +#include "RTC/rtc.h" +#include "PortExpander/portexpander.h" + +#endif /* DEVICES_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/devicesManager.cpp b/main/Application/Manager/Devices/devicesManager.cpp new file mode 100644 index 0000000..40aa062 --- /dev/null +++ b/main/Application/Manager/Devices/devicesManager.cpp @@ -0,0 +1,245 @@ +/* + * devicesManager.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Devices management implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include + +#include +#include + +#include + +#include "lepton.h" +#include "devices.h" +#include "devicesManager.h" +#include "I2C/i2c.h" +#include "SPI/spi.h" +#include "ADC/adc.h" +#include "RTC/rtc.h" +#include "PortExpander/portexpander.h" +#include "../Time/timeManager.h" + +/** @brief Voltage divider resistors for battery measurement. + */ +#define BATTERY_R1 10000 /* Upper resistor */ +#define BATTERY_R2 3300 /* Lower resistor */ + +/** @brief Battery voltage range (in millivolts). + */ +#define BATTERY_MIN_VOLTAGE 3300 /* 3.3V */ +#define BATTERY_MAX_VOLTAGE 4200 /* 4.2V (fully charged LiPo) */ + +/** @brief Default configuration for the I2C interface. + */ +static i2c_master_bus_config_t _Devices_Manager_I2CM_Config = { + .i2c_port = static_cast(CONFIG_DEVICES_I2C_HOST), + .sda_io_num = static_cast(CONFIG_DEVICES_I2C_SDA), + .scl_io_num = static_cast(CONFIG_DEVICES_I2C_SCL), + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .intr_priority = 0, + .trans_queue_depth = 0, + .flags = { + .enable_internal_pullup = false, + .allow_pd = false, + }, +}; + +/** @brief Default configuration for the SPI3 bus (shared by LCD, Touch, SD card). + */ +static const spi_bus_config_t _Devices_Manager_SPI_Config = { + .mosi_io_num = CONFIG_SPI_MOSI, + .miso_io_num = CONFIG_SPI_MISO, + .sclk_io_num = CONFIG_SPI_SCLK, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .data4_io_num = -1, + .data5_io_num = -1, + .data6_io_num = -1, + .data7_io_num = -1, + .data_io_default_level = 0, + .max_transfer_sz = CONFIG_SPI_TRANSFER_SIZE, + .flags = SPICOMMON_BUSFLAG_MASTER, + .isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO, + .intr_flags = 0, +}; + +typedef struct { + bool initialized; + i2c_master_dev_handle_t RTC_Handle; + i2c_master_bus_handle_t I2C_Bus_Handle; +} Devices_Manager_State_t; + +static Devices_Manager_State_t _Devices_Manager_State; + +static const char *TAG = "devices-manager"; + +/** @brief Initialize the devices manager. + * @return ESP_OK on success, ESP_FAIL on error + */ +esp_err_t DevicesManager_Init(void) +{ + if (_Devices_Manager_State.initialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + /* Initialize I2C bus */ + if (I2CM_Init(&_Devices_Manager_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize I2C!"); + return ESP_FAIL; + } + + /* Initialize SPI bus */ + if (SPIM_Init(&_Devices_Manager_SPI_Config, SPI3_HOST, SPI_DMA_CH_AUTO) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize SPI3!"); + return ESP_FAIL; + } + + if (ADC_Init() != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize ADC!"); + return ESP_FAIL; + } + + if (PortExpander_Init(&_Devices_Manager_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { + ESP_LOGE(TAG, "Failed to set default configuration for port expander!"); + return ESP_FAIL; + } + + /* Give the camera time to power up and stabilize (Lepton requires ~1.5s boot time) */ + ESP_LOGI(TAG, "Waiting for camera power stabilization..."); + vTaskDelay(2000 / portTICK_PERIOD_MS); + + if (RTC_Init(&_Devices_Manager_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle, + &_Devices_Manager_State.RTC_Handle) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize RTC!"); + return ESP_FAIL; + } + + PortExpander_EnableBatteryVoltage(false); + + _Devices_Manager_State.initialized = true; + + return ESP_OK; +} + +/** @brief Deinitialize the devices manager. + * @return ESP_OK on success, error code otherwise + */ +esp_err_t DevicesManager_Deinit(void) +{ + esp_err_t Error; + + if (_Devices_Manager_State.initialized == false) { + ESP_LOGE(TAG, "Devices manager not initialized yet!"); + return ESP_OK; + } + + PortExpander_EnableBatteryVoltage(false); + + ADC_Deinit(); + RTC_Deinit(); + PortExpander_Deinit(); + Error = I2CM_Deinit(_Devices_Manager_State.I2C_Bus_Handle); + + SPIM_Deinit(SPI3_HOST); + + _Devices_Manager_State.initialized = false; + + return Error; +} + +/** @brief Get the I2C bus handle. + * @return I2C bus handle, or NULL if not initialized + */ +i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void) +{ + if (_Devices_Manager_State.initialized == false) { + ESP_LOGE(TAG, "Devices manager not initialized yet!"); + return NULL; + } + + return _Devices_Manager_State.I2C_Bus_Handle; +} + +/** @brief Get battery voltage and percentage. + * @param p_Voltage Pointer to store voltage in millivolts + * @param p_Percentage Pointer to store percentage (0-100) + * @return ESP_OK on success, error code otherwise + */ +esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage) +{ + int Raw; + esp_err_t Error; + + if (_Devices_Manager_State.initialized == false) { + ESP_LOGE(TAG, "Devices Manager not initialized yet!"); + return ESP_ERR_INVALID_STATE; + } else if ((p_Voltage == NULL) || (p_Percentage == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + PortExpander_EnableBatteryVoltage(true); + + Error = ADC_ReadBattery(&Raw); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read battery voltage: %d", Error); + + PortExpander_EnableBatteryVoltage(false); + + return Error; + } + + PortExpander_EnableBatteryVoltage(false); + + *p_Voltage = Raw * (BATTERY_R1 + BATTERY_R2) / BATTERY_R2; + + *p_Percentage = (*p_Voltage - BATTERY_MIN_VOLTAGE) * 100 / (BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE); + if (*p_Percentage < 0) { + *p_Percentage = 0; + } else if (*p_Percentage > 100) { + *p_Percentage = 100; + } + + return ESP_OK; +} + +/** @brief Get RTC device handle. + * @param p_Handle Pointer to store RTC handle + * @return ESP_OK on success, error code otherwise + */ +esp_err_t DevicesManager_GetRTCHandle(void **p_Handle) +{ + if (_Devices_Manager_State.initialized == false) { + ESP_LOGE(TAG, "Devices Manager not initialized yet!"); + return ESP_ERR_INVALID_STATE; + } + + if (p_Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *p_Handle = &_Devices_Manager_State.RTC_Handle; + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/Devices/devicesManager.h b/main/Application/Manager/Devices/devicesManager.h new file mode 100644 index 0000000..6477b1a --- /dev/null +++ b/main/Application/Manager/Devices/devicesManager.h @@ -0,0 +1,63 @@ +/* + * devicesManager.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Devices management for the peripheral devices. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef DEVICESMANAGER_H_ +#define DEVICESMANAGER_H_ + +#include +#include + +#include +#include + +/** @brief Initialize the Devices Manager. + * @return ESP_OK on success + */ +esp_err_t DevicesManager_Init(void); + +/** @brief Deinitialize the Devices Manager. + * @return ESP_OK on success + */ +esp_err_t DevicesManager_Deinit(void); + +/** @brief Get the I2C bus handle. + * @return I2C bus handle or NULL if not initialized + */ +i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void); + +/** @brief Get the battery voltage and percentage. + * @param p_Voltage Pointer to store voltage in mV + * @param p_Percentage Pointer to store percentage (0-100) + * @return ESP_OK on success + */ +esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage); + +/** @brief Get the RTC device handle (for Time Manager). + * @param p_Handle Pointer to store the RTC handle + * @return ESP_OK on success + */ +esp_err_t DevicesManager_GetRTCHandle(void **p_Handle); + +// TODO: Function to get charge status? + +#endif /* DEVICESMANAGER_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Network/Provisioning/provisioning.cpp b/main/Application/Manager/Network/Provisioning/provisioning.cpp new file mode 100644 index 0000000..971fd45 --- /dev/null +++ b/main/Application/Manager/Network/Provisioning/provisioning.cpp @@ -0,0 +1,380 @@ +/* + * provisioning.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: WiFi provisioning implementation using ESP-IDF unified provisioning. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include + +#include +#include +#include + +#include + +#include "../networkManager.h" +#include "provisioning.h" + +typedef struct { + bool isInitialized; + bool active; + Network_ProvMethod_t Method; + char device_name[32]; + char pop[32]; + uint32_t timeout_sec; + TimerHandle_t timeout_timer; + TaskHandle_t network_task_handle; +} Provisioning_State_t; + +static Provisioning_State_t _Provisioning_State; + +static const char *TAG = "Provisioning"; + +/** @brief Timeout timer callback. + * @param timer Timer handle + */ +static void on_Timeout_Timer_Handler(TimerHandle_t p_Timer) +{ + /* Use task notification to signal timeout */ + if (_Provisioning_State.network_task_handle != NULL) { + xTaskNotify(_Provisioning_State.network_task_handle, 0x01, eSetBits); + } +} + +/** @brief Provisioning event handler. + * @param p_Arg User argument + * @param event_base Event base + * @param event_id Event ID + * @param event_data Event data + */ +static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t EventId, void *p_EventData) +{ + switch (EventId) { + case WIFI_PROV_START: { + ESP_LOGD(TAG, "Provisioning started"); + break; + } + case WIFI_PROV_CRED_RECV: { + wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)p_EventData; + ESP_LOGD(TAG, "Received WiFi credentials - SSID: %s", wifi_sta_cfg->ssid); + /* Save credentials */ + NetworkManager_SetCredentials((const char *)wifi_sta_cfg->ssid, (const char *)wifi_sta_cfg->password); + NetworkManager_SaveCredentials(); + break; + } + case WIFI_PROV_CRED_FAIL: { + wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)p_EventData; + ESP_LOGE(TAG, "Provisioning failed! Reason: %s", (*reason == WIFI_PROV_STA_AUTH_ERROR) ? "Auth Error" : "AP Not Found"); + break; + } + case WIFI_PROV_CRED_SUCCESS: { + ESP_LOGD(TAG, "Provisioning successful"); + /* Stop timeout timer */ + if (_Provisioning_State.timeout_timer != NULL) { + xTimerStop(_Provisioning_State.timeout_timer, 0); + } + break; + } + case WIFI_PROV_END: { + ESP_LOGD(TAG, "Provisioning ended"); + wifi_prov_mgr_deinit(); + /* Release BLE/BT memory after provisioning */ + if ((_Provisioning_State.Method == NETWORK_PROV_BLE) || (_Provisioning_State.Method == NETWORK_PROV_BOTH)) { + wifi_prov_scheme_ble_event_cb_free_btdm(NULL, WIFI_PROV_END, NULL); + } + _Provisioning_State.active = false; + break; + } + default: { + break; + } + } +} + +/** @brief Custom endpoint handler for device info. + * @param session_id Session ID + * @param inbuf Input buffer + * @param inlen Input length + * @param outbuf Output buffer + * @param outlen Output length + * @param priv_data Private data + * @return ESP_OK on success + */ +static esp_err_t on_Custom_Data_Prov_Handler(uint32_t session_id, const uint8_t *p_InBuf, + ssize_t inlen, uint8_t **p_OutBuf, + ssize_t *p_OutLen, void *p_PrivData) +{ + if (p_InBuf) { + ESP_LOGD(TAG, "Received custom data: %.*s", (int)inlen, (char *)p_InBuf); + } + + /* Send device info as response */ + const char *response = "{\"device\":\"PyroVision\",\"version\":\"1.0\"}"; + *p_OutLen = strlen(response); + *p_OutBuf = (uint8_t *)malloc(*p_OutLen); + + if (*p_OutBuf == NULL) { + ESP_LOGE(TAG, "Failed to allocate response buffer!"); + return ESP_ERR_NO_MEM; + } + + memcpy(*p_OutBuf, response, *p_OutLen); + + return ESP_OK; +} + +esp_err_t Provisioning_Init(Network_ProvMethod_t Method, const Network_Config_t *p_Config) +{ + if (_Provisioning_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + if (Method == NETWORK_PROV_NONE) { + ESP_LOGD(TAG, "Provisioning disabled"); + return ESP_OK; + } + + ESP_LOGD(TAG, "Initializing Provisioning Manager"); + _Provisioning_State.Method = Method; +#ifdef CONFIG_NETWORK_PROV_BLE_DEVICE_NAME + strncpy(_Provisioning_State.device_name, CONFIG_NETWORK_PROV_BLE_DEVICE_NAME, + sizeof(_Provisioning_State.device_name) - 1); +#else + strncpy(_Provisioning_State.device_name, "PyroVision_PROV", + sizeof(_Provisioning_State.device_name) - 1); +#endif +#ifdef CONFIG_NETWORK_PROV_POP + strncpy(_Provisioning_State.pop, CONFIG_NETWORK_PROV_POP, sizeof(_Provisioning_State.pop) - 1); +#else + strncpy(_Provisioning_State.pop, "pyrovision123", sizeof(_Provisioning_State.pop) - 1); +#endif +#ifdef CONFIG_NETWORK_PROV_TIMEOUT_SEC + _Provisioning_State.timeout_sec = CONFIG_NETWORK_PROV_TIMEOUT_SEC; +#else + _Provisioning_State.timeout_sec = 300; +#endif + /* Register event handler */ + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &on_Prov_Event, NULL)); + + /* Create timeout timer */ + _Provisioning_State.timeout_timer = xTimerCreate("prov_timeout", + (_Provisioning_State.timeout_sec * 1000) / portTICK_PERIOD_MS, + pdFALSE, + NULL, + on_Timeout_Timer_Handler); + + _Provisioning_State.isInitialized = true; + + ESP_LOGD(TAG, "Provisioning initialized"); + + return ESP_OK; +} + +void Provisioning_Deinit(void) +{ + if (_Provisioning_State.isInitialized == false) { + return; + } + + Provisioning_Stop(); + + /* Give time for stop to complete before deinit */ + vTaskDelay(200 / portTICK_PERIOD_MS); + + /* Now safely deinit the provisioning manager */ + wifi_prov_mgr_deinit(); + + if (_Provisioning_State.timeout_timer != NULL) { + xTimerDelete(_Provisioning_State.timeout_timer, portMAX_DELAY); + _Provisioning_State.timeout_timer = NULL; + } + + esp_event_handler_unregister(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &on_Prov_Event); + + _Provisioning_State.isInitialized = false; +} + +esp_err_t Provisioning_Start(void) +{ + esp_err_t Error; + wifi_prov_mgr_config_t prov_config; + const char *pop = NULL; + char service_name[32]; + uint8_t mac[6]; + + if (_Provisioning_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + if (_Provisioning_State.active) { + ESP_LOGW(TAG, "Provisioning already active"); + return ESP_OK; + } + + memset(&prov_config, 0, sizeof(prov_config)); + + ESP_LOGD(TAG, "Starting Provisioning"); + + if ((_Provisioning_State.Method == NETWORK_PROV_BLE) || (_Provisioning_State.Method == NETWORK_PROV_BOTH)) { + prov_config.scheme = wifi_prov_scheme_ble; + prov_config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; + } + + if (_Provisioning_State.Method == NETWORK_PROV_SOFTAP) { + prov_config.scheme = wifi_prov_scheme_softap; + prov_config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; + } + + prov_config.app_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; + + /* Initialize provisioning */ + Error = wifi_prov_mgr_init(prov_config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to init Provisioning: %d!", Error); + return Error; + } + + /* Security configuration */ +#ifdef CONFIG_NETWORK_PROV_SECURITY_VERSION + int security = CONFIG_NETWORK_PROV_SECURITY_VERSION; +#else + int security = 1; +#endif + + if ((security == 1) && (strlen(_Provisioning_State.pop) > 0)) { + pop = _Provisioning_State.pop; + } + + /* Set service name (BLE device name or SoftAP SSID) */ + esp_wifi_get_mac(WIFI_IF_STA, mac); + snprintf(service_name, sizeof(service_name), "%.26s_%02X%02X", _Provisioning_State.device_name, mac[4], mac[5]); + if ((_Provisioning_State.Method == NETWORK_PROV_BLE) || (_Provisioning_State.Method == NETWORK_PROV_BOTH)) { + /* Configure BLE service UUID */ + uint8_t custom_service_uuid[] = { + 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, + 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, + }; + wifi_prov_scheme_ble_set_service_uuid(custom_service_uuid); + } + + /* Register custom endpoint */ + wifi_prov_mgr_endpoint_create("custom-data"); + + /* Start provisioning */ + Error = wifi_prov_mgr_start_provisioning((wifi_prov_security_t)security, + pop, service_name, NULL); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to start provisioning: %d!", Error); + wifi_prov_mgr_deinit(); + return Error; + } + + /* Register custom endpoint handler */ + wifi_prov_mgr_endpoint_register("custom-data", on_Custom_Data_Prov_Handler, NULL); + _Provisioning_State.active = true; + + /* Post provisioning started event */ + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STARTED, NULL, 0, portMAX_DELAY); + + /* Start timeout timer */ + if (_Provisioning_State.timeout_timer != NULL) { + xTimerStart(_Provisioning_State.timeout_timer, 0); + } + + ESP_LOGD(TAG, "Provisioning started. Service name: %s", service_name); + + return ESP_OK; +} + +esp_err_t Provisioning_Stop(void) +{ + if (_Provisioning_State.active == false) { + return ESP_OK; + } + + ESP_LOGD(TAG, "Stopping Provisioning"); + + /* Stop timeout timer */ + if (_Provisioning_State.timeout_timer != NULL) { + xTimerStop(_Provisioning_State.timeout_timer, 0); + } + + /* Stop provisioning service - do NOT deinit to avoid race conditions */ + /* The provisioning manager can be restarted without deinit */ + wifi_prov_mgr_stop_provisioning(); + + _Provisioning_State.active = false; + + /* Post provisioning stopped event */ + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STOPPED, NULL, 0, portMAX_DELAY); + + return ESP_OK; +} + +bool Provisioning_isProvisioned(void) +{ + bool isProvisioned = false; + wifi_prov_mgr_config_t config; + + memset(&config, 0, sizeof(wifi_prov_mgr_config_t)); + + if ((_Provisioning_State.Method == NETWORK_PROV_BLE) || (_Provisioning_State.Method == NETWORK_PROV_BOTH)) { + config.scheme = wifi_prov_scheme_ble; + config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; + } else if (_Provisioning_State.Method == NETWORK_PROV_SOFTAP) { + config.scheme = wifi_prov_scheme_softap; + config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; + } + + if (wifi_prov_mgr_init(config) == ESP_OK) { + wifi_prov_mgr_is_provisioned(&isProvisioned); + wifi_prov_mgr_deinit(); + } + + ESP_LOGD(TAG, "Provisioned: %s", isProvisioned ? "true" : "false"); + + return isProvisioned; +} + +esp_err_t Provisioning_Reset(void) +{ + ESP_LOGD(TAG, "Resetting Provisioning"); + + /* Clear WiFi credentials from NVS */ + NetworkManager_ClearCredentials(); + + /* Reset provisioning state */ + wifi_prov_mgr_reset_provisioning(); + + return ESP_OK; +} + +bool Provisioning_isActive(void) +{ + return _Provisioning_State.active; +} + +void Provisioning_SetNetworkTaskHandle(TaskHandle_t task_handle) +{ + _Provisioning_State.network_task_handle = task_handle; +} diff --git a/main/Application/Manager/Network/Provisioning/provisioning.h b/main/Application/Manager/Network/Provisioning/provisioning.h new file mode 100644 index 0000000..4c2c73a --- /dev/null +++ b/main/Application/Manager/Network/Provisioning/provisioning.h @@ -0,0 +1,70 @@ +/* + * provisioning.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: WiFi provisioning via BLE and SoftAP. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef PROVISIONING_H_ +#define PROVISIONING_H_ + +#include "../network_types.h" + +/** @brief Initialize provisioning manager. + * @param Method Provisioning method (BLE, SoftAP, or both) + * @param p_Config Network configuration + * @return ESP_OK on success + */ +esp_err_t Provisioning_Init(Network_ProvMethod_t Method, const Network_Config_t *p_Config); + +/** @brief Deinitialize provisioning manager. + */ +void Provisioning_Deinit(void); + +/** @brief Start provisioning. + * @return ESP_OK on success + */ +esp_err_t Provisioning_Start(void); + +/** @brief Stop provisioning. + * @return ESP_OK on success + */ +esp_err_t Provisioning_Stop(void); + +/** @brief Check if device is provisioned. + * @return true if provisioned + */ +bool Provisioning_isProvisioned(void); + +/** @brief Reset provisioning (clear stored credentials). + * @return ESP_OK on success + */ +esp_err_t Provisioning_Reset(void); + +/** @brief Check if provisioning is active. + * @return true if provisioning is running + */ +bool Provisioning_isActive(void); + +/** @brief Set network task handle for timeout notification. + * @param task_handle Network task handle + */ +void Provisioning_SetNetworkTaskHandle(TaskHandle_t task_handle); + +#endif /* PROVISIONING_H_ */ diff --git a/main/Application/Manager/Network/SNTP/sntp.cpp b/main/Application/Manager/Network/SNTP/sntp.cpp new file mode 100644 index 0000000..4557a6b --- /dev/null +++ b/main/Application/Manager/Network/SNTP/sntp.cpp @@ -0,0 +1,128 @@ +/* + * sntp.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: SNTP management implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include + +#include "sntp.h" +#include "../networkManager.h" + +#define SNTP_TZ_MAX_LEN 64 + +static char _SNTP_Timezone[SNTP_TZ_MAX_LEN] = "CET-1CEST,M3.5.0,M10.5.0/3"; + +static const char *TAG = "sntp"; + +/** @brief SNTP event handler for task coordination. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_SNTP_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + switch (ID) { + case NETWORK_EVENT_SET_TZ: { + size_t Len = strlen((const char *)p_Data); + if (Len < SNTP_TZ_MAX_LEN) { + memcpy(_SNTP_Timezone, (const char *)p_Data, Len + 1); + setenv("TZ", _SNTP_Timezone, 1); + tzset(); + } else { + ESP_LOGE(TAG, "Timezone string too long!"); + } + + break; + } + default: { + break; + } + } +} + +/** @brief SNTP time synchronization callback. + * @param p_tv Pointer to timeval structure with synchronized time + */ +static void on_SNTP_Time_Sync(struct timeval *p_tv) +{ + ESP_LOGD(TAG, "Time synchronized via SNTP"); + + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SNTP_SYNCED, p_tv, sizeof(struct timeval), portMAX_DELAY); +} + +esp_err_t SNTP_Init(void) +{ + esp_err_t Error; + + Error = esp_event_handler_register(NETWORK_EVENTS, NETWORK_EVENT_SET_TZ, on_SNTP_Event_Handler, NULL); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to register event handler: %d!", Error); + return Error; + } + + setenv("TZ", _SNTP_Timezone, 1); + tzset(); + + esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); + esp_sntp_setservername(0, "pool.ntp.org"); + esp_sntp_set_time_sync_notification_cb(on_SNTP_Time_Sync); + esp_sntp_init(); + + return ESP_OK; +} + +esp_err_t SNTP_Deinit(void) +{ + esp_sntp_stop(); + return esp_event_handler_unregister(NETWORK_EVENTS, NETWORK_EVENT_SET_TZ, on_SNTP_Event_Handler); +} + +esp_err_t SNTP_GetTime(uint8_t Retries) +{ + time_t Now; + struct tm TimeInfo; + uint8_t Retry = 0; + + ESP_LOGD(TAG, "Initializing SNTP"); + + memset(&TimeInfo, 0, sizeof(struct tm)); + + while ((TimeInfo.tm_year < (2016 - 1900)) && (++Retry < Retries)) { + ESP_LOGD(TAG, "Waiting for system time... (%d/%d)", Retry, Retries); + vTaskDelay(2000 / portTICK_PERIOD_MS); + time(&Now); + localtime_r(&Now, &TimeInfo); + } + + if (Retry == Retries) { + ESP_LOGW(TAG, "Failed to synchronize time!"); + return ESP_FAIL; + } + + ESP_LOGD(TAG, "Time synchronized successfully"); + time(&Now); + localtime_r(&Now, &TimeInfo); + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/Network/SNTP/sntp.h b/main/Application/Manager/Network/SNTP/sntp.h new file mode 100644 index 0000000..053f3eb --- /dev/null +++ b/main/Application/Manager/Network/SNTP/sntp.h @@ -0,0 +1,47 @@ +/* + * sntp.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: SNTP management. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef SNTP_H_ +#define SNTP_H_ + +#include + +#include + +/** @brief Initialize SNTP and event handlers. + * @return ESP_OK on success + */ +esp_err_t SNTP_Init(void); + +/** @brief Deinitialize SNTP and event handlers. + * @return ESP_OK on success + */ +esp_err_t SNTP_Deinit(void); + +/** @brief Initialize SNTP and synchronize time. + * @param Retries Number of retries to get time + * @return ESP_OK on success + */ +esp_err_t SNTP_GetTime(uint8_t Retries); + +#endif /* SNTP_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Network/Server/Websocket.md b/main/Application/Manager/Network/Server/Websocket.md new file mode 100644 index 0000000..07d684e --- /dev/null +++ b/main/Application/Manager/Network/Server/Websocket.md @@ -0,0 +1,445 @@ +# WebSocket Communication + +## Overview + +Simplified WebSocket protocol for real-time thermal image streaming. **All clients receive JPEG format only** for maximum compatibility and efficiency. + +## Features + +- **Real-time Streaming** - JPEG frames at configurable FPS (1-30) +- **Multi-Client Support** - Up to 4 simultaneous connections +- **Simple Protocol** - Flat JSON structure, no nested types +- **Robust** - Single encoding per frame, proper error handling + +## Protocol + +### Message Format + +**All messages use flat JSON:** + +```json +{ + "cmd": "command_name", + "data": { } +} +``` + +### Commands (Client → Server) + +#### Start Streaming + +```json +{ + "cmd": "start", + "data": { + "fps": 8 + } +} +``` + +**Response:** +```json +{ + "cmd": "started", + "data": { + "status": "ok", + "fps": 8 + } +} +``` + +#### Stop Streaming + +```json +{ + "cmd": "stop" +} +``` + +**Response:** +```json +{ + "cmd": "stopped", + "data": { + "status": "ok" + } +} +``` + +#### Subscribe to Telemetry + +```json +{ + "cmd": "subscribe", + "data": { + "interval": 1000 + } +} +``` + +**Response:** +```json +{ + "cmd": "subscribed", + "data": { + "status": "ok" + } +} +``` + +#### Unsubscribe from Telemetry + +```json +{ + "cmd": "unsubscribe" +} +``` + +### Events (Server → Client) + +#### Telemetry Event + +```json +{ + "cmd": "telemetry", + "data": { + "temp": 25.5 + } +} +``` + +#### Binary Frame Data + +Image frames are sent as **binary WebSocket messages (OPCODE 0x02)** containing JPEG data. + +## Python Client Example + +```python +import asyncio +import websockets +import json +from PIL import Image +from io import BytesIO + +async def stream(): + uri = "ws://192.168.1.100/ws" + + async with websockets.connect(uri, + ping_interval=20, + ping_timeout=60, + max_size=None) as ws: + # Start streaming at 8 FPS + await ws.send(json.dumps({ + "cmd": "start", + "data": {"fps": 8} + })) + + # Receive frames + while True: + message = await ws.recv() + + if isinstance(message, bytes): + # JPEG frame + img = Image.open(BytesIO(message)) + img.show() # or process as needed + else: + # JSON response/event + data = json.loads(message) + print(f"Event: {data}") + +asyncio.run(stream()) +``` + +## Architecture + +### System Components + +```sh +┌─────────────┐ ┌──────────────────┐ ┌──────────────┐ +│ GUI Task │ │ Broadcast Task │ │ WS Clients │ +│ (CPU 0) │ │ (CPU 1) │ │ │ +└─────┬───────┘ └────────┬─────────┘ └──────┬───────┘ + │ │ │ + │ 1. Frame Update │ │ + │ (fast, <10ms) │ │ + │ │ │ + │ 2. NotifyFrameReady() │ │ + │ (non-blocking) │ │ + ├──────────────────────────────>│ │ + │ │ │ + │ 3. Continue GUI │ 4. JPEG Encode │ + │ (no blocking!) │ (200-400ms) │ + │ │ │ + │ │ 5. Send Frame │ + │ ├───────────────────────────────>│ + │ │ (TCP Send) │ + │ │ │ + │ │ 6. Wait for │ + │ │ next frame │ + │ │ │ +``` + +### Task Configuration + +**WebSocket Broadcast Task** (`websocket_handler.cpp`) + +- **Task Name:** `WS_Broadcast` +- **Stack Size:** 4096 Bytes +- **Priority:** 5 (lower than GUI Task priority 10) +- **CPU Affinity:** Core 1 (Network CPU) +- **Queue Length:** 1 (only latest frame notification) + +**Key Design Decisions:** + +1. **Separate Task** - Prevents GUI blocking during encoding/transmission +2. **CPU Pinning** - Network operations on Core 1, GUI rendering on Core 0 +3. **Queue-based** - Frame notifications are queued, not frames themselves +4. **Mutex Optimization** - Released during I/O operations to prevent deadlocks + +## Protocol + +### WebSocket Endpoint + +```sh +ws:///ws +``` + +### Message Format + +All messages use JSON format with the following structure: + +```json +{ + "type": "command|response|event", + "name": "message_name", + "payload": { } +} +``` + +### Commands + +#### Stream Control + +**Start Streaming:** + +```json +{ + "type": "command", + "name": "stream.start", + "payload": { + "format": "jpeg|png|raw", + "fps": 8 + } +} +``` + +- **format**: Image encoding format + - `jpeg` - JPEG compressed (default, recommended) + - `png` - PNG compressed (larger, lossless) + - `raw` - Raw RGB888 data (fastest, largest) +- **fps**: Frame rate (1-30, default: 8) + +**Stop Streaming:** + +```json +{ + "type": "command", + "name": "stream.stop" +} +``` + +#### Telemetry Control + +**Subscribe to Telemetry:** + +```json +{ + "type": "command", + "name": "telemetry.subscribe", + "payload": { + "interval_ms": 1000 + } +} +``` + +- **interval_ms**: Update interval in milliseconds (minimum: 100ms) + +**Unsubscribe from Telemetry:** + +```json +{ + "type": "command", + "name": "telemetry.unsubscribe" +} +``` + +#### LED Control + +**Set LED State:** + +```json +{ + "type": "command", + "name": "led.set", + "payload": { + "state": "on|off|blink", + "blink_ms": 500 + } +} +``` + +### Responses + +All commands receive an acknowledgment response: + +```json +{ + "type": "response", + "name": "stream.start", + "payload": { + "status": "streaming|stopped|subscribed|unsubscribed" + } +} +``` + +### Events + +#### Telemetry Event + +Sent periodically when subscribed: + +```json +{ + "type": "event", + "name": "telemetry", + "payload": { + "sensor_temp_c": 25.5, + "core_temp_c": 45.2 + } +} +``` + +#### Binary Frame Data + +Image frames are sent as binary WebSocket messages (OPCODE 0x02): + +- **JPEG Format:** Binary JPEG data +- **PNG Format:** Binary PNG data +- **RAW Format:** RGB888 pixel data (width × height × 3 bytes) + +## API Reference + +### Initialization + +```cpp +/* Initialize WebSocket handler */ +esp_err_t WebSocket_Handler_Init(const Server_Config_t *p_Config); + +/* Register handler with HTTP server */ +esp_err_t WebSocket_Handler_Register(httpd_handle_t p_ServerHandle); + +/* Start broadcast task */ +esp_err_t WebSocket_Handler_StartTask(void); +``` + +### Frame Broadcasting + +```cpp +/* Set thermal frame data source */ +void WebSocket_Handler_SetThermalFrame(Network_Thermal_Frame_t *p_Frame); + +/* Notify that new frame is ready (non-blocking) */ +esp_err_t WebSocket_Handler_NotifyFrameReady(void); +``` + +**Usage Example:** + +```cpp +// In GUI task, after frame update: +if (WebSocket_Handler_HasClients()) { + WebSocket_Handler_NotifyFrameReady(); // Non-blocking notification +} +``` + +### Telemetry Broadcasting + +```cpp +/* Broadcast telemetry to subscribed clients */ +esp_err_t WebSocket_Handler_BroadcastTelemetry(void); +``` + +### Client Management + +```cpp +/* Get number of connected clients */ +uint8_t WebSocket_Handler_GetClientCount(void); + +/* Check if any clients are connected */ +bool WebSocket_Handler_HasClients(void); + +/* Send ping to all clients */ +esp_err_t WebSocket_Handler_PingAll(void); +``` + +### Cleanup + +```cpp +/* Stop broadcast task */ +void WebSocket_Handler_StopTask(void); + +/* Deinitialize handler */ +void WebSocket_Handler_Deinit(void); +``` + +## JavaScript Client Example + +```javascript +const ws = new WebSocket('ws://192.168.1.100/ws'); + +ws.binaryType = 'arraybuffer'; + +ws.onopen = () => { + // Start streaming at 8 FPS + ws.send(JSON.stringify({ + cmd: 'start', + data: { fps: 8 } + })); +}; + +ws.onmessage = (event) => { + if (event.data instanceof ArrayBuffer) { + // JPEG frame + const blob = new Blob([event.data], { type: 'image/jpeg' }); + const url = URL.createObjectURL(blob); + document.getElementById('image').src = url; + } else { + // JSON event + const data = JSON.parse(event.data); + console.log('Event:', data); + } +}; + +ws.onerror = (error) => { + console.error('WebSocket error:', error); +}; + +ws.onclose = () => { + console.log('WebSocket closed'); +}; +``` + +## Architecture + +### Broadcast Task + +- **Single Encoding**: Each frame is encoded once and sent to all clients +- **CPU Pinning**: Runs on Core 1 (network CPU) to avoid GUI blocking +- **Retry Logic**: 3 retries with backoff on send failures +- **Auto-Cleanup**: Failed clients are automatically removed + +### Performance + +- **Encoding**: ~200-400ms per JPEG frame +- **FPS Limit**: Client-specific (1-30 FPS) +- **Memory**: Single encoded frame shared across all clients +- **Latency**: <100ms from frame capture to client receipt diff --git a/main/Application/Manager/Network/Server/http_server.cpp b/main/Application/Manager/Network/Server/http_server.cpp new file mode 100644 index 0000000..681438a --- /dev/null +++ b/main/Application/Manager/Network/Server/http_server.cpp @@ -0,0 +1,623 @@ +/* + * http_server.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: HTTP server implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "http_server.h" +#include "image_encoder.h" + +#define HTTP_SERVER_API_BASE_PATH "/api/v1" +#define HTTP_SERVER_API_KEY_HEADER "X-API-Key" + +typedef struct { + bool isInitialized; + bool isRunning; + httpd_handle_t Handle; + Server_Config_t Config; + Network_Thermal_Frame_t *ThermalFrame; + uint32_t RequestCount; + uint32_t StartTime; +} HTTP_Server_State_t; + +static HTTP_Server_State_t _HTTPServer_State; + +static const char *TAG = "http_server"; + +/** @brief Check API key authentication. + * @param p_Request HTTP request handle + * @return true if authenticated + */ +static bool HTTP_Server_CheckAuth(httpd_req_t *p_Request) +{ + if (_HTTPServer_State.Config.api_key == NULL) { + return true; + } + + char ApiKey[64] = {0}; + if (httpd_req_get_hdr_value_str(p_Request, HTTP_SERVER_API_KEY_HEADER, ApiKey, sizeof(ApiKey)) != ESP_OK) { + return false; + } + + return (strcmp(ApiKey, _HTTPServer_State.Config.api_key) == 0); +} + +/** @brief Send JSON response. + * @param p_Request HTTP request handle + * @param p_JSON JSON object to send + * @param status_code HTTP status code + * @return ESP_OK on success + */ +static esp_err_t HTTP_Server_SendJSON(httpd_req_t *p_Request, cJSON *p_JSON, int status_code) +{ + esp_err_t Error; + + char *JsonStr = cJSON_PrintUnformatted(p_JSON); + if (JsonStr == NULL) { + httpd_resp_send_err(p_Request, HTTPD_500_INTERNAL_SERVER_ERROR, "JSON encoding failed"); + return ESP_FAIL; + } + + if (status_code != 200) { + char status_str[16]; + snprintf(status_str, sizeof(status_str), "%d", status_code); + httpd_resp_set_status(p_Request, status_str); + } + + httpd_resp_set_type(p_Request, "application/json"); + + if (_HTTPServer_State.Config.enable_cors) { + httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Origin", "*"); + } + + Error = httpd_resp_sendstr(p_Request, JsonStr); + cJSON_free(JsonStr); + + return Error; +} + +/** @brief Send error response. + * @param p_Request HTTP request handle + * @param status_code HTTP status code + * @param p_Message Error message + * @return ESP_OK on success + */ +static esp_err_t HTTP_Server_SendError(httpd_req_t *p_Request, int status_code, const char *p_Message) +{ + esp_err_t Error; + + cJSON *Json = cJSON_CreateObject(); + cJSON_AddStringToObject(Json, "error", p_Message); + cJSON_AddNumberToObject(Json, "code", status_code); + + Error = HTTP_Server_SendJSON(p_Request, Json, status_code); + cJSON_Delete(Json); + + return Error; +} + +/** @brief Parse JSON from request body. + * @param p_Request HTTP request handle + * @return cJSON object or NULL on error + */ +static cJSON *HTTP_Server_ParseJSON(httpd_req_t *p_Request) +{ + int ContentLen = p_Request->content_len; + if (ContentLen <= 0 || ContentLen > 4096) { + return NULL; + } + + char *Buffer = (char *)malloc(ContentLen + 1); + if (Buffer == NULL) { + return NULL; + } + + int Received = httpd_req_recv(p_Request, Buffer, ContentLen); + if (Received != ContentLen) { + free(Buffer); + return NULL; + } + + Buffer[ContentLen] = '\0'; + cJSON *Json = cJSON_Parse(Buffer); + free(Buffer); + + return Json; +} + +/** @brief Handler for POST /api/v1/time. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +static esp_err_t HTTP_Handler_Time(httpd_req_t *p_Request) +{ + esp_err_t Error; + + _HTTPServer_State.RequestCount++; + + if (HTTP_Server_CheckAuth(p_Request) == false) { + return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); + } + + cJSON *json = HTTP_Server_ParseJSON(p_Request); + if (json == NULL) { + return HTTP_Server_SendError(p_Request, 400, "Invalid JSON"); + } + + cJSON *epoch = cJSON_GetObjectItem(json, "epoch"); + cJSON *timezone = cJSON_GetObjectItem(json, "timezone"); + + if (cJSON_IsNumber(epoch) == false) { + cJSON_Delete(json); + return HTTP_Server_SendError(p_Request, 400, "Missing epoch field"); + } + + /* Set system time */ + struct timeval tv = { + .tv_sec = (time_t)epoch->valuedouble, + .tv_usec = 0, + }; + settimeofday(&tv, NULL); + + /* Set timezone if provided */ + if (cJSON_IsString(timezone) && timezone->valuestring != NULL) { + setenv("TZ", timezone->valuestring, 1); + tzset(); + } + + ESP_LOGI(TAG, "Time set to epoch: %f", epoch->valuedouble); + + cJSON_Delete(json); + + /* Send response */ + cJSON *response = cJSON_CreateObject(); + cJSON_AddStringToObject(response, "status", "ok"); + Error = HTTP_Server_SendJSON(p_Request, response, 200); + cJSON_Delete(response); + + return Error; +} + +/** @brief Handler for GET /api/v1/image. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) +{ + esp_err_t Error; + Network_Encoded_Image_t encoded; + + _HTTPServer_State.RequestCount++; + + if (HTTP_Server_CheckAuth(p_Request) == false) { + return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); + } + + if (_HTTPServer_State.ThermalFrame == NULL) { + return HTTP_Server_SendError(p_Request, 503, "No thermal data available"); + } + + /* Parse query parameters */ + char query[128] = {0}; + Network_ImageFormat_t format = NETWORK_IMAGE_FORMAT_JPEG; + Server_Palette_t palette = PALETTE_IRON; + + if (httpd_req_get_url_query_str(p_Request, query, sizeof(query)) == ESP_OK) { + char param[32]; + if (httpd_query_key_value(query, "format", param, sizeof(param)) == ESP_OK) { + if (strcmp(param, "png") == 0) { + format = NETWORK_IMAGE_FORMAT_PNG; + } else if (strcmp(param, "raw") == 0) { + format = NETWORK_IMAGE_FORMAT_RAW; + } + } + if (httpd_query_key_value(query, "palette", param, sizeof(param)) == ESP_OK) { + if (strcmp(param, "gray") == 0) { + palette = PALETTE_GRAY; + } else if (strcmp(param, "rainbow") == 0) { + palette = PALETTE_RAINBOW; + } + } + } + + /* Lock frame data */ + if (xSemaphoreTake(_HTTPServer_State.ThermalFrame->mutex, 100 / portTICK_PERIOD_MS) != pdTRUE) { + return HTTP_Server_SendError(p_Request, 503, "Frame busy"); + } + + /* Encode image */ + Error = Image_Encoder_Encode(_HTTPServer_State.ThermalFrame, format, palette, &encoded); + + xSemaphoreGive(_HTTPServer_State.ThermalFrame->mutex); + + if (Error != ESP_OK) { + return HTTP_Server_SendError(p_Request, 500, "Image encoding failed"); + } + + /* Set content type */ + switch (format) { + case NETWORK_IMAGE_FORMAT_JPEG: + httpd_resp_set_type(p_Request, "image/jpeg"); + break; + case NETWORK_IMAGE_FORMAT_PNG: + httpd_resp_set_type(p_Request, "image/png"); + break; + case NETWORK_IMAGE_FORMAT_RAW: + httpd_resp_set_type(p_Request, "application/octet-stream"); + break; + } + + if (_HTTPServer_State.Config.enable_cors) { + httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Origin", "*"); + } + + /* Send image data */ + Error = httpd_resp_send(p_Request, (const char *)encoded.data, encoded.size); + + /* Free encoded image */ + Image_Encoder_Free(&encoded); + + return Error; +} + +/** @brief Handler for GET /api/v1/telemetry. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) +{ + _HTTPServer_State.RequestCount++; + + if (HTTP_Server_CheckAuth(p_Request) == false) { + return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); + } + + /* Build telemetry response */ + cJSON *json = cJSON_CreateObject(); + + /* Uptime */ + uint32_t uptime = (esp_timer_get_time() / 1000000); + cJSON_AddNumberToObject(json, "uptime_s", uptime); + + /* Sensor temperature (from thermal frame if available) */ + if (_HTTPServer_State.ThermalFrame != NULL) { + cJSON_AddNumberToObject(json, "sensor_temp_c", _HTTPServer_State.ThermalFrame->temp_avg); + } + + /* Core temperature (ESP32 internal) */ + /* Note: ESP32 doesn't have a direct internal temp sensor API, use 0 as placeholder */ + cJSON_AddNumberToObject(json, "core_temp_c", 0); + + /* Supply voltage (placeholder) */ + cJSON_AddNumberToObject(json, "supply_voltage_v", 0); + + /* WiFi RSSI */ + wifi_ap_record_t ap_info; + if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { + cJSON_AddNumberToObject(json, "wifi_rssi_dbm", ap_info.rssi); + } else { + cJSON_AddNumberToObject(json, "wifi_rssi_dbm", 0); + } + + /* SD card info (placeholder) */ + cJSON *sdcard = cJSON_CreateObject(); + cJSON_AddBoolToObject(sdcard, "present", false); + cJSON_AddNumberToObject(sdcard, "free_mb", 0); + cJSON_AddItemToObject(json, "sdcard", sdcard); + + esp_err_t Error = HTTP_Server_SendJSON(p_Request, json, 200); + cJSON_Delete(json); + + return Error; +} + +/** @brief Handler for POST /api/v1/update (OTA). + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +static esp_err_t HTTP_Handler_Update(httpd_req_t *p_Request) +{ + int content_len; + int received = 0; + int total_received = 0; + esp_err_t Error; + esp_ota_handle_t ota_handle; + + _HTTPServer_State.RequestCount++; + + if (HTTP_Server_CheckAuth(p_Request) == false) { + return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); + } + + const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL); + + if (update_partition == NULL) { + return HTTP_Server_SendError(p_Request, 500, "No OTA partition found"); + } + + ESP_LOGI(TAG, "OTA update starting, partition: %s", update_partition->label); + + Error = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &ota_handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_begin failed: %d!", Error); + return HTTP_Server_SendError(p_Request, 500, "OTA begin failed"); + } + + /* Receive firmware data */ + char *buffer = (char *)malloc(1024); + if (buffer == NULL) { + esp_ota_abort(ota_handle); + return HTTP_Server_SendError(p_Request, 500, "Memory allocation failed"); + } + + content_len = p_Request->content_len; + + while (total_received < content_len) { + received = httpd_req_recv(p_Request, buffer, 1024); + if (received <= 0) { + if (received == HTTPD_SOCK_ERR_TIMEOUT) { + continue; + } + free(buffer); + esp_ota_abort(ota_handle); + return HTTP_Server_SendError(p_Request, 500, "Receive failed"); + } + + Error = esp_ota_write(ota_handle, buffer, received); + if (Error != ESP_OK) { + free(buffer); + esp_ota_abort(ota_handle); + ESP_LOGE(TAG, "esp_ota_write failed: %d!", Error); + return HTTP_Server_SendError(p_Request, 500, "OTA write failed"); + } + + total_received += received; + ESP_LOGD(TAG, "OTA progress: %d/%d bytes", total_received, content_len); + } + + free(buffer); + + Error = esp_ota_end(ota_handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_end failed: %d", Error); + return HTTP_Server_SendError(p_Request, 500, "OTA end failed"); + } + + Error = esp_ota_set_boot_partition(update_partition); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_set_boot_partition failed: %d!", Error); + return HTTP_Server_SendError(p_Request, 500, "Set boot partition failed"); + } + + ESP_LOGI(TAG, "OTA update successful, rebooting..."); + + /* Send response */ + cJSON *response = cJSON_CreateObject(); + cJSON_AddStringToObject(response, "status", "updating"); + cJSON_AddStringToObject(response, "message", "Firmware upload successful. Device will reboot after update."); + Error = HTTP_Server_SendJSON(p_Request, response, 200); + cJSON_Delete(response); + + /* Reboot after response is sent */ + vTaskDelay(1000 / portTICK_PERIOD_MS); + esp_restart(); + + return Error; +} + +/** @brief Handler for CORS preflight requests. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +static esp_err_t HTTP_Handler_Options(httpd_req_t *p_Request) +{ + httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Origin", "*"); + httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Headers", "Content-Type, X-API-Key"); + httpd_resp_set_hdr(p_Request, "Access-Control-Max-Age", "86400"); + httpd_resp_send(p_Request, NULL, 0); + + return ESP_OK; +} + +static const httpd_uri_t _URI_Time = { + .uri = HTTP_SERVER_API_BASE_PATH "/time", + .method = HTTP_POST, + .handler = HTTP_Handler_Time, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +static const httpd_uri_t _URI_Image = { + .uri = HTTP_SERVER_API_BASE_PATH "/image", + .method = HTTP_GET, + .handler = HTTP_Handler_Image, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +static const httpd_uri_t _URI_Telemetry = { + .uri = HTTP_SERVER_API_BASE_PATH "/telemetry", + .method = HTTP_GET, + .handler = HTTP_Handler_Telemetry, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +static const httpd_uri_t _URI_Update = { + .uri = HTTP_SERVER_API_BASE_PATH "/update", + .method = HTTP_POST, + .handler = HTTP_Handler_Update, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +static const httpd_uri_t _URI_Options = { + .uri = HTTP_SERVER_API_BASE_PATH "/*", + .method = HTTP_OPTIONS, + .handler = HTTP_Handler_Options, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +esp_err_t HTTP_Server_Init(const Server_Config_t *p_Config) +{ + if (p_Config == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (_HTTPServer_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + ESP_LOGI(TAG, "Initializing HTTP server"); + + memcpy(&_HTTPServer_State.Config, p_Config, sizeof(Server_Config_t)); + _HTTPServer_State.Handle = NULL; + _HTTPServer_State.ThermalFrame = NULL; + _HTTPServer_State.RequestCount = 0; + _HTTPServer_State.isInitialized = true; + + return ESP_OK; +} + +void HTTP_Server_Deinit(void) +{ + if (_HTTPServer_State.isInitialized == false) { + return; + } + + HTTP_Server_Stop(); + _HTTPServer_State.isInitialized = false; + + ESP_LOGI(TAG, "HTTP server deinitialized"); +} + +esp_err_t HTTP_Server_Start(void) +{ + if (_HTTPServer_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + if (_HTTPServer_State.isRunning) { + ESP_LOGW(TAG, "Server already running"); + return ESP_OK; + } + + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + config.server_port = _HTTPServer_State.Config.http_port; + config.max_uri_handlers = 16; + config.max_open_sockets = _HTTPServer_State.Config.max_clients; + config.lru_purge_enable = true; + config.uri_match_fn = httpd_uri_match_wildcard; + + /* WebSocket stability configuration */ + config.recv_wait_timeout = 120; /* Increase receive timeout to 120 seconds */ + config.send_wait_timeout = 120; /* Increase send timeout to 120 seconds */ + config.keep_alive_enable = true; /* Enable TCP keep-alive */ + config.keep_alive_idle = 60; /* Start keep-alive after 60s of idle */ + config.keep_alive_interval = 10; /* Send keep-alive probes every 10s */ + config.keep_alive_count = 3; /* Close connection after 3 failed probes */ + + /* Increase stack size for handling large WebSocket frames */ + config.stack_size = 8192; /* Increase from default 4096 to handle JPEG encoding */ + config.max_resp_headers = 16; /* Increase header limit */ + + ESP_LOGI(TAG, "Starting HTTP server on port %d", config.server_port); + + esp_err_t err = httpd_start(&_HTTPServer_State.Handle, &config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start HTTP server: %s", esp_err_to_name(err)); + return err; + } + + /* Register URI handlers */ + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Time); + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Image); + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Telemetry); + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Update); + + if (_HTTPServer_State.Config.enable_cors) { + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Options); + } + + _HTTPServer_State.isRunning = true; + _HTTPServer_State.StartTime = esp_timer_get_time() / 1000000; + + ESP_LOGI(TAG, "HTTP server started"); + + return ESP_OK; +} + +esp_err_t HTTP_Server_Stop(void) +{ + if (_HTTPServer_State.isRunning == false) { + return ESP_OK; + } + + ESP_LOGI(TAG, "Stopping HTTP server"); + + if (_HTTPServer_State.Handle != NULL) { + httpd_stop(_HTTPServer_State.Handle); + _HTTPServer_State.Handle = NULL; + } + + _HTTPServer_State.isRunning = false; + + return ESP_OK; +} + +bool HTTP_Server_isRunning(void) +{ + return _HTTPServer_State.isRunning; +} + +void HTTP_Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) +{ + /* Consider adding synchronization if called from different contexts */ + _HTTPServer_State.ThermalFrame = p_Frame; +} + +httpd_handle_t HTTP_Server_GetHandle(void) +{ + return _HTTPServer_State.Handle; +} diff --git a/main/Application/Manager/Network/Server/http_server.h b/main/Application/Manager/Network/Server/http_server.h new file mode 100644 index 0000000..57c324f --- /dev/null +++ b/main/Application/Manager/Network/Server/http_server.h @@ -0,0 +1,67 @@ +/* + * http_server.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: HTTP server handler. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef HTTP_SERVER_H_ +#define HTTP_SERVER_H_ + +#include +#include + +#include "../network_types.h" + +/** @brief Initialize the HTTP server. + * @param p_Config Pointer to server configuration. + * @return ESP_OK on success. + */ +esp_err_t HTTP_Server_Init(const Server_Config_t *p_Config); + +/** @brief Deinitialize the HTTP server. + */ +void HTTP_Server_Deinit(void); + +/** @brief Start the HTTP server. + * @return ESP_OK on success + */ +esp_err_t HTTP_Server_Start(void); + +/** @brief Stop the HTTP server. + * @return ESP_OK on success + */ +esp_err_t HTTP_Server_Stop(void); + +/** @brief Check if the HTTP server is running. + * @return true if running + */ +bool HTTP_Server_isRunning(void); + +/** @brief Set thermal frame data for image endpoint. + * @param p_Frame Pointer to thermal frame data. + */ +void HTTP_Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame); + +/** @brief Get the HTTP server handle for WebSocket registration. + * @return HTTP server handle or NULL if not running + */ +httpd_handle_t HTTP_Server_GetHandle(void); + +#endif /* HTTP_SERVER_H_ */ diff --git a/main/Application/Manager/Network/Server/image_encoder.cpp b/main/Application/Manager/Network/Server/image_encoder.cpp new file mode 100644 index 0000000..34f9bd8 --- /dev/null +++ b/main/Application/Manager/Network/Server/image_encoder.cpp @@ -0,0 +1,265 @@ +/* + * image_encoder.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Image encoder implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include + +#include + +#include "image_encoder.h" + +#include "lepton.h" + +typedef struct { + bool isInitialized; + uint8_t JpegQuality; +} Image_Encoder_State_t; + +static Image_Encoder_State_t _Encoder_State; + +static const char *TAG = "image_encoder"; + +/** @brief Get palette lookup table. + * @param palette Palette type. + * @return Pointer to palette array. + */ +static const uint8_t (*Image_Encoder_GetPalette(Server_Palette_t palette))[3] { + switch (palette) + { + case PALETTE_IRON: + return Lepton_Palette_Iron; + case PALETTE_RAINBOW: + return Lepton_Palette_Rainbow; + case PALETTE_GRAY: + default: + return NULL; /* Use grayscale formula */ + } +} + +/** @brief Apply color palette to thermal frame. + * @param p_Frame Pointer to thermal frame (with RGB888 buffer) + * @param palette Color palette (currently ignored, frame already has correct colors) + * @param p_Output Output RGB buffer (width * height * 3 bytes) + * @return ESP_OK on success + */ +static esp_err_t Image_Encoder_ApplyPalette(const Network_Thermal_Frame_t *p_Frame, + Server_Palette_t palette, + uint8_t *p_Output) +{ + if (p_Frame == NULL || p_Output == NULL || p_Frame->buffer == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Frame already contains RGB888 data with palette applied by Lepton task */ + size_t buffer_size = p_Frame->width * p_Frame->height * 3; + memcpy(p_Output, p_Frame->buffer, buffer_size); + + return ESP_OK; +} + +/** @brief Encode RGB data to JPEG. + * @param p_RGB RGB pixel data + * @param width Image width + * @param height Image height + * @param quality JPEG quality (1-100) + * @param p_Encoded Output encoded image + * @return ESP_OK on success + */ +static esp_err_t Image_Encoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, uint16_t height, + uint8_t quality, Network_Encoded_Image_t *p_Encoded) +{ + /* Configure JPEG encoder */ + jpeg_enc_config_t enc_config = { + .width = width, + .height = height, + .src_type = JPEG_PIXEL_FORMAT_RGB888, + .subsampling = JPEG_SUBSAMPLE_420, + .quality = quality, + .rotate = JPEG_ROTATE_0D, + .task_enable = false, + .hfm_task_priority = 0, + .hfm_task_core = 0, + }; + + jpeg_enc_handle_t encoder = NULL; + jpeg_error_t err = jpeg_enc_open(&enc_config, &encoder); + if (err != JPEG_ERR_OK) { + ESP_LOGE(TAG, "Failed to open JPEG encoder: %d", err); + return ESP_FAIL; + } + + /* Allocate output buffer (estimate max size) */ + size_t max_size = width * height * 3; + p_Encoded->data = (uint8_t *)heap_caps_malloc(max_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (p_Encoded->data == NULL) { + p_Encoded->data = (uint8_t *)malloc(max_size); + } + + if (p_Encoded->data == NULL) { + jpeg_enc_close(encoder); + ESP_LOGE(TAG, "Failed to allocate JPEG output buffer"); + return ESP_ERR_NO_MEM; + } + + /* Encode image */ + int out_size = 0; + size_t input_size = width * height * 3; + err = jpeg_enc_process(encoder, p_RGB, input_size, p_Encoded->data, max_size, &out_size); + + jpeg_enc_close(encoder); + + if (err != JPEG_ERR_OK) { + free(p_Encoded->data); + p_Encoded->data = NULL; + ESP_LOGE(TAG, "JPEG encoding failed: %d", err); + return ESP_FAIL; + } + + p_Encoded->size = out_size; + p_Encoded->format = NETWORK_IMAGE_FORMAT_JPEG; + p_Encoded->width = width; + p_Encoded->height = height; + + return ESP_OK; +} + +esp_err_t Image_Encoder_Init(uint8_t quality) +{ + if (_Encoder_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + ESP_LOGI(TAG, "Initializing image encoder, quality=%d", quality); + + _Encoder_State.JpegQuality = quality; + if (_Encoder_State.JpegQuality < 1) { + _Encoder_State.JpegQuality = 1; + } + if (_Encoder_State.JpegQuality > 100) { + _Encoder_State.JpegQuality = 100; + } + + _Encoder_State.isInitialized = true; + + return ESP_OK; +} + +void Image_Encoder_Deinit(void) +{ + if (_Encoder_State.isInitialized == false) { + return; + } + + _Encoder_State.isInitialized = false; + + ESP_LOGI(TAG, "Image encoder deinitialized"); +} + +esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, + Network_ImageFormat_t format, + Server_Palette_t palette, + Network_Encoded_Image_t *p_Encoded) +{ + if ((p_Frame == NULL) || (p_Encoded == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + memset(p_Encoded, 0, sizeof(Network_Encoded_Image_t)); + + size_t pixel_count = p_Frame->width * p_Frame->height; + size_t rgb_size = pixel_count * 3; + + /* Allocate RGB buffer */ + uint8_t *rgb_buffer = (uint8_t *)heap_caps_malloc(rgb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (rgb_buffer == NULL) { + rgb_buffer = (uint8_t *)malloc(rgb_size); + } + + if (rgb_buffer == NULL) { + ESP_LOGE(TAG, "Failed to allocate RGB buffer"); + return ESP_ERR_NO_MEM; + } + + /* Apply color palette */ + esp_err_t err = Image_Encoder_ApplyPalette(p_Frame, palette, rgb_buffer); + if (err != ESP_OK) { + free(rgb_buffer); + return err; + } + + /* Encode based on format */ + switch (format) { + case NETWORK_IMAGE_FORMAT_JPEG: + err = Image_Encoder_EncodeJPEG(rgb_buffer, p_Frame->width, p_Frame->height, + _Encoder_State.JpegQuality, p_Encoded); + break; + + case NETWORK_IMAGE_FORMAT_PNG: + /* PNG not implemented - fall through to RAW */ + ESP_LOGW(TAG, "PNG format not implemented, using RAW"); + /* Fall through */ + + case NETWORK_IMAGE_FORMAT_RAW: + default: + /* Return raw RGB data */ + p_Encoded->data = rgb_buffer; + p_Encoded->size = rgb_size; + p_Encoded->format = NETWORK_IMAGE_FORMAT_RAW; + p_Encoded->width = p_Frame->width; + p_Encoded->height = p_Frame->height; + return ESP_OK; + } + + free(rgb_buffer); + + return err; +} + +void Image_Encoder_Free(Network_Encoded_Image_t *p_Encoded) +{ + if (p_Encoded == NULL) { + return; + } + + if (p_Encoded->data != NULL) { + free(p_Encoded->data); + p_Encoded->data = NULL; + } + + p_Encoded->size = 0; +} + +void Image_Encoder_SetQuality(uint8_t quality) +{ + _Encoder_State.JpegQuality = quality; + if (_Encoder_State.JpegQuality < 1) { + _Encoder_State.JpegQuality = 1; + } + if (_Encoder_State.JpegQuality > 100) { + _Encoder_State.JpegQuality = 100; + } + + ESP_LOGI(TAG, "JPEG quality set to %d", _Encoder_State.JpegQuality); +} diff --git a/main/Application/Manager/Network/Server/image_encoder.h b/main/Application/Manager/Network/Server/image_encoder.h new file mode 100644 index 0000000..dac5ddb --- /dev/null +++ b/main/Application/Manager/Network/Server/image_encoder.h @@ -0,0 +1,63 @@ +/* + * image_encoder.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Image encoder for thermal frames. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef IMAGE_ENCODER_H_ +#define IMAGE_ENCODER_H_ + +#include + +#include "../network_types.h" + +/** @brief Initialize the image encoder. + * @param quality JPEG quality (1-100) + * @return ESP_OK on success + */ +esp_err_t Image_Encoder_Init(uint8_t quality); + +/** @brief Deinitialize the image encoder. + */ +void Image_Encoder_Deinit(void); + +/** @brief Encode a thermal frame to the specified format. + * @param p_Frame Pointer to thermal frame data + * @param format Output image format + * @param palette Color palette to use + * @param p_Encoded Pointer to store encoded image data + * @return ESP_OK on success + */ +esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, + Network_ImageFormat_t format, + Server_Palette_t palette, + Network_Encoded_Image_t *p_Encoded); + +/** @brief Free encoded image data. + * @param p_Encoded Pointer to encoded image structure + */ +void Image_Encoder_Free(Network_Encoded_Image_t *p_Encoded); + +/** @brief Set JPEG encoding quality. + * @param quality Quality value (1-100) + */ +void Image_Encoder_SetQuality(uint8_t quality); + +#endif /* IMAGE_ENCODER_H_ */ diff --git a/main/Application/Manager/Network/Server/server.h b/main/Application/Manager/Network/Server/server.h new file mode 100644 index 0000000..90baba7 --- /dev/null +++ b/main/Application/Manager/Network/Server/server.h @@ -0,0 +1,125 @@ +/* + * server.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Server module header. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef SERVER_H_ +#define SERVER_H_ + +#include "http_server.h" +#include "websocket_handler.h" +#include "image_encoder.h" + +/** @brief Initialize the complete server (HTTP + WebSocket + Image Encoder). + * @param p_Config Pointer to server configuration + * @return ESP_OK on success + */ +static inline esp_err_t Server_Init(const Server_Config_t *p_Config) +{ + esp_err_t Error; + + Error = Image_Encoder_Init(80); /* Default JPEG quality */ + if (Error != ESP_OK) { + return Error; + } + + Error = HTTP_Server_Init(p_Config); + if (Error != ESP_OK) { + Image_Encoder_Deinit(); + return Error; + } + + Error = WebSocket_Handler_Init(p_Config); + if (Error != ESP_OK) { + HTTP_Server_Deinit(); + Image_Encoder_Deinit(); + return Error; + } + + return ESP_OK; +} + +/** @brief Deinitialize the complete server. + */ +static inline void Server_Deinit(void) +{ + WebSocket_Handler_Deinit(); + HTTP_Server_Deinit(); + Image_Encoder_Deinit(); +} + +/** @brief Start the server (HTTP server and register WebSocket handler). + * @return ESP_OK on success + */ +static inline esp_err_t Server_Start(void) +{ + esp_err_t Error; + + Error = HTTP_Server_Start(); + if (Error != ESP_OK) { + return Error; + } + + Error = WebSocket_Handler_Register(HTTP_Server_GetHandle()); + if (Error != ESP_OK) { + HTTP_Server_Stop(); + return Error; + } + + /* Start WebSocket broadcast task */ + Error = WebSocket_Handler_StartTask(); + if (Error != ESP_OK) { + HTTP_Server_Stop(); + return Error; + } + + return ESP_OK; +} + +/** @brief Stop the server. + * @return ESP_OK on success + */ +static inline esp_err_t Server_Stop(void) +{ + /* Stop WebSocket broadcast task first */ + WebSocket_Handler_StopTask(); + + return HTTP_Server_Stop(); +} + +/** @brief Check if the server is running. + * @return true if running + */ +static inline bool Server_isRunning(void) +{ + return HTTP_Server_isRunning(); +} + +/** @brief Set thermal frame data for both HTTP and WebSocket endpoints. + * @param p_Frame Pointer to thermal frame data + */ +static inline void Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) +{ + HTTP_Server_SetThermalFrame(p_Frame); + WebSocket_Handler_SetThermalFrame(p_Frame); +} + +#endif /* SERVER_H_ */ diff --git a/main/Application/Manager/Network/Server/websocket_handler.cpp b/main/Application/Manager/Network/Server/websocket_handler.cpp new file mode 100644 index 0000000..da464f3 --- /dev/null +++ b/main/Application/Manager/Network/Server/websocket_handler.cpp @@ -0,0 +1,794 @@ +/* + * websocket_handler.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: WebSocket handler implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include + +#include + +#include "websocket_handler.h" +#include "image_encoder.h" + +/** @brief WebSocket client state. + */ +typedef struct { + int fd; + bool active; + bool stream_enabled; + bool telemetry_enabled; + Network_ImageFormat_t stream_format; + uint8_t stream_fps; + uint32_t telemetry_interval_ms; + uint32_t last_telemetry_time; + uint32_t last_frame_time; +} WS_Client_t; + +typedef struct { + bool isInitialized; + httpd_handle_t ServerHandle; + Server_Config_t Config; + WS_Client_t Clients[WS_MAX_CLIENTS]; + uint8_t ClientCount; + Network_Thermal_Frame_t *ThermalFrame; + SemaphoreHandle_t ClientsMutex; + TaskHandle_t BroadcastTask; + QueueHandle_t FrameReadyQueue; + bool TaskRunning; +} WebSocket_Handler_State_t; + +static WebSocket_Handler_State_t _WSHandler_State; + +static const char *TAG = "websocket_handler"; + +/** @brief Find client by file descriptor. + * @param FD File descriptor + * @return Pointer to client or NULL if not found + */ +static WS_Client_t *WS_FindClient(int FD) +{ + for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { + if (_WSHandler_State.Clients[i].active && _WSHandler_State.Clients[i].fd == FD) { + return &_WSHandler_State.Clients[i]; + } + } + + return NULL; +} + +/** @brief Add a new client. + * @param FD File descriptor + * @return Pointer to new client or NULL if full + */ +static WS_Client_t *WS_AddClient(int FD) +{ + xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + + for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { + if (_WSHandler_State.Clients[i].active == false) { + _WSHandler_State.Clients[i].fd = FD; + _WSHandler_State.Clients[i].active = true; + _WSHandler_State.Clients[i].stream_enabled = false; + _WSHandler_State.Clients[i].telemetry_enabled = false; + _WSHandler_State.Clients[i].stream_format = NETWORK_IMAGE_FORMAT_JPEG; + _WSHandler_State.Clients[i].stream_fps = 8; + _WSHandler_State.Clients[i].telemetry_interval_ms = 1000; + _WSHandler_State.Clients[i].last_telemetry_time = 0; + _WSHandler_State.Clients[i].last_frame_time = 0; + _WSHandler_State.ClientCount++; + + xSemaphoreGive(_WSHandler_State.ClientsMutex); + + ESP_LOGI(TAG, "Client added: fd=%d, total=%d", FD, _WSHandler_State.ClientCount); + return &_WSHandler_State.Clients[i]; + } + } + + xSemaphoreGive(_WSHandler_State.ClientsMutex); + + ESP_LOGW(TAG, "Max clients reached, rejecting fd=%d", FD); + + return NULL; +} + +/** @brief Remove a client. + * @param FD File descriptor + */ +static void WS_RemoveClient(int FD) +{ + xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + + for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { + if (_WSHandler_State.Clients[i].active && _WSHandler_State.Clients[i].fd == FD) { + _WSHandler_State.Clients[i].active = false; + _WSHandler_State.ClientCount--; + + ESP_LOGI(TAG, "Client removed: fd=%d, total=%d", FD, _WSHandler_State.ClientCount); + break; + } + } + + xSemaphoreGive(_WSHandler_State.ClientsMutex); +} + +/** @brief Send JSON message to a client. + * @param FD File descriptor + * @param p_Cmd Command/Event name + * @param p_Data Data JSON object (will not be freed, can be NULL) + * @return ESP_OK on success + */ +static esp_err_t WS_SendJSON(int FD, const char *p_Cmd, cJSON *p_Data) +{ + cJSON *msg = cJSON_CreateObject(); + cJSON_AddStringToObject(msg, "cmd", p_Cmd); + + if (p_Data != NULL) { + cJSON_AddItemReferenceToObject(msg, "data", p_Data); + } + + char *json_str = cJSON_PrintUnformatted(msg); + cJSON_Delete(msg); + + if (json_str == NULL) { + return ESP_ERR_NO_MEM; + } + + httpd_ws_frame_t Frame = { + .final = true, + .fragmented = false, + .type = HTTPD_WS_TYPE_TEXT, + .payload = (uint8_t *)json_str, + .len = strlen(json_str), + }; + + esp_err_t err = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &Frame); + + cJSON_free(json_str); + + return err; +} + +/** @brief Send binary frame to a client. + * @param FD File descriptor + * @param p_Data Binary data + * @param Length Data length + * @return ESP_OK on success + */ +static esp_err_t WS_SendBinary(int FD, const uint8_t *p_Data, size_t Length) +{ + httpd_ws_frame_t Frame = { + .final = true, + .fragmented = false, + .type = HTTPD_WS_TYPE_BINARY, + .payload = (uint8_t *)p_Data, + .len = Length, + }; + + /* Try to send with retry logic to handle queue congestion */ + esp_err_t err = ESP_FAIL; + for (uint8_t retry = 0; retry < 3; retry++) { + err = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &Frame); + + if (err == ESP_OK) { + /* Send queued successfully - add small delay to prevent queue overflow */ + vTaskDelay(5 / portTICK_PERIOD_MS); + break; + } + + /* Queue might be full, wait and retry */ + ESP_LOGW(TAG, "Failed to queue frame to fd=%d (retry %d): %s", + FD, retry + 1, esp_err_to_name(err)); + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to send binary frame to fd=%d after retries: %s (len=%zu)", + FD, esp_err_to_name(err), Length); + } + + return err; +} + +/** @brief Handle start command. + * @param p_Client Client pointer + * @param p_Data Command data + */ +static void WS_HandleStart(WS_Client_t *p_Client, cJSON *p_Data) +{ + cJSON *fps = cJSON_GetObjectItem(p_Data, "fps"); + + /* Set FPS (default 8) */ + if (cJSON_IsNumber(fps)) { + p_Client->stream_fps = (uint8_t)fps->valueint; + if (p_Client->stream_fps < 1) p_Client->stream_fps = 1; + if (p_Client->stream_fps > 30) p_Client->stream_fps = 30; + } + + /* Always use JPEG format for simplicity and efficiency */ + p_Client->stream_format = NETWORK_IMAGE_FORMAT_JPEG; + p_Client->stream_enabled = true; + p_Client->last_frame_time = 0; + + ESP_LOGI(TAG, "Stream started for fd=%d, fps=%d", p_Client->fd, p_Client->stream_fps); + + /* Send ACK */ + cJSON *response = cJSON_CreateObject(); + cJSON_AddStringToObject(response, "status", "ok"); + cJSON_AddNumberToObject(response, "fps", p_Client->stream_fps); + WS_SendJSON(p_Client->fd, "started", response); + cJSON_Delete(response); +} + +/** @brief Handle stop command. + * @param p_Client Client pointer + */ +static void WS_HandleStop(WS_Client_t *p_Client) +{ + p_Client->stream_enabled = false; + p_Client->last_frame_time = 0; + + ESP_LOGI(TAG, "Stream stopped for fd=%d", p_Client->fd); + + cJSON *response = cJSON_CreateObject(); + cJSON_AddStringToObject(response, "status", "ok"); + WS_SendJSON(p_Client->fd, "stopped", response); + cJSON_Delete(response); +} + +/** @brief Handle subscribe command. + * @param p_Client Client pointer + * @param p_Data Command data + */ +static void WS_HandleTelemetrySubscribe(WS_Client_t *p_Client, cJSON *p_Data) +{ + cJSON *interval = cJSON_GetObjectItem(p_Data, "interval"); + + if (cJSON_IsNumber(interval)) { + p_Client->telemetry_interval_ms = (uint32_t)interval->valueint; + if (p_Client->telemetry_interval_ms < 100) { + p_Client->telemetry_interval_ms = 100; + } + } + + p_Client->telemetry_enabled = true; + + ESP_LOGI(TAG, "Telemetry subscribed for fd=%d, interval=%lu ms", + p_Client->fd, p_Client->telemetry_interval_ms); + + cJSON *response = cJSON_CreateObject(); + cJSON_AddStringToObject(response, "status", "ok"); + WS_SendJSON(p_Client->fd, "subscribed", response); + cJSON_Delete(response); +} + +/** @brief Handle unsubscribe command. + * @param p_Client Client pointer + */ +static void WS_HandleTelemetryUnsubscribe(WS_Client_t *p_Client) +{ + p_Client->telemetry_enabled = false; + + ESP_LOGI(TAG, "Telemetry unsubscribed for fd=%d", p_Client->fd); + + cJSON *response = cJSON_CreateObject(); + cJSON_AddStringToObject(response, "status", "ok"); + WS_SendJSON(p_Client->fd, "unsubscribed", response); + cJSON_Delete(response); +} + +/** @brief Process incoming WebSocket message. + * @param p_Client Client pointer + * @param p_Data Message data + * @param length Message length + */ +static void WS_ProcessMessage(WS_Client_t *p_Client, const char *p_Data, size_t length) +{ + cJSON *json = cJSON_ParseWithLength(p_Data, length); + if (json == NULL) { + ESP_LOGW(TAG, "Invalid JSON from fd=%d", p_Client->fd); + return; + } + + cJSON *cmd = cJSON_GetObjectItem(json, "cmd"); + cJSON *data = cJSON_GetObjectItem(json, "data"); + + if (!cJSON_IsString(cmd)) { + ESP_LOGW(TAG, "Invalid message format from fd=%d", p_Client->fd); + cJSON_Delete(json); + return; + } + + /* Handle commands */ + const char *cmd_str = cmd->valuestring; + if (strcmp(cmd_str, "start") == 0) { + WS_HandleStart(p_Client, data); + } else if (strcmp(cmd_str, "stop") == 0) { + WS_HandleStop(p_Client); + } else if (strcmp(cmd_str, "subscribe") == 0) { + WS_HandleTelemetrySubscribe(p_Client, data); + } else if (strcmp(cmd_str, "unsubscribe") == 0) { + WS_HandleTelemetryUnsubscribe(p_Client); + } else { + ESP_LOGW(TAG, "Unknown command from fd=%d: %s", p_Client->fd, cmd_str); + } + + cJSON_Delete(json); +} + +/** @brief WebSocket handler callback. + */ +static esp_err_t WS_Handler(httpd_req_t *p_Request) +{ + httpd_ws_frame_t Frame; + esp_err_t Error; + WS_Client_t *Client; + int FD; + + /* Handle new connection */ + if (p_Request->method == HTTP_GET) { + WS_Client_t *client = WS_AddClient(httpd_req_to_sockfd(p_Request)); + if (client == NULL) { + httpd_resp_send_err(p_Request, HTTPD_500_INTERNAL_SERVER_ERROR, "Max clients reached"); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "WebSocket handshake with fd=%d", client->fd); + return ESP_OK; + } + + /* Handle WebSocket frame */ + memset(&Frame, 0, sizeof(httpd_ws_frame_t)); + + /* Get frame info */ + Error = httpd_ws_recv_frame(p_Request, &Frame, 0); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to get frame info: %d!", Error); + return Error; + } + + if (Frame.len > 0) { + Frame.payload = (uint8_t *)malloc(Frame.len + 1); + if (Frame.payload == NULL) { + ESP_LOGE(TAG, "Failed to allocate frame buffer!"); + return ESP_ERR_NO_MEM; + } + + Error = httpd_ws_recv_frame(p_Request, &Frame, Frame.len); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to receive frame: %d!", Error); + free(Frame.payload); + return Error; + } + + Frame.payload[Frame.len] = '\0'; + } + + FD = httpd_req_to_sockfd(p_Request); + Client = WS_FindClient(FD); + + switch (Frame.type) { + case HTTPD_WS_TYPE_TEXT: { + if (Client != NULL && Frame.payload != NULL) { + WS_ProcessMessage(Client, (const char *)Frame.payload, Frame.len); + } + + break; + } + case HTTPD_WS_TYPE_CLOSE: { + ESP_LOGI(TAG, "WebSocket close from fd=%d", FD); + WS_RemoveClient(FD); + + break; + } + case HTTPD_WS_TYPE_PING: { + /* Must manually send PONG when handle_ws_control_frames=true */ + ESP_LOGD(TAG, "Ping received from fd=%d, sending Pong", FD); + + httpd_ws_frame_t pong_frame = { + .final = true, + .fragmented = false, + .type = HTTPD_WS_TYPE_PONG, + .payload = Frame.payload, /* Echo back the ping payload */ + .len = Frame.len, + }; + + Error = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &pong_frame); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to send Pong to fd=%d: %d, retrying...", FD, Error); + + /* Pong fails sometimes. So we simply try again */ + vTaskDelay(10 / portTICK_PERIOD_MS); + Error = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &pong_frame); + if(Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to send Pong to fd=%d again: %d, removing client!", FD, Error); + WS_RemoveClient(FD); + } + } + + break; + } + case HTTPD_WS_TYPE_PONG: { + ESP_LOGD(TAG, "Pong received from fd=%d", FD); + + break; + } + default: { + ESP_LOGW(TAG, "Unknown frame type %d from fd=%d", Frame.type, FD); + + break; + } + } + + if (Frame.payload != NULL) { + free(Frame.payload); + } + + return ESP_OK; +} + +static const httpd_uri_t _URI_WebSocket = { + .uri = "/ws", + .method = HTTP_GET, + .handler = WS_Handler, + .user_ctx = NULL, + .is_websocket = true, + .handle_ws_control_frames = true, + .supported_subprotocol = NULL, +}; + +esp_err_t WebSocket_Handler_Init(const Server_Config_t *p_Config) +{ + if (p_Config == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (_WSHandler_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + ESP_LOGI(TAG, "Initializing WebSocket handler"); + + memcpy(&_WSHandler_State.Config, p_Config, sizeof(Server_Config_t)); + memset(_WSHandler_State.Clients, 0, sizeof(_WSHandler_State.Clients)); + _WSHandler_State.ClientCount = 0; + _WSHandler_State.ThermalFrame = NULL; + _WSHandler_State.ServerHandle = NULL; + _WSHandler_State.BroadcastTask = NULL; + _WSHandler_State.FrameReadyQueue = NULL; + _WSHandler_State.TaskRunning = false; + + _WSHandler_State.ClientsMutex = xSemaphoreCreateMutex(); + if (_WSHandler_State.ClientsMutex == NULL) { + ESP_LOGE(TAG, "Failed to create mutex"); + return ESP_ERR_NO_MEM; + } + + /* Create queue for frame ready notifications (queue size = 1, only latest matters) */ + _WSHandler_State.FrameReadyQueue = xQueueCreate(1, sizeof(uint8_t)); + if (_WSHandler_State.FrameReadyQueue == NULL) { + ESP_LOGE(TAG, "Failed to create frame queue!"); + vSemaphoreDelete(_WSHandler_State.ClientsMutex); + return ESP_ERR_NO_MEM; + } + + _WSHandler_State.isInitialized = true; + + return ESP_OK; +} + +void WebSocket_Handler_Deinit(void) +{ + if (_WSHandler_State.isInitialized == false) { + return; + } + + WebSocket_Handler_StopTask(); + + if (_WSHandler_State.FrameReadyQueue != NULL) { + vQueueDelete(_WSHandler_State.FrameReadyQueue); + _WSHandler_State.FrameReadyQueue = NULL; + } + + if (_WSHandler_State.ClientsMutex != NULL) { + vSemaphoreDelete(_WSHandler_State.ClientsMutex); + _WSHandler_State.ClientsMutex = NULL; + } + + _WSHandler_State.isInitialized = false; + + ESP_LOGI(TAG, "WebSocket handler deinitialized"); +} + +esp_err_t WebSocket_Handler_Register(httpd_handle_t p_ServerHandle) +{ + esp_err_t Error; + + if (_WSHandler_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (p_ServerHandle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + _WSHandler_State.ServerHandle = p_ServerHandle; + + Error = httpd_register_uri_handler(p_ServerHandle, &_URI_WebSocket); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to register WebSocket URI: %d!", Error); + return Error; + } + + ESP_LOGI(TAG, "WebSocket handler registered at /ws"); + + return ESP_OK; +} + +uint8_t WebSocket_Handler_GetClientCount(void) +{ + return _WSHandler_State.ClientCount; +} + +bool WebSocket_Handler_HasClients(void) +{ + return _WSHandler_State.ClientCount > 0; +} + +void WebSocket_Handler_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) +{ + xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + _WSHandler_State.ThermalFrame = p_Frame; + xSemaphoreGive(_WSHandler_State.ClientsMutex); +} + +/** @brief Broadcast task function - runs in separate task to avoid blocking GUI. + * @param p_Param Task parameter (unused) + */ +static void WS_BroadcastTask(void *p_Param) +{ + uint8_t Signal; + Network_Encoded_Image_t Encoded; + + ESP_LOGI(TAG, "WebSocket broadcast task started"); + + while (_WSHandler_State.TaskRunning) { + /* Wait for frame ready notification (blocking, 100ms timeout) */ + if (xQueueReceive(_WSHandler_State.FrameReadyQueue, &Signal, 100 / portTICK_PERIOD_MS) == pdTRUE) { + uint32_t Now = esp_timer_get_time() / 1000; + + if ((_WSHandler_State.isInitialized == false) || (_WSHandler_State.ThermalFrame == NULL) || + (_WSHandler_State.ClientCount == 0)) { + continue; + } + + /* Encode frame ONCE for all clients (assume JPEG format for simplicity) */ + if (xSemaphoreTake(_WSHandler_State.ThermalFrame->mutex, 50 / portTICK_PERIOD_MS) == pdTRUE) { + esp_err_t err = Image_Encoder_Encode(_WSHandler_State.ThermalFrame, + NETWORK_IMAGE_FORMAT_JPEG, PALETTE_IRON, &Encoded); + xSemaphoreGive(_WSHandler_State.ThermalFrame->mutex); + + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to encode frame: %d!", err); + continue; + } + } else { + /* Frame mutex busy, skip this frame */ + continue; + } + + /* Send to all active streaming clients */ + xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + + for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { + WS_Client_t *client = &_WSHandler_State.Clients[i]; + + if ((client->active == false) || (client->stream_enabled == false)) { + continue; + } + + /* Check frame rate limit */ + uint32_t frame_interval = 1000 / client->stream_fps; + if ((Now - client->last_frame_time) < frame_interval) { + continue; + } + + /* Release mutex during send to avoid blocking other operations */ + xSemaphoreGive(_WSHandler_State.ClientsMutex); + + /* Send frame to this client */ + esp_err_t send_err = WS_SendBinary(client->fd, Encoded.data, Encoded.size); + + /* Re-acquire mutex to update state */ + xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + + if (send_err == ESP_OK) { + client->last_frame_time = Now; + } else { + /* Send failed - remove client */ + ESP_LOGW(TAG, "Removing client fd=%d due to send failure", client->fd); + client->active = false; + _WSHandler_State.ClientCount--; + } + } + + xSemaphoreGive(_WSHandler_State.ClientsMutex); + + /* Free encoded frame after sending to all clients */ + Image_Encoder_Free(&Encoded); + } + + /* Small yield to prevent task starvation */ + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + ESP_LOGI(TAG, "WebSocket broadcast task stopped"); + vTaskDelete(NULL); +} + +esp_err_t WebSocket_Handler_NotifyFrameReady(void) +{ + uint8_t Signal; + + if ((_WSHandler_State.isInitialized == false) || (_WSHandler_State.FrameReadyQueue == NULL)) { + return ESP_ERR_INVALID_STATE; + } + + if (_WSHandler_State.ClientCount == 0) { + return ESP_OK; + } + + /* Signal frame ready (overwrite if queue full - only latest frame matters) */ + Signal = 1; + xQueueOverwrite(_WSHandler_State.FrameReadyQueue, &Signal); + + return ESP_OK; +} + +esp_err_t WebSocket_Handler_BroadcastTelemetry(void) +{ + uint32_t Now; + + if (_WSHandler_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + if (_WSHandler_State.ClientCount == 0) { + return ESP_OK; + } + + Now = esp_timer_get_time() / 1000; + + /* Build telemetry data */ + cJSON *data = cJSON_CreateObject(); + + if (_WSHandler_State.ThermalFrame != NULL) { + cJSON_AddNumberToObject(data, "temp", _WSHandler_State.ThermalFrame->temp_avg); + } + + xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + + for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { + WS_Client_t *client = &_WSHandler_State.Clients[i]; + + if ((client->active == false) || (client->telemetry_enabled == false)) { + continue; + } + + /* Check interval */ + if ((Now - client->last_telemetry_time) < client->telemetry_interval_ms) { + continue; + } + + WS_SendJSON(client->fd, "telemetry", data); + client->last_telemetry_time = Now; + } + + xSemaphoreGive(_WSHandler_State.ClientsMutex); + + cJSON_Delete(data); + + return ESP_OK; +} + +esp_err_t WebSocket_Handler_PingAll(void) +{ + if ((_WSHandler_State.isInitialized == false) || (_WSHandler_State.ServerHandle == NULL)) { + return ESP_ERR_INVALID_STATE; + } + + httpd_ws_frame_t Frame = { + .final = true, + .fragmented = false, + .type = HTTPD_WS_TYPE_PING, + .payload = NULL, + .len = 0, + }; + + xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + + for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { + if (_WSHandler_State.Clients[i].active) { + httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, _WSHandler_State.Clients[i].fd, &Frame); + } + } + + xSemaphoreGive(_WSHandler_State.ClientsMutex); + + return ESP_OK; +} + +esp_err_t WebSocket_Handler_StartTask(void) +{ + if (_WSHandler_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (_WSHandler_State.BroadcastTask != NULL) { + ESP_LOGW(TAG, "Broadcast task already running"); + return ESP_OK; + } + + _WSHandler_State.TaskRunning = true; + + BaseType_t ret = xTaskCreatePinnedToCore( + WS_BroadcastTask, + "WS_Broadcast", + 4096, + NULL, + 5, + &_WSHandler_State.BroadcastTask, + 1 + ); + + if (ret != pdPASS) { + ESP_LOGE(TAG, "Failed to create broadcast task"); + _WSHandler_State.TaskRunning = false; + return ESP_ERR_NO_MEM; + } + + ESP_LOGI(TAG, "WebSocket broadcast task started"); + + return ESP_OK; +} + +void WebSocket_Handler_StopTask(uint32_t Timeout_ms) +{ + uint32_t Start; + + if (_WSHandler_State.BroadcastTask == NULL) { + return; + } + + ESP_LOGI(TAG, "Stopping WebSocket broadcast task..."); + + _WSHandler_State.TaskRunning = false; + + /* Wait for task to finish (max 2 seconds) */ + Start = esp_timer_get_time() / 1000; + + while (_WSHandler_State.BroadcastTask != NULL && + ((esp_timer_get_time() / 1000) - Start) < Timeout_ms) { + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + _WSHandler_State.BroadcastTask = NULL; + + ESP_LOGI(TAG, "WebSocket broadcast task stopped"); +} diff --git a/main/Application/Manager/Network/Server/websocket_handler.h b/main/Application/Manager/Network/Server/websocket_handler.h new file mode 100644 index 0000000..96330d5 --- /dev/null +++ b/main/Application/Manager/Network/Server/websocket_handler.h @@ -0,0 +1,92 @@ +/* + * websocket_handler.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: WebSocket handler. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef WEBSOCKET_HANDLER_H_ +#define WEBSOCKET_HANDLER_H_ + +#include +#include + +#include "../network_types.h" + +/** @brief Maximum number of WebSocket clients. + */ +#define WS_MAX_CLIENTS 4 + +/** @brief Initialize the WebSocket handler. + * @param p_Config Pointer to server configuration + * @return ESP_OK on success + */ +esp_err_t WebSocket_Handler_Init(const Server_Config_t *p_Config); + +/** @brief Deinitialize the WebSocket handler. + */ +void WebSocket_Handler_Deinit(void); + +/** @brief Register WebSocket handler with HTTP server. + * @param p_ServerHandle HTTP server handle + * @return ESP_OK on success + */ +esp_err_t WebSocket_Handler_Register(httpd_handle_t p_ServerHandle); + +/** @brief Get the number of connected WebSocket clients. + * @return Number of connected clients + */ +uint8_t WebSocket_Handler_GetClientCount(void); + +/** @brief Check if there are any connected clients. + * @return true if at least one client is connected + */ +bool WebSocket_Handler_HasClients(void); + +/** @brief Set thermal frame data for streaming. + * @param p_Frame Pointer to thermal frame data + */ +void WebSocket_Handler_SetThermalFrame(Network_Thermal_Frame_t *p_Frame); + +/** @brief Signal that a new frame is ready for broadcasting (non-blocking). + * @return ESP_OK on success + */ +esp_err_t WebSocket_Handler_NotifyFrameReady(void); + +/** @brief Broadcast telemetry data to all subscribed clients. + * @return ESP_OK on success + */ +esp_err_t WebSocket_Handler_BroadcastTelemetry(void); + +/** @brief Start the WebSocket broadcast task. + * @return ESP_OK on success + */ +esp_err_t WebSocket_Handler_StartTask(void); + +/** @brief Stop the WebSocket broadcast task. + * @param Timeout_ms Timeout in milliseconds to wait for task to stop (default: 2000ms) + */ +void WebSocket_Handler_StopTask(uint32_t Timeout_ms = 2000); + +/** @brief Send ping to all connected clients. + * @return ESP_OK on success. + */ +esp_err_t WebSocket_Handler_PingAll(void); + +#endif /* WEBSOCKET_HANDLER_H_ */ diff --git a/main/Application/Manager/Network/VISA/CMakeLists.txt b/main/Application/Manager/Network/VISA/CMakeLists.txt new file mode 100644 index 0000000..e871406 --- /dev/null +++ b/main/Application/Manager/Network/VISA/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + SRCS "visa_server.cpp" "visa_commands.cpp" + INCLUDE_DIRS "." + REQUIRES lwip freertos esp_timer +) diff --git a/main/Application/Manager/Network/VISA/README.md b/main/Application/Manager/Network/VISA/README.md new file mode 100644 index 0000000..5fcbfb8 --- /dev/null +++ b/main/Application/Manager/Network/VISA/README.md @@ -0,0 +1,554 @@ +# PyroVision VISA Interface + +## Overview + +The VISA (Virtual Instrument Software Architecture) interface provides standardized instrument control for the PyroVision thermal camera over TCP/IP. This implementation follows SCPI (Standard Commands for Programmable Instruments) conventions and IEEE 488.2 standards, enabling integration with test automation systems like LabVIEW, MATLAB, or Python-VISA. + +## Features + +- **TCP/IP Communication**: Standard VISA/SCPI port 5025 +- **IEEE 488.2 Compliance**: Mandatory common commands implemented +- **SCPI Command Structure**: Hierarchical command tree with queries +- **Binary Data Transfer**: IEEE 488.2 definite length arbitrary block format +- **Error Management**: SCPI error queue with standard error codes +- **Thermal Camera Control**: Device-specific commands for imaging +- **Multiple Clients**: Support for up to 4 concurrent connections + +## Network Configuration + +- **Default Port**: 5025 (configurable in `visa_server.h`) +- **Protocol**: TCP/IP +- **Encoding**: ASCII text for commands, binary for image data +- **Termination**: Commands terminated with newline (`\n`) +- **Timeout**: 5000 ms (configurable) + +## Command Reference + +### IEEE 488.2 Common Commands + +All commands are case-insensitive. Long form and short form are both supported (e.g., `SYSTem` or `SYST`). + +#### `*IDN?` - Identification Query + +Returns device identification string. + +**Response Format**: `Manufacturer,Model,SerialNumber,FirmwareVersion` + +**Example**: + +```sh +*IDN? +PyroVision,ThermalCam-ESP32,0000001,1.0.0 +``` + +#### `*RST` - Reset + +Resets the device to default state. + +**Example**: + +```sh +*RST +``` + +#### `*CLS` - Clear Status + +Clears the status data structures and error queue. + +**Example**: + +```sh +*CLS +``` + +#### `*OPC?` - Operation Complete Query + +Returns 1 when all pending operations are complete. + +**Response**: `1` or `0` + +**Example**: + +```sh +*OPC? +1 +``` + +#### `*TST?` - Self-Test Query + +Performs device self-test. Returns 0 for pass, non-zero for failure. + +**Example**: + +```sh +*TST? +0 +``` + +### SCPI System Commands + +#### `SYSTem:ERRor?` - Error Query + +Returns the oldest error from the error queue. + +**Response Format**: `ErrorCode,"ErrorMessage"` + +**Example**: + +```sh +SYST:ERR? +0,"No error" +``` + +#### `SYSTem:VERSion?` - SCPI Version Query + +Returns the SCPI version supported. + +**Response**: `1999.0` (SCPI-99) + +**Example**: + +```sh +SYST:VERS? +1999.0 +``` + +### Sensor Commands + +#### `SENSe:TEMPerature?` - Temperature Query + +Returns the thermal sensor temperature in Celsius. + +**Response**: Floating point temperature value + +**Example**: + +```sh +SENS:TEMP? +25.50 +``` + +#### `SENSe:IMAGE:CAPTure` - Capture Image + +Triggers image capture. Operation completes asynchronously. + +**Example**: + +```sh +SENS:IMG:CAPT +``` + +#### `SENSe:IMAGE:DATA?` - Image Data Query + +Returns the captured image in binary format using IEEE 488.2 definite length arbitrary block format. + +**Response Format**: `#` where: + +- `n` = number of digits in length +- `length` = byte count of data +- `data` = binary image data + +**Example**: + +```sh +SENS:IMG:DATA? +#41024 +``` + +(Header `#41024` means 4 digits, 1024 bytes of data follows) + +#### `SENSe:IMAGE:FORMat {JPEG|PNG|RAW}` - Set Image Format + +Sets the format for captured images. + +**Parameters**: + +- `JPEG`: JPEG compressed format +- `PNG`: PNG compressed format +- `RAW`: Raw thermal data (16-bit) + +**Example**: + +```sh +SENS:IMG:FORM JPEG +``` + +#### `SENSe:IMAGE:PALette {IRON|GRAY|RAINBOW}` - Set Color Palette + +Sets the color palette for thermal image visualization. + +**Parameters**: + +- `IRON`: Ironbow palette (thermal imaging standard) +- `GRAY`: Grayscale palette +- `RAINBOW`: Rainbow palette + +**Example**: + +```sh +SENS:IMG:PAL IRON +``` + +### Display Commands + +#### `DISPlay:LED:STATe {ON|OFF|BLINK}` - LED Control + +Controls the status LED. + +**Parameters**: + +- `ON`: LED continuously on +- `OFF`: LED off +- `BLINK`: LED blinking + +**Example**: + +```sh +DISP:LED:STAT ON +``` + +#### `DISPlay:LED:BRIGhtness <0-255>` - LED Brightness + +Sets the LED brightness level. + +**Parameters**: Integer value 0-255 (0=off, 255=maximum) + +**Example**: + +```sh +DISP:LED:BRIG 128 +``` + +## Error Codes + +Standard SCPI error codes are used: + +| Code | Description | +|------|-------------| +| 0 | No error | +| -100 | Command error | +| -101 | Invalid character | +| -102 | Syntax error | +| -103 | Invalid separator | +| -104 | Data type error | +| -108 | Parameter not allowed | +| -109 | Missing parameter | +| -110 | Command header error | +| -113 | Undefined header | +| -200 | Execution error | +| -222 | Data out of range | +| -240 | Hardware error | +| -241 | Hardware missing | +| -300 | System error | +| -350 | Out of memory | +| -400 | Query error | + +## Usage Examples + +### Python with PyVISA + +```python +import pyvisa + +rm = pyvisa.ResourceManager() +# Connect to PyroVision camera +camera = rm.open_resource('TCPIP::192.168.4.1::5025::SOCKET') +camera.read_termination = '\n' +camera.write_termination = '\n' + +# Identify device +idn = camera.query('*IDN?') +print(f"Connected to: {idn}") + +# Set image format +camera.write('SENS:IMG:FORM JPEG') + +# Set color palette +camera.write('SENS:IMG:PAL IRON') + +# Capture image +camera.write('SENS:IMG:CAPT') + +# Wait for operation complete +while camera.query('*OPC?') != '1': + time.sleep(0.1) + +# Get image data (binary) +camera.write('SENS:IMG:DATA?') +image_data = camera.read_raw() + +# Parse IEEE 488.2 block format +# Skip header (#) +header_start = image_data.find(b'#') +n = int(chr(image_data[header_start + 1])) +length = int(image_data[header_start + 2:header_start + 2 + n]) +data = image_data[header_start + 2 + n:header_start + 2 + n + length] + +# Save image +with open('thermal_image.jpg', 'wb') as f: + f.write(data) + +# Check for errors +error = camera.query('SYST:ERR?') +print(f"Error status: {error}") + +camera.close() +``` + +### Python with Sockets + +```python +import socket +import time + +# Connect to camera +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.connect(('192.168.4.1', 5025)) +sock.settimeout(5.0) + +def send_command(sock, command): + sock.sendall((command + '\n').encode()) + +def read_response(sock): + data = b'' + while True: + chunk = sock.recv(1024) + data += chunk + if b'\n' in chunk: + break + return data.decode().strip() + +# Identify device +send_command(sock, '*IDN?') +response = read_response(sock) +print(f"Device: {response}") + +# Get temperature +send_command(sock, 'SENS:TEMP?') +temp = read_response(sock) +print(f"Temperature: {temp}°C") + +# Control LED +send_command(sock, 'DISP:LED:STAT BLINK') +send_command(sock, 'DISP:LED:BRIG 200') + +sock.close() +``` + +### MATLAB + +```matlab +% Connect to camera +t = tcpclient('192.168.4.1', 5025); +configureTerminator(t, 'LF'); + +% Identify device +writeline(t, '*IDN?'); +idn = readline(t); +disp(['Connected to: ', idn]); + +% Get temperature +writeline(t, 'SENS:TEMP?'); +temp = str2double(readline(t)); +fprintf('Temperature: %.2f°C\n', temp); + +% Capture image +writeline(t, 'SENS:IMG:CAPT'); + +% Wait for completion +writeline(t, '*OPC?'); +while str2double(readline(t)) ~= 1 + pause(0.1); +end + +% Get image data +writeline(t, 'SENS:IMG:DATA?'); +data = read(t); + +% Parse IEEE 488.2 block format +header_idx = find(data == uint8('#'), 1); +n = data(header_idx + 1) - uint8('0'); +length = str2double(char(data(header_idx + 2:header_idx + 1 + n))); +img_data = data(header_idx + 2 + n:header_idx + 1 + n + length); + +% Save image +fid = fopen('thermal_image.jpg', 'wb'); +fwrite(fid, img_data, 'uint8'); +fclose(fid); + +clear t; +``` + +### LabVIEW + +1. Use **VISA TCP/IP Resource** with format: `TCPIP::192.168.4.1::5025::SOCKET` +2. Use **VISA Write** to send commands +3. Use **VISA Read** to receive responses +4. Set termination character to `\n` (0x0A) +5. For binary data, use **VISA Read** in binary mode + +## Integration with Firmware + +To integrate the VISA server with your application: + +### 1. Include Headers + +```cpp +#include "Manager/Network/VISA/visa_server.h" +``` + +### 2. Initialize Server + +```cpp +// During application initialization +esp_err_t err = VISA_Server_Init(); +if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize VISA server"); +} +``` + +### 3. Start Server + +```cpp +// After network is connected +err = VISA_Server_Start(); +if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start VISA server"); +} +``` + +### 4. Stop Server (if needed) + +```cpp +// Before shutdown or network disconnect +VISA_Server_Stop(); +``` + +### 5. Deinitialize + +```cpp +// During application cleanup +VISA_Server_Deinit(); +``` + +### CMake Integration + +Add to your main component's `CMakeLists.txt`: + +```cmake +idf_component_register( + SRCS "main.cpp" ... + INCLUDE_DIRS "." ... + REQUIRES ... visa_interface +) +``` + +## Customization + +### Adding New Commands + +1. Define command handler in `visa_commands.cpp`: + +```cpp +static int VISA_CMD_MY_COMMAND(char *Response, size_t MaxLen) +{ + // Implement command logic + return snprintf(Response, MaxLen, "Result\n"); +} +``` + +2. Add command to parser in `VISA_Commands_Execute()`: + +```cpp +else if (strcasecmp(tokens[0], "MYCommand") == 0) { + return VISA_CMD_MY_COMMAND(Response, MaxLen); +} +``` + +### Modifying Port + +Edit `VISA_SERVER_PORT` in `visa_server.h`: + +```cpp +#define VISA_SERVER_PORT 5555 // Custom port +``` + +### Adjusting Timeouts + +Edit `VISA_SOCKET_TIMEOUT_MS` in `visa_server.h`: + +```cpp +#define VISA_SOCKET_TIMEOUT_MS 10000 // 10 seconds +``` + +## Troubleshooting + +### Cannot Connect + +- Verify network connectivity: `ping 192.168.4.1` +- Check firewall settings +- Confirm server is running: Check logs for "VISA server listening" +- Verify correct port (default: 5025) + +### Commands Not Responding + +- Ensure commands are terminated with newline `\n` +- Check command syntax (case-insensitive) +- Query error queue: `SYST:ERR?` +- Enable debug logs in `visa_server.cpp` and `visa_commands.cpp` + +### Binary Data Issues + +- Verify IEEE 488.2 block format parsing +- Check data length matches header +- Use binary read mode, not text mode +- Ensure sufficient buffer size + +### Performance Optimization + +- Reduce `VISA_SOCKET_TIMEOUT_MS` for faster response +- Increase task stack size if needed +- Use binary format for large data transfers +- Consider caching frequently requested data + +## Protocol Specification + +### Command Format + +```sh +
[][\n] +``` + +- Header: Hierarchical command path separated by colons +- Parameter: Optional command argument +- Terminator: Newline character (0x0A) + +### Query Format + +```sh +
?[\n] +``` + +- Query: Header followed by question mark + +### Response Format + +```sh +[\n] +``` + +- Text responses terminated with newline +- Binary data uses IEEE 488.2 block format + +### IEEE 488.2 Block Format + +```sh +# +``` + +- `#`: Start marker +- `n`: Single digit, number of digits in length +- `length`: ASCII decimal length value +- `data`: Binary data bytes + +**Example**: `#41024<1024 bytes>` means 4 digits, 1024 bytes follow diff --git a/main/Application/Manager/Network/VISA/visa_commands.cpp b/main/Application/Manager/Network/VISA/visa_commands.cpp new file mode 100644 index 0000000..35dab89 --- /dev/null +++ b/main/Application/Manager/Network/VISA/visa_commands.cpp @@ -0,0 +1,510 @@ +/* + * visa_commands.cpp + * + * Copyright (C) 2026 + * This file is part of PyroVision. + * + * PyroVision is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PyroVision is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PyroVision. If not, see . + * + * File info: VISA/SCPI command handler implementation. + */ + +#include +#include +#include +#include + +#include +#include + +#include "visa_commands.h" + +#include "sdkconfig.h" + +/** @brief Error queue */ +#define ERROR_QUEUE_SIZE 10 + +static int _error_queue[ERROR_QUEUE_SIZE]; +static size_t _error_count = 0; + +/** @brief Operation complete flag */ +static bool _operation_complete = true; + +static const char *TAG = "VISA-Commands"; + +/** @brief Push error to queue + * @param Error Error code + */ +static void VISA_PushError(int Error) +{ + if (_error_count < ERROR_QUEUE_SIZE) { + _error_queue[_error_count++] = Error; + } +} + +/** @brief Check if string is a query (ends with ?) + * @param Command Command string + * @return true if query, false otherwise + */ +static bool VISA_IsQuery(const char *Command) +{ + size_t len = strlen(Command); + return ((len > 0) && (Command[len - 1] == '?')); +} + +/** @brief Parse command into tokens + * @param Command Command string + * @param Tokens Array to store tokens + * @param MaxTokens Maximum number of tokens + * @return Number of tokens parsed + */ +static int VISA_ParseCommand(char *Command, char **Tokens, int MaxTokens) +{ + int count = 0; + char *token = strtok(Command, " \t:"); + + while ((token != NULL) && (count < MaxTokens)) { + Tokens[count++] = token; + token = strtok(NULL, " \t:"); + } + + return count; +} + +/* ===== IEEE 488.2 Common Commands ===== */ + +/** @brief *IDN? - Identification query + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_IDN(char *Response, size_t MaxLen) +{ + return snprintf(Response, MaxLen, "%s,%s,%s,%u.%u.%u\n", + CONFIG_NETWORK_VISA_DEVICE_MANUFACTURER, + CONFIG_NETWORK_VISA_DEVICE_MODEL, + CONFIG_NETWORK_VISA_DEVICE_SERIAL, + PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, PYROVISION_VERSION_BUILD); +} + +/** @brief *RST - Reset device + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_RST(char *Response, size_t MaxLen) +{ + ESP_LOGI(TAG, "Device reset requested"); + + /* TODO: Implement actual reset logic */ + // Reset managers to default state + + _operation_complete = true; + return 0; /* No response for command */ +} + +/** @brief *CLS - Clear status + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_CLS(char *Response, size_t MaxLen) +{ + VISA_Commands_ClearErrors(); + _operation_complete = true; + return 0; /* No response */ +} + +/** @brief *OPC? - Operation complete query + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_OPC(char *Response, size_t MaxLen) +{ + return snprintf(Response, MaxLen, "%d\n", _operation_complete ? 1 : 0); +} + +/** @brief *TST? - Self-test query + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_TST(char *Response, size_t MaxLen) +{ + /* Perform basic self-test */ + /* 0 = pass, non-zero = fail */ + int result = 0; + + /* TODO: Implement actual self-test */ + // Check camera connection + // Check display + // Check memory + + return snprintf(Response, MaxLen, "%d\n", result); +} + +/** @brief SYSTem:ERRor? - Get error from queue + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_SYST_ERR(char *Response, size_t MaxLen) +{ + int error = VISA_Commands_GetError(); + + if (error == SCPI_ERROR_NO_ERROR) { + return snprintf(Response, MaxLen, "0,\"No error\"\n"); + } else { + return snprintf(Response, MaxLen, "%d,\"Error %d\"\n", error, error); + } +} + +/** @brief SYSTem:VERSion? - Get SCPI version + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_SYST_VERS(char *Response, size_t MaxLen) +{ + return snprintf(Response, MaxLen, "1999.0\n"); /* SCPI-99 */ +} + +/* ===== Device-Specific Commands ===== */ + +/** @brief SENSe:TEMPerature? - Get sensor temperature + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_SENS_TEMP(char *Response, size_t MaxLen) +{ + /* TODO: Get actual temperature from Lepton manager */ + float temperature = 25.5f; /* Placeholder */ + + return snprintf(Response, MaxLen, "%.2f\n", temperature); +} + +/** @brief SENSe:IMAGE:CAPTure - Capture image + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_SENS_IMG_CAPT(char *Response, size_t MaxLen) +{ + /* TODO: Trigger image capture */ + ESP_LOGI(TAG, "Image capture triggered"); + + _operation_complete = false; + /* Capture happens asynchronously */ + /* Set _operation_complete = true when done */ + + return 0; /* No immediate response */ +} + +/** @brief SENSe:IMAGE:DATA? - Get captured image data + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative for binary data + */ +static int VISA_CMD_SENS_IMG_DATA(char *Response, size_t MaxLen) +{ + /* TODO: Get actual image data */ + /* This should return binary data in IEEE 488.2 format */ + /* Format: # where n = digits in length */ + + /* Example with dummy data */ + uint8_t *image_data = (uint8_t *)malloc(1024); + if (image_data == NULL) { + VISA_PushError(SCPI_ERROR_OUT_OF_MEMORY); + return SCPI_ERROR_OUT_OF_MEMORY; + } + + size_t image_size = 1024; /* Placeholder */ + memset(image_data, 0xAA, image_size); /* Dummy data */ + + /* Format binary block header */ + char header[32]; + int digits = snprintf(header, sizeof(header), "%zu", image_size); + int header_len = snprintf(Response, MaxLen, "#%d%zu", digits, image_size); + + /* Copy image data after header */ + if ((header_len + image_size) < MaxLen) { + memcpy(Response + header_len, image_data, image_size); + free(image_data); + return header_len + image_size; + } + + free(image_data); + VISA_PushError(SCPI_ERROR_OUT_OF_MEMORY); + return SCPI_ERROR_OUT_OF_MEMORY; +} + +/** @brief SENSe:IMAGE:FORMat - Set image format + * @param Tokens Command tokens + * @param Count Token count + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_SENS_IMG_FORM(char **Tokens, int Count, char *Response, size_t MaxLen) +{ + if (Count < 4) { + VISA_PushError(SCPI_ERROR_MISSING_PARAMETER); + return SCPI_ERROR_MISSING_PARAMETER; + } + + const char *format = Tokens[3]; + + ESP_LOGI(TAG, "Set image format: %s", format); + + /* TODO: Set actual format */ + /* Valid: JPEG, PNG, RAW */ + + if ((strcasecmp(format, "JPEG") == 0) || + (strcasecmp(format, "PNG") == 0) || + (strcasecmp(format, "RAW") == 0)) { + return 0; /* Success */ + } else { + VISA_PushError(SCPI_ERROR_DATA_OUT_OF_RANGE); + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } +} + +/** @brief SENSe:IMAGE:PALette - Set color palette + * @param Tokens Command tokens + * @param Count Token count + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_SENS_IMG_PAL(char **Tokens, int Count, char *Response, size_t MaxLen) +{ + if (Count < 4) { + VISA_PushError(SCPI_ERROR_MISSING_PARAMETER); + return SCPI_ERROR_MISSING_PARAMETER; + } + + const char *palette = Tokens[3]; + + ESP_LOGI(TAG, "Set palette: %s", palette); + + /* TODO: Set actual palette */ + /* Valid: IRON, GRAY, RAINBOW */ + + if ((strcasecmp(palette, "IRON") == 0) || + (strcasecmp(palette, "GRAY") == 0) || + (strcasecmp(palette, "RAINBOW") == 0)) { + return 0; /* Success */ + } else { + VISA_PushError(SCPI_ERROR_DATA_OUT_OF_RANGE); + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } +} + +/** @brief DISPlay:LED:STATe - Set LED state + * @param Tokens Command tokens + * @param Count Token count + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_DISP_LED_STAT(char **Tokens, int Count, char *Response, size_t MaxLen) +{ + if (Count < 4) { + VISA_PushError(SCPI_ERROR_MISSING_PARAMETER); + return SCPI_ERROR_MISSING_PARAMETER; + } + + const char *state = Tokens[3]; + + ESP_LOGI(TAG, "Set LED state: %s", state); + + /* TODO: Control actual LED */ + /* Valid: ON, OFF, BLINK */ + + if ((strcasecmp(state, "ON") == 0) || + (strcasecmp(state, "OFF") == 0) || + (strcasecmp(state, "BLINK") == 0)) { + return 0; /* Success */ + } else { + VISA_PushError(SCPI_ERROR_DATA_OUT_OF_RANGE); + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } +} + +/** @brief DISPlay:LED:BRIGhtness - Set LED brightness + * @param Tokens Command tokens + * @param Count Token count + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length + */ +static int VISA_CMD_DISP_LED_BRIG(char **Tokens, int Count, char *Response, size_t MaxLen) +{ + if (Count < 4) { + VISA_PushError(SCPI_ERROR_MISSING_PARAMETER); + return SCPI_ERROR_MISSING_PARAMETER; + } + + int brightness = atoi(Tokens[3]); + + if ((brightness < 0) || (brightness > 255)) { + VISA_PushError(SCPI_ERROR_DATA_OUT_OF_RANGE); + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + ESP_LOGI(TAG, "Set LED brightness: %d", brightness); + + /* TODO: Set actual LED brightness */ + + return 0; /* Success */ +} + +esp_err_t VISA_Commands_Init(void) +{ + VISA_Commands_ClearErrors(); + _operation_complete = true; + + ESP_LOGI(TAG, "VISA command handler initialized"); + return ESP_OK; +} + +esp_err_t VISA_Commands_Deinit(void) +{ + VISA_Commands_ClearErrors(); + + ESP_LOGI(TAG, "VISA command handler deinitialized"); + return ESP_OK; +} + +int VISA_Commands_Execute(const char *Command, char *Response, size_t MaxLen) +{ + if ((Command == NULL) || (Response == NULL)) { + return SCPI_ERROR_COMMAND_ERROR; + } + + /* Make a copy for parsing */ + char cmd_copy[256]; + strncpy(cmd_copy, Command, sizeof(cmd_copy) - 1); + cmd_copy[sizeof(cmd_copy) - 1] = '\0'; + + /* Convert to uppercase for comparison */ + char *tokens[16]; + int token_count = VISA_ParseCommand(cmd_copy, tokens, 16); + + if (token_count == 0) { + VISA_PushError(SCPI_ERROR_COMMAND_ERROR); + return SCPI_ERROR_COMMAND_ERROR; + } + + /* Check for queries */ + bool is_query = VISA_IsQuery(tokens[token_count - 1]); + + /* Remove ? from last token if query */ + if (is_query) { + size_t len = strlen(tokens[token_count - 1]); + if (len > 0) { + tokens[token_count - 1][len - 1] = '\0'; + } + } + + /* IEEE 488.2 Common Commands */ + if (strcmp(tokens[0], "*IDN") == 0) { + if (is_query) { + return VISA_CMD_IDN(Response, MaxLen); + } + } else if (strcmp(tokens[0], "*RST") == 0) { + return VISA_CMD_RST(Response, MaxLen); + } else if (strcmp(tokens[0], "*CLS") == 0) { + return VISA_CMD_CLS(Response, MaxLen); + } else if (strcmp(tokens[0], "*OPC") == 0) { + if (is_query) { + return VISA_CMD_OPC(Response, MaxLen); + } + } else if (strcmp(tokens[0], "*TST") == 0) { + if (is_query) { + return VISA_CMD_TST(Response, MaxLen); + } + } + /* SCPI System Commands */ + else if ((strcasecmp(tokens[0], "SYST") == 0) || (strcasecmp(tokens[0], "SYSTem") == 0)) { + if ((token_count >= 2) && (strcasecmp(tokens[1], "ERR") == 0 || strcasecmp(tokens[1], "ERRor") == 0)) { + if (is_query) { + return VISA_CMD_SYST_ERR(Response, MaxLen); + } + } else if ((token_count >= 2) && (strcasecmp(tokens[1], "VERS") == 0 || strcasecmp(tokens[1], "VERSion") == 0)) { + if (is_query) { + return VISA_CMD_SYST_VERS(Response, MaxLen); + } + } + } + /* Device-Specific Commands - SENSe */ + else if ((strcasecmp(tokens[0], "SENS") == 0) || (strcasecmp(tokens[0], "SENSe") == 0)) { + if ((token_count >= 2) && (strcasecmp(tokens[1], "TEMP") == 0 || strcasecmp(tokens[1], "TEMPerature") == 0)) { + if (is_query) { + return VISA_CMD_SENS_TEMP(Response, MaxLen); + } + } else if ((token_count >= 2) && (strcasecmp(tokens[1], "IMG") == 0 || strcasecmp(tokens[1], "IMAGE") == 0)) { + if ((token_count >= 3) && (strcasecmp(tokens[2], "CAPT") == 0 || strcasecmp(tokens[2], "CAPTure") == 0)) { + return VISA_CMD_SENS_IMG_CAPT(Response, MaxLen); + } else if ((token_count >= 3) && (strcasecmp(tokens[2], "DATA") == 0)) { + if (is_query) { + return VISA_CMD_SENS_IMG_DATA(Response, MaxLen); + } + } else if ((token_count >= 3) && (strcasecmp(tokens[2], "FORM") == 0 || strcasecmp(tokens[2], "FORMat") == 0)) { + return VISA_CMD_SENS_IMG_FORM(tokens, token_count, Response, MaxLen); + } else if ((token_count >= 3) && (strcasecmp(tokens[2], "PAL") == 0 || strcasecmp(tokens[2], "PALette") == 0)) { + return VISA_CMD_SENS_IMG_PAL(tokens, token_count, Response, MaxLen); + } + } + } + /* Device-Specific Commands - DISPlay */ + else if ((strcasecmp(tokens[0], "DISP") == 0) || (strcasecmp(tokens[0], "DISPlay") == 0)) { + if ((token_count >= 2) && (strcasecmp(tokens[1], "LED") == 0)) { + if ((token_count >= 3) && (strcasecmp(tokens[2], "STAT") == 0 || strcasecmp(tokens[2], "STATe") == 0)) { + return VISA_CMD_DISP_LED_STAT(tokens, token_count, Response, MaxLen); + } else if ((token_count >= 3) && (strcasecmp(tokens[2], "BRIG") == 0 || strcasecmp(tokens[2], "BRIGhtness") == 0)) { + return VISA_CMD_DISP_LED_BRIG(tokens, token_count, Response, MaxLen); + } + } + } + + /* Command not found */ + VISA_PushError(SCPI_ERROR_UNDEFINED_HEADER); + return SCPI_ERROR_UNDEFINED_HEADER; +} + +int VISA_Commands_GetError(void) +{ + if (_error_count > 0) { + int error = _error_queue[0]; + + /* Shift queue */ + for (size_t i = 1; i < _error_count; i++) { + _error_queue[i - 1] = _error_queue[i]; + } + _error_count--; + + return error; + } + + return SCPI_ERROR_NO_ERROR; +} + +void VISA_Commands_ClearErrors(void) +{ + _error_count = 0; + memset(_error_queue, 0, sizeof(_error_queue)); +} diff --git a/main/Application/Manager/Network/VISA/visa_commands.h b/main/Application/Manager/Network/VISA/visa_commands.h new file mode 100644 index 0000000..91b14de --- /dev/null +++ b/main/Application/Manager/Network/VISA/visa_commands.h @@ -0,0 +1,76 @@ +/* + * visa_commands.h + * + * Copyright (C) 2026 + * This file is part of PyroVision. + * + * PyroVision is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PyroVision is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PyroVision. If not, see . + * + * File info: VISA/SCPI command handler for PyroVision thermal camera. + */ + +#ifndef VISA_COMMANDS_H_ +#define VISA_COMMANDS_H_ + +#include + +#include + +/** @brief Standard SCPI error codes */ +#define SCPI_ERROR_NO_ERROR 0 /**< No error */ +#define SCPI_ERROR_COMMAND_ERROR -100 /**< Command error */ +#define SCPI_ERROR_INVALID_CHARACTER -101 /**< Invalid character */ +#define SCPI_ERROR_SYNTAX_ERROR -102 /**< Syntax error */ +#define SCPI_ERROR_INVALID_SEPARATOR -103 /**< Invalid separator */ +#define SCPI_ERROR_DATA_TYPE_ERROR -104 /**< Data type error */ +#define SCPI_ERROR_PARAMETER_NOT_ALLOWED -108 /**< Parameter not allowed */ +#define SCPI_ERROR_MISSING_PARAMETER -109 /**< Missing parameter */ +#define SCPI_ERROR_COMMAND_HEADER_ERROR -110 /**< Command header error */ +#define SCPI_ERROR_UNDEFINED_HEADER -113 /**< Undefined header */ +#define SCPI_ERROR_EXECUTION_ERROR -200 /**< Execution error */ +#define SCPI_ERROR_DATA_OUT_OF_RANGE -222 /**< Data out of range */ +#define SCPI_ERROR_HARDWARE_MISSING -241 /**< Hardware missing */ +#define SCPI_ERROR_HARDWARE_ERROR -240 /**< Hardware error */ +#define SCPI_ERROR_SYSTEM_ERROR -300 /**< System error */ +#define SCPI_ERROR_OUT_OF_MEMORY -350 /**< Out of memory */ +#define SCPI_ERROR_QUERY_ERROR -400 /**< Query error */ + +/** @brief Initialize command handler + * @return ESP_OK on success, error code otherwise + */ +esp_err_t VISA_Commands_Init(void); + +/** @brief Deinitialize command handler + * @return ESP_OK on success, error code otherwise + */ +esp_err_t VISA_Commands_Deinit(void); + +/** @brief Execute VISA/SCPI command + * @param Command Command string + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or error code + */ +int VISA_Commands_Execute(const char *Command, char *Response, size_t MaxLen); + +/** @brief Get last error from error queue + * @return Error code + */ +int VISA_Commands_GetError(void); + +/** @brief Clear error queue + */ +void VISA_Commands_ClearErrors(void); + +#endif /* VISA_COMMANDS_H_ */ diff --git a/main/Application/Manager/Network/VISA/visa_server.cpp b/main/Application/Manager/Network/VISA/visa_server.cpp new file mode 100644 index 0000000..057f2af --- /dev/null +++ b/main/Application/Manager/Network/VISA/visa_server.cpp @@ -0,0 +1,339 @@ +/* + * visa_server.cpp + * + * Copyright (C) 2026 + * This file is part of PyroVision. + * + * PyroVision is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PyroVision is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PyroVision. If not, see . + * + * File info: VISA (Virtual Instrument Software Architecture) TCP server implementation. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "visa_server.h" +#include "visa_commands.h" + +static const char *TAG = "VISA-Server"; + +/** @brief VISA server state */ +typedef struct { + int ListenSocket; /**< Listening socket */ + TaskHandle_t ServerTask; /**< Server task handle */ + bool isRunning; /**< Server running flag */ + bool isInitialized; /**< Initialization flag */ + SemaphoreHandle_t Mutex; /**< Thread safety mutex */ +} VISA_Server_State_t; + +static VISA_Server_State_t _VISA_Server_State = {0}; + +/** @brief Process VISA command and generate response + * @param Command Received command string + * @param Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or error code + */ +static int VISA_ProcessCommand(const char *Command, char *Response, size_t MaxLen) +{ + if ((Command == NULL) || (Response == NULL)) { + return VISA_ERR_INVALID_ARG; + } + + ESP_LOGD(TAG, "Processing command: %s", Command); + + /* Remove trailing newline/carriage return */ + char cmd_buffer[VISA_MAX_COMMAND_LENGTH]; + strncpy(cmd_buffer, Command, sizeof(cmd_buffer) - 1); + cmd_buffer[sizeof(cmd_buffer) - 1] = '\0'; + + size_t len = strlen(cmd_buffer); + while ((len > 0) && ((cmd_buffer[len - 1] == '\n') || (cmd_buffer[len - 1] == '\r'))) { + cmd_buffer[--len] = '\0'; + } + + /* Process command */ + return VISA_Commands_Execute(cmd_buffer, Response, MaxLen); +} + +/** @brief Handle client connection + * @param ClientSocket Client socket descriptor + */ +static void VISA_HandleClient(int ClientSocket) +{ + char rx_buffer[VISA_MAX_COMMAND_LENGTH]; + char tx_buffer[VISA_MAX_RESPONSE_LENGTH]; + struct timeval timeout; + + timeout.tv_sec = VISA_SOCKET_TIMEOUT_MS / 1000; + timeout.tv_usec = (VISA_SOCKET_TIMEOUT_MS % 1000) * 1000; + + setsockopt(ClientSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + setsockopt(ClientSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + + ESP_LOGI(TAG, "Client connected"); + + while (_VISA_Server_State.isRunning) { + memset(rx_buffer, 0, sizeof(rx_buffer)); + + int len = recv(ClientSocket, rx_buffer, sizeof(rx_buffer) - 1, 0); + + if (len < 0) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + /* Timeout, continue */ + continue; + } + ESP_LOGE(TAG, "recv failed: errno %d", errno); + break; + } else if (len == 0) { + ESP_LOGI(TAG, "Client disconnected"); + break; + } + + rx_buffer[len] = '\0'; + ESP_LOGD(TAG, "Received: %s", rx_buffer); + + /* Process command */ + memset(tx_buffer, 0, sizeof(tx_buffer)); + int response_len = VISA_ProcessCommand(rx_buffer, tx_buffer, sizeof(tx_buffer)); + + if (response_len > 0) { + /* Send response */ + int sent = send(ClientSocket, tx_buffer, response_len, 0); + if (sent < 0) { + ESP_LOGE(TAG, "send failed: errno %d", errno); + break; + } + ESP_LOGD(TAG, "Sent %d bytes", sent); + } else if (response_len < 0) { + /* Error response */ + snprintf(tx_buffer, sizeof(tx_buffer), "ERROR: %d\n", response_len); + send(ClientSocket, tx_buffer, strlen(tx_buffer), 0); + } + } + + close(ClientSocket); + ESP_LOGI(TAG, "Client connection closed"); +} + +/** @brief VISA server task + * @param p_Args Task arguments (unused) + */ +static void VISA_ServerTask(void *p_Args) +{ + struct sockaddr_in dest_addr; + + dest_addr.sin_addr.s_addr = htonl(INADDR_ANY); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(VISA_SERVER_PORT); + + _VISA_Server_State.ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (_VISA_Server_State.ListenSocket < 0) { + ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); + _VISA_Server_State.isRunning = false; + vTaskDelete(NULL); + return; + } + + int opt = 1; + setsockopt(_VISA_Server_State.ListenSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + int err = bind(_VISA_Server_State.ListenSocket, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); + if (err != 0) { + ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); + close(_VISA_Server_State.ListenSocket); + _VISA_Server_State.isRunning = false; + vTaskDelete(NULL); + return; + } + + err = listen(_VISA_Server_State.ListenSocket, VISA_MAX_CLIENTS); + if (err != 0) { + ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno); + close(_VISA_Server_State.ListenSocket); + _VISA_Server_State.isRunning = false; + vTaskDelete(NULL); + return; + } + + ESP_LOGI(TAG, "VISA server listening on port %d", VISA_SERVER_PORT); + + while (_VISA_Server_State.isRunning) { + struct sockaddr_in source_addr; + socklen_t addr_len = sizeof(source_addr); + + int client_socket = accept(_VISA_Server_State.ListenSocket, (struct sockaddr *)&source_addr, &addr_len); + + if (client_socket < 0) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + continue; + } + + ESP_LOGE(TAG, "Unable to accept connection: errno %d!", errno); + + break; + } + + char addr_str[16]; + inet_ntop(AF_INET, &source_addr.sin_addr, addr_str, sizeof(addr_str)); + ESP_LOGI(TAG, "Client connected from %s:%d", addr_str, ntohs(source_addr.sin_port)); + + /* Handle client in same task (simple single-client implementation) */ + VISA_HandleClient(client_socket); + } + + close(_VISA_Server_State.ListenSocket); + _VISA_Server_State.ListenSocket = -1; + _VISA_Server_State.isRunning = false; + + ESP_LOGI(TAG, "VISA server stopped"); + vTaskDelete(NULL); +} + +esp_err_t VISA_Server_Init(void) +{ + esp_err_t Error; + + if (_VISA_Server_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + memset(&_VISA_Server_State, 0, sizeof(_VISA_Server_State)); + + _VISA_Server_State.Mutex = xSemaphoreCreateMutex(); + if (_VISA_Server_State.Mutex == NULL) { + ESP_LOGE(TAG, "Failed to create mutex!"); + return ESP_ERR_NO_MEM; + } + + /* Initialize command handler */ + Error = VISA_Commands_Init(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize command handler: 0x%x!", Error); + vSemaphoreDelete(_VISA_Server_State.Mutex); + return Error; + } + + _VISA_Server_State.ListenSocket = -1; + _VISA_Server_State.isInitialized = true; + + ESP_LOGI(TAG, "VISA server initialized"); + + return ESP_OK; +} + +esp_err_t VISA_Server_Deinit(void) +{ + if (_VISA_Server_State.isInitialized == false) { + return ESP_OK; + } + + VISA_Server_Stop(); + + VISA_Commands_Deinit(); + + if (_VISA_Server_State.Mutex != NULL) { + vSemaphoreDelete(_VISA_Server_State.Mutex); + _VISA_Server_State.Mutex = NULL; + } + + _VISA_Server_State.isInitialized = false; + + ESP_LOGI(TAG, "VISA server deinitialized"); + + return ESP_OK; +} + +bool VISA_Server_IsRunning(void) +{ + return _VISA_Server_State.isRunning; +} + +esp_err_t VISA_Server_Start(void) +{ + if (_VISA_Server_State.isInitialized == false) { + ESP_LOGE(TAG, "Not initialized!"); + return ESP_ERR_INVALID_STATE; + } + + if (_VISA_Server_State.isRunning) { + ESP_LOGW(TAG, "Already running"); + return ESP_OK; + } + + xSemaphoreTake(_VISA_Server_State.Mutex, portMAX_DELAY); + + _VISA_Server_State.isRunning = true; + + BaseType_t result = xTaskCreate( + VISA_ServerTask, + "visa_server", + 4096, + NULL, + 5, + &_VISA_Server_State.ServerTask + ); + + if (result != pdPASS) { + ESP_LOGE(TAG, "Failed to create server task!"); + _VISA_Server_State.isRunning = false; + xSemaphoreGive(_VISA_Server_State.Mutex); + + return ESP_ERR_NO_MEM; + } + + xSemaphoreGive(_VISA_Server_State.Mutex); + + ESP_LOGI(TAG, "VISA server started"); + + return ESP_OK; +} + +esp_err_t VISA_Server_Stop(void) +{ + if (_VISA_Server_State.isRunning == false) { + return ESP_OK; + } + + xSemaphoreTake(_VISA_Server_State.Mutex, portMAX_DELAY); + + _VISA_Server_State.isRunning = false; + + if (_VISA_Server_State.ListenSocket >= 0) { + shutdown(_VISA_Server_State.ListenSocket, SHUT_RDWR); + close(_VISA_Server_State.ListenSocket); + _VISA_Server_State.ListenSocket = -1; + } + + /* Wait for task to terminate */ + if (_VISA_Server_State.ServerTask != NULL) { + vTaskDelay(pdMS_TO_TICKS(100)); + _VISA_Server_State.ServerTask = NULL; + } + + xSemaphoreGive(_VISA_Server_State.Mutex); + + ESP_LOGI(TAG, "VISA server stopped"); + + return ESP_OK; +} diff --git a/main/Application/Manager/Network/VISA/visa_server.h b/main/Application/Manager/Network/VISA/visa_server.h new file mode 100644 index 0000000..b13df07 --- /dev/null +++ b/main/Application/Manager/Network/VISA/visa_server.h @@ -0,0 +1,74 @@ +/* + * visa_server.h + * + * Copyright (C) 2026 + * This file is part of PyroVision. + * + * PyroVision is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PyroVision is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with PyroVision. If not, see . + * + * File info: VISA (Virtual Instrument Software Architecture) TCP server for PyroVision thermal camera. + */ + +#ifndef VISA_SERVER_H_ +#define VISA_SERVER_H_ + +#include +#include +#include + +/** @brief VISA server configuration */ +#define VISA_SERVER_PORT 5025 /**< Standard VISA/SCPI port */ +#define VISA_MAX_COMMAND_LENGTH 256 /**< Maximum command length */ +#define VISA_MAX_RESPONSE_LENGTH 1024 /**< Maximum response length */ +#define VISA_MAX_CLIENTS 4 /**< Maximum concurrent clients */ +#define VISA_SOCKET_TIMEOUT_MS 5000 /**< Socket timeout in milliseconds */ + +/** @brief VISA error codes */ +typedef enum { + VISA_OK = 0, /**< Operation successful */ + VISA_ERR_INVALID_ARG = -1, /**< Invalid argument */ + VISA_ERR_NO_MEM = -2, /**< Out of memory */ + VISA_ERR_SOCKET = -3, /**< Socket error */ + VISA_ERR_TIMEOUT = -4, /**< Operation timeout */ + VISA_ERR_INVALID_COMMAND = -5, /**< Invalid command */ + VISA_ERR_EXECUTION = -6, /**< Command execution error */ + VISA_ERR_NOT_INITIALIZED = -7, /**< Server not initialized */ +} VISA_Error_t; + +/** @brief Initialize VISA server + * @return VISA_OK on success, error code otherwise + */ +esp_err_t VISA_Server_Init(void); + +/** @brief Deinitialize VISA server + * @return VISA_OK on success, error code otherwise + */ +esp_err_t VISA_Server_Deinit(void); + +/** @brief Check if VISA server is running + * @return true if running, false otherwise + */ +bool VISA_Server_IsRunning(void); + +/** @brief Start VISA server + * @return VISA_OK on success, error code otherwise + */ +esp_err_t VISA_Server_Start(void); + +/** @brief Stop VISA server + * @return VISA_OK on success, error code otherwise + */ +esp_err_t VISA_Server_Stop(void); + +#endif /* VISA_SERVER_H_ */ diff --git a/main/Application/Manager/Network/networkManager.cpp b/main/Application/Manager/Network/networkManager.cpp new file mode 100644 index 0000000..67f6474 --- /dev/null +++ b/main/Application/Manager/Network/networkManager.cpp @@ -0,0 +1,774 @@ +/* + * networkManager.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Network management implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "network_types.h" +#include "Server/server.h" +#include "Provisioning/provisioning.h" + +#include "networkManager.h" + +/* Define network event base */ +ESP_EVENT_DEFINE_BASE(NETWORK_EVENTS); + +#define NVS_NAMESPACE "wifi_creds" +#define NVS_KEY_SSID "ssid" +#define NVS_KEY_PASSWORD "password" + +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 +#define WIFI_STARTED_BIT BIT2 + +typedef struct { + bool isInitialized; + Network_State_t State; + Network_WiFiMode_t mode; + esp_netif_t *STA_NetIF; + esp_netif_t *AP_NetIF; + EventGroupHandle_t EventGroup; + Network_WiFi_STA_Config_t STA_Config; + Network_WiFi_AP_Config_t AP_Config; + uint8_t RetryCount; + uint8_t Retries; + esp_netif_ip_info_t IP_Info; +} Network_Manager_State_t; + +static Network_Manager_State_t _Network_Manager_State; + +static const char *TAG = "Network Manager"; + +/** @brief WiFi event handler. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_WiFi_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + switch (ID) { + case WIFI_EVENT_STA_START: { + ESP_LOGD(TAG, "WiFi STA started"); + xEventGroupSetBits(_Network_Manager_State.EventGroup, WIFI_STARTED_BIT); + esp_wifi_connect(); + + break; + } + case WIFI_EVENT_STA_CONNECTED: { + ESP_LOGD(TAG, "Connected to AP"); + _Network_Manager_State.RetryCount = 0; + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_WIFI_CONNECTED, NULL, 0, portMAX_DELAY); + + break; + } + case WIFI_EVENT_STA_DISCONNECTED: { + wifi_event_sta_disconnected_t *Event = (wifi_event_sta_disconnected_t *)p_Data; + + /* Decode disconnect reason for better debugging */ + const char *ReasonStr = "Unknown"; + switch (Event->reason) { + case WIFI_REASON_UNSPECIFIED: + ReasonStr = "Unspecified"; + break; + case WIFI_REASON_AUTH_EXPIRE: + ReasonStr = "Auth expired"; + break; + case WIFI_REASON_AUTH_LEAVE: + ReasonStr = "Auth leave"; + break; + case WIFI_REASON_ASSOC_EXPIRE: + ReasonStr = "Assoc expired"; + break; + case WIFI_REASON_ASSOC_TOOMANY: + ReasonStr = "Too many assocs"; + break; + case WIFI_REASON_NOT_AUTHED: + ReasonStr = "Not authenticated"; + break; + case WIFI_REASON_NOT_ASSOCED: + ReasonStr = "Not associated"; + break; + case WIFI_REASON_ASSOC_LEAVE: + ReasonStr = "Assoc leave"; + break; + case WIFI_REASON_ASSOC_NOT_AUTHED: + ReasonStr = "Assoc not authed"; + break; + case WIFI_REASON_DISASSOC_PWRCAP_BAD: + ReasonStr = "Bad power capability"; + break; + case WIFI_REASON_DISASSOC_SUPCHAN_BAD: + ReasonStr = "Bad supported channels"; + break; + case WIFI_REASON_IE_INVALID: + ReasonStr = "Invalid IE"; + break; + case WIFI_REASON_MIC_FAILURE: + ReasonStr = "MIC failure"; + break; + case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: + ReasonStr = "4-way handshake timeout"; + break; + case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: + ReasonStr = "Group key update timeout"; + break; + case WIFI_REASON_IE_IN_4WAY_DIFFERS: + ReasonStr = "IE in 4-way differs"; + break; + case WIFI_REASON_GROUP_CIPHER_INVALID: + ReasonStr = "Invalid group cipher"; + break; + case WIFI_REASON_PAIRWISE_CIPHER_INVALID: + ReasonStr = "Invalid pairwise cipher"; + break; + case WIFI_REASON_AKMP_INVALID: + ReasonStr = "Invalid AKMP"; + break; + case WIFI_REASON_UNSUPP_RSN_IE_VERSION: + ReasonStr = "Unsupported RSN IE version"; + break; + case WIFI_REASON_INVALID_RSN_IE_CAP: + ReasonStr = "Invalid RSN IE cap"; + break; + case WIFI_REASON_802_1X_AUTH_FAILED: + ReasonStr = "802.1X auth failed"; + break; + case WIFI_REASON_CIPHER_SUITE_REJECTED: + ReasonStr = "Cipher suite rejected"; + break; + case WIFI_REASON_BEACON_TIMEOUT: + ReasonStr = "Beacon timeout"; + break; + case WIFI_REASON_NO_AP_FOUND: + ReasonStr = "No AP found"; + break; + case WIFI_REASON_AUTH_FAIL: + ReasonStr = "Auth failed"; + break; + case WIFI_REASON_ASSOC_FAIL: + ReasonStr = "Assoc failed"; + break; + case WIFI_REASON_HANDSHAKE_TIMEOUT: + ReasonStr = "Handshake timeout"; + break; + case WIFI_REASON_CONNECTION_FAIL: + ReasonStr = "Connection failed"; + break; + default: + break; + } + + ESP_LOGW(TAG, "Disconnected from AP, reason: %d (%s)", Event->reason, ReasonStr); + + /* Special handling for "No AP found" */ + if (Event->reason == WIFI_REASON_NO_AP_FOUND) { + ESP_LOGW(TAG, "AP '%s' not found - check SSID spelling, signal strength, or if AP is on 2.4GHz band", + _Network_Manager_State.STA_Config.ssid); + } + + _Network_Manager_State.State = NETWORK_STATE_DISCONNECTED; + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_WIFI_DISCONNECTED, p_Data, sizeof(wifi_event_sta_disconnected_t), + portMAX_DELAY); + + if (_Network_Manager_State.RetryCount < _Network_Manager_State.Retries) { + ESP_LOGD(TAG, "Retry %d/%d", _Network_Manager_State.RetryCount++, _Network_Manager_State.Retries); + + vTaskDelay(_Network_Manager_State.STA_Config.retry_interval_ms / portTICK_PERIOD_MS); + esp_wifi_connect(); + _Network_Manager_State.State = NETWORK_STATE_CONNECTING; + } else { + ESP_LOGE(TAG, "Max retries reached!"); + + xEventGroupSetBits(_Network_Manager_State.EventGroup, WIFI_FAIL_BIT); + _Network_Manager_State.State = NETWORK_STATE_ERROR; + } + + break; + } + case WIFI_EVENT_AP_START: { + ESP_LOGD(TAG, "WiFi AP started"); + _Network_Manager_State.State = NETWORK_STATE_AP_STARTED; + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STARTED, NULL, 0, portMAX_DELAY); + + break; + } + case WIFI_EVENT_AP_STOP: { + ESP_LOGD(TAG, "WiFi AP stopped"); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STOPPED, NULL, 0, portMAX_DELAY); + + break; + } + case WIFI_EVENT_AP_STACONNECTED: { + wifi_event_ap_staconnected_t *Event = (wifi_event_ap_staconnected_t *)p_Data; + Network_Event_STA_Info_t StaInfo; + ESP_LOGD(TAG, "Station " MACSTR " joined, AID=%d", MAC2STR(Event->mac), Event->aid); + memcpy(StaInfo.MAC, Event->mac, 6); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STA_CONNECTED, &StaInfo, sizeof(StaInfo), portMAX_DELAY); + + break; + } + case WIFI_EVENT_AP_STADISCONNECTED: { + wifi_event_ap_stadisconnected_t *Event = (wifi_event_ap_stadisconnected_t *)p_Data; + Network_Event_STA_Info_t StaInfo; + ESP_LOGD(TAG, "Station " MACSTR " left, AID=%d", MAC2STR(Event->mac), Event->aid); + memcpy(StaInfo.MAC, Event->mac, 6); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STA_DISCONNECTED, &StaInfo, sizeof(StaInfo), portMAX_DELAY); + + break; + } + default: { + break; + } + } +} + +/** @brief IP event handler. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_IP_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + switch (ID) { + case IP_EVENT_STA_GOT_IP: { + ip_event_got_ip_t *Event = (ip_event_got_ip_t *)p_Data; + Network_IP_Info_t IP_Data; + + ESP_LOGD(TAG, "Got IP: " IPSTR, IP2STR(&Event->ip_info.ip)); + + memcpy(&_Network_Manager_State.IP_Info, &Event->ip_info, sizeof(esp_netif_ip_info_t)); + _Network_Manager_State.State = NETWORK_STATE_CONNECTED; + + IP_Data.IP = Event->ip_info.ip.addr; + IP_Data.Netmask = Event->ip_info.netmask.addr; + IP_Data.Gateway = Event->ip_info.gw.addr; + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_WIFI_GOT_IP, &IP_Data, sizeof(IP_Data), portMAX_DELAY); + + xEventGroupSetBits(_Network_Manager_State.EventGroup, WIFI_CONNECTED_BIT); + + break; + } + case IP_EVENT_STA_LOST_IP: { + ESP_LOGW(TAG, "Lost IP address"); + memset(&_Network_Manager_State.IP_Info, 0, sizeof(esp_netif_ip_info_t)); + + break; + } + default: { + break; + } + } +} + +esp_err_t NetworkManager_Init(const Network_Config_t *p_Config) +{ + esp_err_t Error; + + if (_Network_Manager_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + if (p_Config == NULL) { + return ESP_ERR_INVALID_ARG; + } + + ESP_LOGD(TAG, "Initializing WiFi Manager"); + + /* Create event group */ + _Network_Manager_State.EventGroup = xEventGroupCreate(); + if (_Network_Manager_State.EventGroup == NULL) { + ESP_LOGE(TAG, "Failed to create event group!"); + return ESP_ERR_NO_MEM; + } + + /* Initialize TCP/IP stack */ + ESP_ERROR_CHECK(esp_netif_init()); + + /* Copy configuration */ + memcpy(&_Network_Manager_State.STA_Config, &p_Config->STA_Config, sizeof(Network_WiFi_STA_Config_t)); + memcpy(&_Network_Manager_State.AP_Config, &p_Config->AP_Config, sizeof(Network_WiFi_AP_Config_t)); + _Network_Manager_State.mode = p_Config->WiFi_Mode; + _Network_Manager_State.Retries = _Network_Manager_State.STA_Config.max_retries; + + /* Create network interfaces */ + _Network_Manager_State.STA_NetIF = esp_netif_create_default_wifi_sta(); + if (_Network_Manager_State.STA_NetIF == NULL) { + ESP_LOGE(TAG, "Failed to create STA netif!"); + vEventGroupDelete(_Network_Manager_State.EventGroup); + _Network_Manager_State.EventGroup = NULL; + + return ESP_FAIL; + } + + _Network_Manager_State.AP_NetIF = esp_netif_create_default_wifi_ap(); + if (_Network_Manager_State.AP_NetIF == NULL) { + ESP_LOGE(TAG, "Failed to create AP netif!"); + + esp_netif_destroy(_Network_Manager_State.STA_NetIF); + _Network_Manager_State.STA_NetIF = NULL; + vEventGroupDelete(_Network_Manager_State.EventGroup); + _Network_Manager_State.EventGroup = NULL; + + return ESP_FAIL; + } + + /* Initialize WiFi with default configuration */ + wifi_init_config_t WifiInitConfig = WIFI_INIT_CONFIG_DEFAULT(); + Error = esp_wifi_init(&WifiInitConfig); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to init WiFi: %d!", Error); + + esp_netif_destroy(_Network_Manager_State.AP_NetIF); + esp_netif_destroy(_Network_Manager_State.STA_NetIF); + vEventGroupDelete(_Network_Manager_State.EventGroup); + + _Network_Manager_State.AP_NetIF = NULL; + _Network_Manager_State.STA_NetIF = NULL; + _Network_Manager_State.EventGroup = NULL; + + return Error; + } + + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &on_WiFi_Event, + NULL, + NULL)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + ESP_EVENT_ANY_ID, + &on_IP_Event, + NULL, + NULL)); + + /* Set storage type */ + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + _Network_Manager_State.isInitialized = true; + _Network_Manager_State.State = NETWORK_STATE_IDLE; + + ESP_LOGD(TAG, "Network Manager initialized"); + + return ESP_OK; +} + +void NetworkManager_Deinit(void) +{ + if (_Network_Manager_State.isInitialized == false) { + return; + } + + ESP_LOGD(TAG, "Deinitializing Network Manager"); + + NetworkManager_Stop(); + esp_wifi_deinit(); + + if (_Network_Manager_State.STA_NetIF) { + esp_netif_destroy(_Network_Manager_State.STA_NetIF); + _Network_Manager_State.STA_NetIF = NULL; + } + + if (_Network_Manager_State.AP_NetIF) { + esp_netif_destroy(_Network_Manager_State.AP_NetIF); + _Network_Manager_State.AP_NetIF = NULL; + } + + if (_Network_Manager_State.EventGroup) { + vEventGroupDelete(_Network_Manager_State.EventGroup); + _Network_Manager_State.EventGroup = NULL; + } + + _Network_Manager_State.isInitialized = false; + _Network_Manager_State.State = NETWORK_STATE_IDLE; +} + +esp_err_t NetworkManager_StartSTA(void) +{ + wifi_config_t WifiConfig; + + if (_Network_Manager_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + _Network_Manager_State.RetryCount = 0; + + xEventGroupClearBits(_Network_Manager_State.EventGroup, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT); + + ESP_LOGI(TAG, "Starting WiFi in STA mode"); + ESP_LOGI(TAG, "Connecting to SSID: %s", _Network_Manager_State.STA_Config.ssid); + + memset(&WifiConfig, 0, sizeof(wifi_config_t)); + WifiConfig.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + WifiConfig.sta.pmf_cfg.capable = true; + WifiConfig.sta.pmf_cfg.required = false; + strncpy((char *)WifiConfig.sta.ssid, _Network_Manager_State.STA_Config.ssid, sizeof(WifiConfig.sta.ssid) - 1); + strncpy((char *)WifiConfig.sta.password, _Network_Manager_State.STA_Config.password, + sizeof(WifiConfig.sta.password) - 1); + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &WifiConfig)); + ESP_ERROR_CHECK(esp_wifi_start()); + + _Network_Manager_State.mode = NETWORK_WIFI_MODE_STA; + _Network_Manager_State.State = NETWORK_STATE_CONNECTING; + + return ESP_OK; +} + +esp_err_t NetworkManager_StartAP(void) +{ + wifi_config_t WifiConfig; + + if (_Network_Manager_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGD(TAG, "Starting WiFi in AP mode"); + memset(&WifiConfig, 0, sizeof(wifi_config_t)); + WifiConfig.ap.channel = _Network_Manager_State.AP_Config.channel; + WifiConfig.ap.max_connection = _Network_Manager_State.AP_Config.max_connections; + WifiConfig.ap.authmode = WIFI_AUTH_WPA2_PSK; + WifiConfig.ap.ssid_hidden = _Network_Manager_State.AP_Config.hidden ? 1 : 0; + strncpy((char *)WifiConfig.ap.ssid, _Network_Manager_State.AP_Config.ssid, sizeof(WifiConfig.ap.ssid) - 1); + WifiConfig.ap.ssid_len = strlen(_Network_Manager_State.AP_Config.ssid); + + if (strlen(_Network_Manager_State.AP_Config.password) < 8) { + WifiConfig.ap.authmode = WIFI_AUTH_OPEN; + } else { + strncpy((char *)WifiConfig.ap.password, _Network_Manager_State.AP_Config.password, + sizeof(WifiConfig.ap.password) - 1); + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &WifiConfig)); + ESP_ERROR_CHECK(esp_wifi_start()); + + _Network_Manager_State.mode = NETWORK_WIFI_MODE_AP; + _Network_Manager_State.State = NETWORK_STATE_AP_STARTED; + + /* Get AP IP info */ + esp_netif_get_ip_info(_Network_Manager_State.AP_NetIF, &_Network_Manager_State.IP_Info); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STARTED, NULL, 0, portMAX_DELAY); + ESP_LOGD(TAG, "AP started. SSID: %s, IP: " IPSTR, + _Network_Manager_State.AP_Config.ssid, IP2STR(&_Network_Manager_State.IP_Info.ip)); + + return ESP_OK; +} + +esp_err_t NetworkManager_StartAPSTA(void) +{ + wifi_config_t STA_Config; + wifi_config_t AP_Config; + + if (_Network_Manager_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGD(TAG, "Starting WiFi in AP+STA mode"); + + /* Configure STA */ + memset(&STA_Config, 0, sizeof(wifi_config_t)); + STA_Config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + STA_Config.sta.pmf_cfg.capable = true; + STA_Config.sta.pmf_cfg.required = false; + strncpy((char *)STA_Config.sta.ssid, _Network_Manager_State.STA_Config.ssid, sizeof(STA_Config.sta.ssid) - 1); + strncpy((char *)STA_Config.sta.password, _Network_Manager_State.STA_Config.password, + sizeof(STA_Config.sta.password) - 1); + + /* Configure AP */ + memset(&AP_Config, 0, sizeof(wifi_config_t)); + AP_Config.ap.channel = _Network_Manager_State.AP_Config.channel; + AP_Config.ap.max_connection = _Network_Manager_State.AP_Config.max_connections; + AP_Config.ap.authmode = WIFI_AUTH_WPA2_PSK; + AP_Config.ap.ssid_hidden = _Network_Manager_State.AP_Config.hidden ? 1 : 0; + strncpy((char *)AP_Config.ap.ssid, _Network_Manager_State.AP_Config.ssid, sizeof(AP_Config.ap.ssid) - 1); + AP_Config.ap.ssid_len = strlen(_Network_Manager_State.AP_Config.ssid); + + if (strlen(_Network_Manager_State.AP_Config.password) < 8) { + AP_Config.ap.authmode = WIFI_AUTH_OPEN; + } else { + strncpy((char *)AP_Config.ap.password, _Network_Manager_State.AP_Config.password, sizeof(AP_Config.ap.password) - 1); + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &STA_Config)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &AP_Config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + _Network_Manager_State.mode = NETWORK_WIFI_MODE_APSTA; + _Network_Manager_State.State = NETWORK_STATE_CONNECTING; + + return ESP_OK; +} + +esp_err_t NetworkManager_StartServer(Server_Config_t *p_Config) +{ + Server_Init(p_Config); + Server_Start(); + + /* Broadcast task will handle frame broadcasting automatically */ + + return ESP_OK; +} + +esp_err_t NetworkManager_Stop(void) +{ + if (_Network_Manager_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + SNTP_Deinit(); + + esp_wifi_stop(); + + _Network_Manager_State.State = NETWORK_STATE_IDLE; + + return ESP_OK; +} + +esp_err_t NetworkManager_ConnectWiFi(const char *p_SSID, const char *p_Password) +{ + if (_Network_Manager_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + if (p_SSID != NULL) { + strncpy(_Network_Manager_State.STA_Config.ssid, p_SSID, sizeof(_Network_Manager_State.STA_Config.ssid) - 1); + } + + if (p_Password != NULL) { + strncpy(_Network_Manager_State.STA_Config.password, p_Password, sizeof(_Network_Manager_State.STA_Config.password) - 1); + } + + /* Restart the WiFi connection with the new credentials */ + NetworkManager_Stop(); + NetworkManager_StartSTA(); + + /* Wait for connection */ + EventBits_t Bits = xEventGroupWaitBits(_Network_Manager_State.EventGroup, + WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, + pdFALSE, + pdFALSE, + 30000 / portTICK_PERIOD_MS); + + if (Bits & WIFI_CONNECTED_BIT) { + ESP_LOGD(TAG, "Connected to SSID: %s!", _Network_Manager_State.STA_Config.ssid); + return ESP_OK; + } else if (Bits & WIFI_FAIL_BIT) { + ESP_LOGE(TAG, "Failed to connect to SSID: %s!", _Network_Manager_State.STA_Config.ssid); + return ESP_FAIL; + } else { + ESP_LOGE(TAG, "Connection timeout!"); + return ESP_ERR_TIMEOUT; + } +} + +esp_err_t NetworkManager_DisconnectWiFi(void) +{ + if (_Network_Manager_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGD(TAG, "Disconnecting from WiFi"); + + return esp_wifi_disconnect(); +} + +bool NetworkManager_isConnected(void) +{ + return _Network_Manager_State.State == NETWORK_STATE_CONNECTED; +} + +Network_State_t NetworkManager_GetState(void) +{ + return _Network_Manager_State.State; +} + +esp_err_t NetworkManager_GetIP(esp_netif_ip_info_t *p_IP) +{ + if (p_IP == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memcpy(p_IP, &_Network_Manager_State.IP_Info, sizeof(esp_netif_ip_info_t)); + + return ESP_OK; +} + +int8_t NetworkManager_GetRSSI(void) +{ + wifi_ap_record_t ApInfo; + + if (NetworkManager_isConnected() == false) { + return 0; + } + + if (esp_wifi_sta_get_ap_info(&ApInfo) == ESP_OK) { + return ApInfo.rssi; + } + + return 0; +} + +esp_err_t NetworkManager_GetMAC(uint8_t *p_MAC) +{ + if (p_MAC == NULL) { + return ESP_ERR_INVALID_ARG; + } + + return esp_wifi_get_mac(WIFI_IF_STA, p_MAC); +} + +esp_err_t NetworkManager_SetCredentials(const char *p_SSID, const char *p_Password) +{ + if (p_SSID == NULL) { + return ESP_ERR_INVALID_ARG; + } + + strncpy(_Network_Manager_State.STA_Config.ssid, p_SSID, sizeof(_Network_Manager_State.STA_Config.ssid) - 1); + if (p_Password != NULL) { + strncpy(_Network_Manager_State.STA_Config.password, p_Password, sizeof(_Network_Manager_State.STA_Config.password) - 1); + } else { + _Network_Manager_State.STA_Config.password[0] = '\0'; + } + + return ESP_OK; +} + +esp_err_t NetworkManager_SaveCredentials(void) +{ + nvs_handle_t Handle; + esp_err_t Error; + + Error = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to open NVS: %d!", Error); + return Error; + } + + Error = nvs_set_str(Handle, NVS_KEY_SSID, _Network_Manager_State.STA_Config.ssid); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to save SSID: %d!", Error); + nvs_close(Handle); + return Error; + } + + Error = nvs_set_str(Handle, NVS_KEY_PASSWORD, _Network_Manager_State.STA_Config.password); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to save password: %d!", Error); + nvs_close(Handle); + return Error; + } + + Error = nvs_commit(Handle); + nvs_close(Handle); + + ESP_LOGD(TAG, "Credentials saved to NVS"); + + return ESP_OK; +} + +esp_err_t NetworkManager_LoadCredentials(void) +{ + nvs_handle_t Handle; + esp_err_t Error; + size_t Length; + + Error = nvs_open(NVS_NAMESPACE, NVS_READONLY, &Handle); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "No stored credentials found"); + return Error; + } + Length = sizeof(_Network_Manager_State.STA_Config.ssid); + + Error = nvs_get_str(Handle, NVS_KEY_SSID, _Network_Manager_State.STA_Config.ssid, &Length); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to load SSID: %d!", Error); + nvs_close(Handle); + return Error; + } + Length = sizeof(_Network_Manager_State.STA_Config.password); + + Error = nvs_get_str(Handle, NVS_KEY_PASSWORD, _Network_Manager_State.STA_Config.password, &Length); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to load password: %d!", Error); + nvs_close(Handle); + return Error; + } + + nvs_close(Handle); + + ESP_LOGD(TAG, "Credentials loaded from NVS. SSID: %s", _Network_Manager_State.STA_Config.ssid); + + return ESP_OK; +} + +esp_err_t NetworkManager_ClearCredentials(void) +{ + nvs_handle_t Handle; + esp_err_t Error; + + Error = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &Handle); + if (Error != ESP_OK) { + return Error; + } + + nvs_erase_key(Handle, NVS_KEY_SSID); + nvs_erase_key(Handle, NVS_KEY_PASSWORD); + nvs_commit(Handle); + nvs_close(Handle); + + _Network_Manager_State.STA_Config.ssid[0] = '\0'; + _Network_Manager_State.STA_Config.password[0] = '\0'; + + ESP_LOGD(TAG, "Credentials cleared"); + + return ESP_OK; +} + +uint8_t NetworkManager_GetConnectedStations(void) +{ + wifi_sta_list_t StaList; + + if ((_Network_Manager_State.mode != NETWORK_WIFI_MODE_AP) && (_Network_Manager_State.mode != NETWORK_WIFI_MODE_APSTA)) { + return 0; + } + + if (esp_wifi_ap_get_sta_list(&StaList) == ESP_OK) { + return StaList.num; + } + + return 0; +} diff --git a/main/Application/Manager/Network/networkManager.h b/main/Application/Manager/Network/networkManager.h new file mode 100644 index 0000000..de147ab --- /dev/null +++ b/main/Application/Manager/Network/networkManager.h @@ -0,0 +1,138 @@ +/* + * networkManager.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Network management definitions + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef NETWORKMANAGER_H_ +#define NETWORKMANAGER_H_ + +#include +#include +#include + +#include "network_types.h" +#include "SNTP/sntp.h" +#include "Server/server.h" +#include "Provisioning/provisioning.h" + +/** @brief Initialize the Network Manager. + * @param config Pointer to WiFi configuration + * @return ESP_OK on success + */ +esp_err_t NetworkManager_Init(const Network_Config_t *p_Config); + +/** @brief Deinitialize the Network Manager. + */ +void NetworkManager_Deinit(void); + +/** @brief Start WiFi in station mode. + * @return ESP_OK on success + */ +esp_err_t NetworkManager_StartSTA(void); + +/** @brief Start WiFi in access point mode. + * @return ESP_OK on success + */ +esp_err_t NetworkManager_StartAP(void); + +/** @brief Start WiFi in AP+STA mode. + * @return ESP_OK on success + */ +esp_err_t NetworkManager_StartAPSTA(void); + +/** @brief Stop Network Manager. + * @return ESP_OK on success + */ +esp_err_t NetworkManager_Stop(void); + +/** @brief Connect to WiFi (station mode). + * @param p_SSID SSID to connect to (NULL to use configured SSID) + * @param p_Password Password (NULL to use configured password) + * @return ESP_OK on success + */ +esp_err_t NetworkManager_ConnectWiFi(const char *p_SSID, const char *p_Password); + +/** @brief Disconnect from WiFi. + * @return ESP_OK on success + */ +esp_err_t NetworkManager_DisconnectWiFi(void); + +/** @brief Check if WiFi is connected. + * @return true if connected + */ +bool NetworkManager_isConnected(void); + +/** @brief Get current WiFi state. + * @return Current state + */ +Network_State_t NetworkManager_GetState(void); + +/** @brief Get IP information. + * @param p_IP Pointer to store IP info + * @return ESP_OK on success + */ +esp_err_t NetworkManager_GetIP(esp_netif_ip_info_t *p_IP); + +/** @brief Get WiFi signal strength (RSSI). + * @return RSSI in dBm, or 0 if not connected + */ +int8_t NetworkManager_GetRSSI(void); + +/** @brief Get MAC address. + * @param p_MAC Buffer to store MAC address (6 bytes) + * @return ESP_OK on success + */ +esp_err_t NetworkManager_GetMAC(uint8_t *p_MAC); + +/** @brief Set WiFi credentials for station mode. + * @param p_SSID SSID + * @param p_Password Password + * @return ESP_OK on success + */ +esp_err_t NetworkManager_SetCredentials(const char *p_SSID, const char *p_Password); + +/** @brief Save WiFi credentials to NVS. + * @return ESP_OK on success + */ +esp_err_t NetworkManager_SaveCredentials(void); + +/** @brief Load WiFi credentials from NVS. + * @return ESP_OK on success + */ +esp_err_t NetworkManager_LoadCredentials(void); + +/** @brief Clear stored WiFi credentials. + * @return ESP_OK on success + */ +esp_err_t NetworkManager_ClearCredentials(void); + +/** @brief Get number of connected stations (AP mode). + * @return Number of connected stations + */ +uint8_t NetworkManager_GetConnectedStations(void); + +/** @brief Start the network server (HTTP + WebSocket). + * @param p_Config Pointer to server configuration + * @return ESP_OK on success + */ +esp_err_t NetworkManager_StartServer(Server_Config_t *p_Config); + +#endif /* NETWORKMANAGER_H_ */ diff --git a/main/Application/Manager/Network/network_types.h b/main/Application/Manager/Network/network_types.h new file mode 100644 index 0000000..562a0a5 --- /dev/null +++ b/main/Application/Manager/Network/network_types.h @@ -0,0 +1,248 @@ +/* + * network_types.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Common type definitions for the network interface component. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef NETWORK_TYPES_H_ +#define NETWORK_TYPES_H_ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* Declare network event base */ +ESP_EVENT_DECLARE_BASE(NETWORK_EVENTS); + +/** @brief Network connection state. + */ +typedef enum { + NETWORK_STATE_IDLE = 0, + NETWORK_STATE_CONNECTING, + NETWORK_STATE_CONNECTED, + NETWORK_STATE_DISCONNECTED, + NETWORK_STATE_PROVISIONING, + NETWORK_STATE_AP_STARTED, + NETWORK_STATE_ERROR, +} Network_State_t; + +/** @brief WiFi operation mode. + */ +typedef enum { + NETWORK_WIFI_MODE_STA = 0, + NETWORK_WIFI_MODE_AP, + NETWORK_WIFI_MODE_APSTA, +} Network_WiFiMode_t; + +/** @brief Provisioning method. + */ +typedef enum { + NETWORK_PROV_NONE = 0, + NETWORK_PROV_BLE, + NETWORK_PROV_SOFTAP, + NETWORK_PROV_BOTH, +} Network_ProvMethod_t; + +/** @brief Image format for encoding. + */ +typedef enum { + NETWORK_IMAGE_FORMAT_JPEG = 0, + NETWORK_IMAGE_FORMAT_PNG, + NETWORK_IMAGE_FORMAT_RAW, +} Network_ImageFormat_t; + +/** @brief Network event types (used as event IDs in NETWORK_EVENTS base). + */ +typedef enum { + NETWORK_EVENT_WIFI_CONNECTED = 0, + NETWORK_EVENT_WIFI_DISCONNECTED, + NETWORK_EVENT_WIFI_GOT_IP, /**< The device got an IP address + Data is of type Network_IP_Info_t */ + NETWORK_EVENT_AP_STARTED, + NETWORK_EVENT_AP_STOPPED, + NETWORK_EVENT_AP_STA_CONNECTED, + NETWORK_EVENT_AP_STA_DISCONNECTED, + NETWORK_EVENT_PROV_STARTED, + NETWORK_EVENT_PROV_STOPPED, + NETWORK_EVENT_PROV_CRED_RECV, + NETWORK_EVENT_PROV_SUCCESS, + NETWORK_EVENT_PROV_FAILED, + NETWORK_EVENT_PROV_TIMEOUT, + NETWORK_EVENT_WS_CLIENT_CONNECTED, + NETWORK_EVENT_WS_CLIENT_DISCONNECTED, + NETWORK_EVENT_OTA_STARTED, + NETWORK_EVENT_OTA_PROGRESS, + NETWORK_EVENT_OTA_COMPLETED, + NETWORK_EVENT_OTA_FAILED, + NETWORK_EVENT_SNTP_SYNCED, /**< SNTP time synchronization completed + Data is of type struct timeval */ + NETWORK_EVENT_SET_TZ, /**< Set the timezone + Data is a const char* string */ + NETWORK_EVENT_OPEN_WIFI_REQUEST, /**< Request to open a WiFi connection */ + NETWORK_EVENT_SERVER_STARTED, /**< HTTP/WebSocket server started */ + NETWORK_EVENT_SERVER_STOPPED, /**< HTTP/WebSocket server stopped */ + NETWORK_EVENT_SERVER_ERROR, /**< HTTP/WebSocket server error */ +} Network_Event_t; + +/** @brief Color palette types. + */ +typedef enum { + PALETTE_IRON = 0, + PALETTE_GRAY, + PALETTE_RAINBOW, +} Server_Palette_t; + +/** @brief Scale mode for temperature visualization. + */ +typedef enum { + SCALE_LINEAR = 0, + SCALE_HISTOGRAM, +} Server_Scale_t; + +/** @brief LED state. + */ +typedef enum { + LED_STATE_OFF = 0, + LED_STATE_ON, + LED_STATE_BLINK, +} Server_LED_State_t; + +/** @brief WebSocket message types. + */ +typedef enum { + WS_MSG_TYPE_EVENT = 0, + WS_MSG_TYPE_COMMAND, + WS_MSG_TYPE_RESPONSE, +} Server_WS_Message_Type_t; + +/** @brief Thermal frame data structure. + */ +typedef struct { + uint8_t *buffer; /**< Pointer to RGB888 image data */ + uint16_t width; /**< Frame width in pixels */ + uint16_t height; /**< Frame height in pixels */ + float temp_min; /**< Minimum temperature in frame */ + float temp_max; /**< Maximum temperature in frame */ + float temp_avg; /**< Average temperature in frame */ + uint32_t timestamp; /**< Timestamp in milliseconds */ + SemaphoreHandle_t mutex; /**< Mutex for thread-safe access */ +} Network_Thermal_Frame_t; + +/** @brief Encoded image data. + */ +typedef struct { + uint8_t *data; /**< Encoded image data */ + size_t size; /**< Size of encoded data */ + Network_ImageFormat_t format; /**< Image format */ + uint16_t width; /**< Image width */ + uint16_t height; /**< Image height */ +} Network_Encoded_Image_t; + +/** @brief IP info event data (for NETWORK_EVENT_WIFI_GOT_IP). + */ +typedef struct { + uint32_t IP; + uint32_t Netmask; + uint32_t Gateway; +} Network_IP_Info_t; + +/** @brief Station info event data (for AP_STA_CONNECTED/DISCONNECTED). + */ +typedef struct { + uint8_t MAC[6]; +} Network_Event_STA_Info_t; + +/** @brief OTA progress event data (for NETWORK_EVENT_OTA_PROGRESS). + */ +typedef struct { + uint32_t bytes_written; + uint32_t total_bytes; +} Network_Event_OTA_Progress_t; + +/** @brief WebSocket client event data. + */ +typedef struct { + int client_fd; +} Network_Event_WS_Client_t; + +/** @brief WiFi station configuration. + */ +typedef struct { + char ssid[33]; + char password[65]; + uint8_t max_retries; + uint16_t retry_interval_ms; +} Network_WiFi_STA_Config_t; + +/** @brief WiFi access point configuration. + */ +typedef struct { + char ssid[33]; + char password[65]; + uint8_t channel; + uint8_t max_connections; + bool hidden; +} Network_WiFi_AP_Config_t; + +/** @brief Network interface configuration. + */ +typedef struct { + Network_WiFiMode_t WiFi_Mode; + Network_WiFi_STA_Config_t STA_Config; + Network_WiFi_AP_Config_t AP_Config; + Network_ProvMethod_t Prov_Method; +} Network_Config_t; + +/** @brief LED control request. + */ +typedef struct { + Server_LED_State_t state; + uint8_t brightness; + uint16_t blink_ms; +} Server_LED_Request_t; + +/** @brief Server configuration. + */ +typedef struct { + uint16_t http_port; + uint8_t max_clients; + uint16_t ws_ping_interval_sec; + bool enable_cors; + const char *api_key; +} Server_Config_t; + +/** @brief Server status. + */ +typedef struct { + bool running; + uint8_t http_clients; + uint8_t ws_clients; + uint32_t requests_served; + uint32_t frames_streamed; +} Server_Status_t; + +#endif /* NETWORK_TYPES_H_ */ diff --git a/main/Application/Manager/SD/sdManager.cpp b/main/Application/Manager/SD/sdManager.cpp new file mode 100644 index 0000000..949bb10 --- /dev/null +++ b/main/Application/Manager/SD/sdManager.cpp @@ -0,0 +1,438 @@ +/* + * sdManager.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: SD card manager implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "sdManager.h" +#include "Application/bitmap.h" +#include "Application/application.h" +#include "Application/Manager/Devices/SPI/spi.h" + +#if defined(CONFIG_SD_CARD_SPI2_HOST) +#define SD_SPI_HOST SPI2_HOST +#elif defined(CONFIG_SD_CARD_SPI3_HOST) +#define SD_SPI_HOST SPI3_HOST +#else +#error "No SPI host defined for SD card!" +#endif + +#if CONFIG_SD_CARD_PIN_CD > 0 +#define SD_DEBOUNCE_TIME_MS 500 +#endif /* CONFIG_SD_CARD_PIN_CD */ + +#define SD_MOUNT_TASK_STACK 4096 +#define SD_MOUNT_TASK_PRIORITY 3 + +ESP_EVENT_DEFINE_BASE(SD_EVENTS); + +static const char *TAG = "sd-manager"; + +typedef struct { + sdmmc_card_t *Card; + sdmmc_host_t Host; + sdspi_device_config_t SlotConfig; + bool isInitialized; + esp_timer_handle_t DebounceTimer; + esp_vfs_fat_sdmmc_mount_config_t MountConfig; + TaskHandle_t MountTaskHandle; + volatile bool CardPresent; + gpio_config_t CD_Conf; +} SD_Manager_State_t; + +static SD_Manager_State_t _SD_Manager_State; + +#if CONFIG_SD_CARD_PIN_CD > 0 +/** @brief Debounce timer callback - called after card state is stable. + * @param p_Arg Unused + */ +static void SDManager_DebounceTimerCallback(void *p_Arg) +{ + (void)p_Arg; + + /* Read current card state */ + bool cardPresent = (gpio_get_level(static_cast(CONFIG_SD_CARD_PIN_CD)) == 0); + + ESP_LOGI(TAG, "Card state stable: %s", cardPresent ? "present" : "removed"); + + _SD_Manager_State.CardPresent = cardPresent; + + /* Notify about state change */ + esp_event_post(SD_EVENTS, SD_EVENT_CARD_CHANGED, (const void *)&cardPresent, sizeof(bool), 0); +} + +/** @brief GPIO interrupt handler for card detection. + * Called when the card detect pin changes state. + * @param p_Arg Unused + */ +static void IRAM_ATTR SDManager_CardDetectISR(void *p_Arg) +{ + (void)p_Arg; + + /* Restart debounce timer on every edge - only triggers callback after stable period */ + if (_SD_Manager_State.DebounceTimer != NULL) { + esp_timer_stop(_SD_Manager_State.DebounceTimer); + esp_timer_start_once(_SD_Manager_State.DebounceTimer, SD_DEBOUNCE_TIME_MS * 1000); + } +} +#endif /* CONFIG_SD_CARD_PIN_CD */ + +esp_err_t SDManager_Init(void) +{ + if (_SD_Manager_State.isInitialized) { + ESP_LOGW(TAG, "SD Manager already initialized"); + return ESP_OK; + } + + ESP_LOGI(TAG, "Initializing SD Manager..."); + + if (CONFIG_SD_CARD_PIN_CS < 0) { + ESP_LOGE(TAG, "Invalid CS pin!"); + return ESP_ERR_INVALID_ARG; + } + + _SD_Manager_State.MountConfig = { +#ifdef CONFIG_SD_CARD_FORMAT_CARD + .format_if_mount_failed = true, +#else + .format_if_mount_failed = false, +#endif + .max_files = 5, + .allocation_unit_size = 16 * 1024, + .disk_status_check_enable = false, + .use_one_fat = false + }; + + _SD_Manager_State.Host = SDSPI_HOST_DEFAULT(); + _SD_Manager_State.Host.slot = SD_SPI_HOST; + _SD_Manager_State.SlotConfig = SDSPI_DEVICE_CONFIG_DEFAULT(); + _SD_Manager_State.SlotConfig.gpio_cs = static_cast(CONFIG_SD_CARD_PIN_CS); + _SD_Manager_State.SlotConfig.host_id = static_cast(_SD_Manager_State.Host.slot); + + if (esp_vfs_fat_sdspi_mount("/sdcard", &_SD_Manager_State.Host, &_SD_Manager_State.SlotConfig, + &_SD_Manager_State.MountConfig, &_SD_Manager_State.Card) != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount SD card filesystem!"); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "SD card filesystem mounted successfully"); + +#if CONFIG_SD_CARD_PIN_CD > 0 + /* Configure card detect pin with interrupt */ + _SD_Manager_State.CD_Conf.intr_type = GPIO_INTR_ANYEDGE; + _SD_Manager_State.CD_Conf.mode = GPIO_MODE_INPUT; + _SD_Manager_State.CD_Conf.pin_bit_mask = (1ULL << CONFIG_SD_CARD_PIN_CD); + _SD_Manager_State.CD_Conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + _SD_Manager_State.CD_Conf.pull_up_en = GPIO_PULLUP_ENABLE; + + Error = gpio_config(&_SD_Manager_State.CD_Conf); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to configure card detect pin: %d!", Error); + return Error; + } + + /* Install GPIO ISR service if not already installed */ + Error = gpio_install_isr_service(0); + if (Error != ESP_OK && Error != ESP_ERR_INVALID_STATE) { + ESP_LOGE(TAG, "Failed to install GPIO ISR service: %d!", Error); + return Error; + } + + /* Add ISR handler for card detect pin */ + Error = gpio_isr_handler_add(static_cast(CONFIG_SD_CARD_PIN_CD), SDManager_CardDetectISR, NULL); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to add ISR handler: %d!", Error); + return Error; + } + + /* Create debounce timer */ + const esp_timer_create_args_t debounce_timer_args = { + .callback = &SDManager_DebounceTimerCallback, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "sd_debounce", + .skip_unhandled_events = false, + }; + + Error = esp_timer_create(&debounce_timer_args, &_SD_Manager_State.DebounceTimer); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to create debounce timer: %d!", Error); + return Error; + } + + /* Check initial card state and trigger debounced event if present */ + if (gpio_get_level(static_cast(CONFIG_SD_CARD_PIN_CD)) == 0) { + ESP_LOGI(TAG, "SD card present at initialization"); + + _SD_Manager_State.CardPresent = true; + + /* Start timer to trigger initial mount after debounce period */ + esp_timer_start_once(_SD_Manager_State.DebounceTimer, SD_DEBOUNCE_TIME_MS * 1000); + } else { + ESP_LOGI(TAG, "No SD card present at initialization"); + + _SD_Manager_State.CardPresent = false; + } +#endif /* CONFIG_SD_CARD_PIN_CD */ + + _SD_Manager_State.isInitialized = true; + + ESP_LOGI(TAG, "SD manager initialized"); + + return ESP_OK; +} + +esp_err_t SDManager_Deinit(void) +{ + if (_SD_Manager_State.isInitialized == false) { + return ESP_OK; + } + + ESP_LOGI(TAG, "Deinitializing SD Manager..."); + +#if CONFIG_SD_CARD_PIN_CD > 0 + /* Stop and delete debounce timer */ + if (_SD_Manager_State.DebounceTimer != NULL) { + esp_timer_stop(_SD_Manager_State.DebounceTimer); + esp_timer_delete(_SD_Manager_State.DebounceTimer); + _SD_Manager_State.DebounceTimer = NULL; + } +#endif /* CONFIG_SD_CARD_PIN_CD */ + + /* Wait for mount task to finish if running */ + if (_SD_Manager_State.MountTaskHandle != NULL) { + vTaskDelay(100 / portTICK_PERIOD_MS); + _SD_Manager_State.MountTaskHandle = NULL; + } + + SDManager_Unmount(); + + _SD_Manager_State.isInitialized = false; + + ESP_LOGI(TAG, "SD Manager deinitialized"); + + return ESP_OK; +} + +bool SDManager_IsCardPresent(void) +{ + return _SD_Manager_State.CardPresent; +} + +esp_err_t SDManager_SaveBitmap(const char *p_Path, uint16_t Width, uint16_t Height, const uint8_t *p_Buffer, + uint32_t Length) +{ + esp_err_t Error; + Bitmap_BMP_Header_t Header; + Bitmap_DIB_Header_t InfoHeader; + + if (_SD_Manager_State.CardPresent == false) { + return ESP_ERR_INVALID_STATE; + } + + if ((p_Path == NULL) || (p_Buffer == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Prepare bitmap headers */ + memset(&Header, 0, sizeof(Header)); + memset(&InfoHeader, 0, sizeof(InfoHeader)); + + Header.bType = BITMAP_MAGIC; + Header.bReserved = 0; + Header.bfSize = sizeof(Header) + sizeof(InfoHeader) + Length; + Header.bfOffBits = sizeof(Header) + sizeof(InfoHeader); + + InfoHeader.biSize = sizeof(InfoHeader); + InfoHeader.biWidth = Width; + InfoHeader.biHeight = Height; + InfoHeader.biPlanes = 1; + InfoHeader.biBitCount = 24; + InfoHeader.biCompression = BITMAP_COMP_RGB; + InfoHeader.biSizeImage = Length; + InfoHeader.biXPelsPerMeter = 0; + InfoHeader.biYPelsPerMeter = 0; + InfoHeader.biClrUsed = 0; + InfoHeader.biClrImportant = 0; + + ESP_LOGI(TAG, "Saving bitmap to %s", p_Path); + + /* Open file for writing */ + FILE *f = fopen(p_Path, "wb"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed to open file for writing: %s!", p_Path); + return ESP_FAIL; + } + + /* Write bitmap file header */ + if (fwrite(&Header, sizeof(uint8_t), sizeof(Header), f) != sizeof(Header)) { + ESP_LOGE(TAG, "Failed to write file header: %s!", p_Path); + Error = ESP_FAIL; + goto SDManager_SaveBitmap_Exit; + } + + /* Write DIB header */ + if (fwrite(&InfoHeader, sizeof(uint8_t), sizeof(InfoHeader), f) != sizeof(InfoHeader)) { + ESP_LOGE(TAG, "Failed to write DIB header: %s!", p_Path); + Error = ESP_FAIL; + goto SDManager_SaveBitmap_Exit; + } + + /* Write image data */ + if (fwrite(p_Buffer, sizeof(uint8_t), Length, f) != Length) { + ESP_LOGE(TAG, "Failed to write image data: %s!", p_Path); + Error = ESP_FAIL; + goto SDManager_SaveBitmap_Exit; + } + + ESP_LOGI(TAG, "Bitmap saved successfully"); + Error = ESP_OK; + +SDManager_SaveBitmap_Exit: + fclose(f); + + return Error; +} + +/** @brief Background task for mounting SD card (prevents GUI blocking). + * @param arg Unused + */ +static void SDManager_MountTask(void *arg) +{ + (void)arg; + esp_err_t Error; + + /* Add this task to WDT */ + esp_task_wdt_add(NULL); + + ESP_LOGI(TAG, "Mount task started"); + + /* Reset WDT before mount attempt */ + esp_task_wdt_reset(); + + Error = esp_vfs_fat_sdspi_mount(SD_MOUNT_POINT, &_SD_Manager_State.Host, &_SD_Manager_State.SlotConfig, + &_SD_Manager_State.MountConfig, + &_SD_Manager_State.Card); + + /* Reset WDT after mount attempt */ + esp_task_wdt_reset(); + if (Error != ESP_OK) { + if (Error == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount filesystem. Format the card or check hardware connection!"); + } else { + ESP_LOGE(TAG, "Failed to initialize SD card %d!", Error); + } + + _SD_Manager_State.Card = NULL; + + /* Post mount error event */ + esp_event_post(SD_EVENTS, SD_EVENT_MOUNT_ERROR, NULL, 0, portMAX_DELAY); + } else { + /* Card mounted successfully */ + ESP_LOGI(TAG, "SD card mounted successfully"); + ESP_LOGI(TAG, "Card size: %llu MB", ((uint64_t)_SD_Manager_State.Card->csd.capacity) * + _SD_Manager_State.Card->csd.sector_size / + (1024 * 1024)); + + /* Post mount success event */ + esp_event_post(SD_EVENTS, SD_EVENT_MOUNTED, NULL, 0, portMAX_DELAY); + } + + _SD_Manager_State.MountTaskHandle = NULL; + + /* Remove from WDT before deleting */ + esp_task_wdt_delete(NULL); + + vTaskDelete(NULL); +} + +esp_err_t SDManager_Mount(void) +{ + if (_SD_Manager_State.CardPresent == false) { + ESP_LOGW(TAG, "No SD card available!"); + return ESP_ERR_NOT_FOUND; + } + + /* Prevent multiple mount tasks */ + if (_SD_Manager_State.MountTaskHandle != NULL) { + ESP_LOGW(TAG, "Mount task already running"); + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGI(TAG, "Starting async mount task..."); + + BaseType_t ret = xTaskCreatePinnedToCore( + SDManager_MountTask, + "sd_mount", + SD_MOUNT_TASK_STACK, + NULL, + SD_MOUNT_TASK_PRIORITY, + &_SD_Manager_State.MountTaskHandle, + 1 /* Run on CPU 1 to avoid blocking GUI task on CPU 0 */ + ); + + if (ret != pdPASS) { + ESP_LOGE(TAG, "Failed to create mount task!"); + return ESP_ERR_NO_MEM; + } + + return ESP_OK; +} + +esp_err_t SDManager_Unmount(void) +{ + esp_err_t Error; + + if (_SD_Manager_State.Card == NULL) { + return ESP_OK; + } + + ESP_LOGI(TAG, "Unmounting SD card..."); + + Error = esp_vfs_fat_sdcard_unmount(SD_MOUNT_POINT, _SD_Manager_State.Card); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to unmount SD card %d!", Error); + + return Error; + } + + ESP_LOGI(TAG, "SD card unmounted"); + + _SD_Manager_State.Card = NULL; + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/SD/sdManager.h b/main/Application/Manager/SD/sdManager.h new file mode 100644 index 0000000..490b95d --- /dev/null +++ b/main/Application/Manager/SD/sdManager.h @@ -0,0 +1,83 @@ +/* + * sdManager.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: SD card manager header. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef SDMANAGER_H_ +#define SDMANAGER_H_ + +#include + +#include +#include + +/** @brief SD card mount point. + */ +#define SD_MOUNT_POINT "/sdcard" + +/** @brief SD card event identifiers. + */ +enum { + SD_EVENT_CARD_CHANGED, /**< SD card has been inserted or removed. + The data type is bool. */ + SD_EVENT_MOUNTED, /**< SD card has been mounted successfully. */ + SD_EVENT_MOUNT_ERROR, /**< SD card mount error occurred. */ +}; + +/** @brief Initialize the SD card manager. + * Sets up card detection GPIO and attempts initial mount if card is present. + * @return ESP_OK on success + */ +esp_err_t SDManager_Init(void); + +/** @brief Deinitialize the SD card manager. + * Unmounts card if present and releases resources. + * @return ESP_OK on success + */ +esp_err_t SDManager_Deinit(void); + +/** @brief Check if SD card is currently present and mounted. + * @return true if card is present and mounted, false otherwise + */ +bool SDManager_IsCardPresent(void); + +/** @brief Save a bitmap image to the SD card. + * @param p_Path Path to save the bitmap file (relative to mount point) + * @param Width Image width in pixels + * @param Height Image height in pixels + * @param p_Buffer Pointer to RGB888 image buffer + * @param Length Buffer length in bytes + * @return ESP_OK on success + */ +esp_err_t SDManager_SaveBitmap(const char *p_Path, uint16_t Width, uint16_t Height, const uint8_t *p_Buffer, + uint32_t Length); + +/** @brief Mount the SD card. + * @return ESP_OK on success + */ +esp_err_t SDManager_Mount(void); + +/** @brief Unmount the SD card. + * @return ESP_OK on success + */ +esp_err_t SDManager_Unmount(void); + +#endif /* SDMANAGER_H_ */ diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp new file mode 100644 index 0000000..57a66fa --- /dev/null +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -0,0 +1,451 @@ +/* + * settingsManager.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Persistent settings management using NVS storage. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#include "settingsManager.h" + +static const char *TAG = "settings_manager"; + +ESP_EVENT_DEFINE_BASE(SETTINGS_EVENTS); + +/** @brief Settings Manager state. + */ +typedef struct { + bool isInitialized; + bool PendingChanges; + nvs_handle_t NVS_Handle; + App_Settings_t Settings; + SemaphoreHandle_t Mutex; +} SettingsManager_State_t; + +static SettingsManager_State_t _State = { + .isInitialized = false, + .PendingChanges = false, + .NVS_Handle = 0, + .Settings = {0}, + .Mutex = NULL, +}; + +/** @brief Initialize settings with factory defaults. + */ +static void _SettingsManager_InitDefaults(App_Settings_t *p_Settings) +{ + uint8_t Mac[6]; + + memset(p_Settings, 0, sizeof(App_Settings_t)); + + p_Settings->Version = SETTINGS_VERSION; + + /* Lepton defaults */ + p_Settings->Lepton.SpotmeterROI.x = 40; + p_Settings->Lepton.SpotmeterROI.y = 40; + p_Settings->Lepton.SpotmeterROI.w = 80; + p_Settings->Lepton.SpotmeterROI.h = 40; + + /* WiFi defaults */ + strncpy(p_Settings->WiFi.SSID, "", sizeof(p_Settings->WiFi.SSID)); + strncpy(p_Settings->WiFi.Password, "", sizeof(p_Settings->WiFi.Password)); + p_Settings->WiFi.AP_Mode = false; + strncpy(p_Settings->WiFi.AP_SSID, "PyroVision", sizeof(p_Settings->WiFi.AP_SSID)); + strncpy(p_Settings->WiFi.AP_Password, "pyrovision123", sizeof(p_Settings->WiFi.AP_Password)); + + /* Display defaults */ + p_Settings->Display.Brightness = 80; + p_Settings->Display.ScreenTimeout = 0; + + /* System defaults */ + if (esp_efuse_mac_get_default(Mac) == ESP_OK) { + /* Append the MAC address to the device name */ + snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision-%02X%02X%02X%02X%02X%02X", + Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]); + } else { + snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision"); + ESP_LOGW(TAG, "Failed to get MAC address, using default name"); + } + + p_Settings->System.SDCard_AutoMount = true; + p_Settings->System.Bluetooth_Enabled = false; + strncpy(p_Settings->System.Timezone, "CET-1CEST,M3.5.0,M10.5.0/3", sizeof(p_Settings->System.Timezone)); +} + +esp_err_t SettingsManager_Init(void) +{ + esp_err_t Error; + + if (_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + ESP_LOGI(TAG, "Initializing Settings Manager..."); + + ESP_ERROR_CHECK(nvs_flash_init()); + + /* Create mutex for thread-safe access */ + _State.Mutex = xSemaphoreCreateMutex(); + if (_State.Mutex == NULL) { + ESP_LOGE(TAG, "Failed to create mutex!"); + return ESP_ERR_NO_MEM; + } + + /* Open NVS handle */ + Error = nvs_open(SETTINGS_NVS_NAMESPACE, NVS_READWRITE, &_State.NVS_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to open NVS handle: %d!", Error); + vSemaphoreDelete(_State.Mutex); + return Error; + } + + _State.isInitialized = true; + _State.PendingChanges = false; + + /* Load settings from NVS or use defaults */ + Error = SettingsManager_Load(&_State.Settings); + if (Error == ESP_ERR_NVS_NOT_FOUND) { + ESP_LOGI(TAG, "No settings found, using factory defaults"); + _SettingsManager_InitDefaults(&_State.Settings); + /* Save defaults to NVS */ + SettingsManager_Save(&_State.Settings); + } else if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to load settings: %d!", Error); + _SettingsManager_InitDefaults(&_State.Settings); + } + + ESP_LOGI(TAG, "Settings Manager initialized (version %lu)", _State.Settings.Version); + + /* Post event to notify settings loaded */ + esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_LOADED, &_State.Settings, sizeof(App_Settings_t), portMAX_DELAY); + + return ESP_OK; +} + +esp_err_t SettingsManager_Deinit(void) +{ + if (_State.isInitialized == false) { + return ESP_OK; + } + + /* Commit any pending changes */ + if (_State.PendingChanges) { + SettingsManager_Commit(); + } + + nvs_close(_State.NVS_Handle); + vSemaphoreDelete(_State.Mutex); + + _State.isInitialized = false; + + ESP_LOGI(TAG, "Settings Manager deinitialized"); + + return ESP_OK; +} + +esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) +{ + esp_err_t Error; + size_t RequiredSize; + + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (p_Settings == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + + /* Check if settings blob exists */ + Error = nvs_get_blob(_State.NVS_Handle, "settings", NULL, &RequiredSize); + if (Error == ESP_ERR_NVS_NOT_FOUND) { + xSemaphoreGive(_State.Mutex); + return ESP_ERR_NVS_NOT_FOUND; + } else if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to get settings size: %d!", Error); + xSemaphoreGive(_State.Mutex); + return Error; + } + + /* Verify size matches */ + if (RequiredSize != sizeof(App_Settings_t)) { + ESP_LOGW(TAG, "Settings size mismatch (expected %u, got %u), using defaults", + sizeof(App_Settings_t), RequiredSize); + xSemaphoreGive(_State.Mutex); + return ESP_ERR_INVALID_SIZE; + } + + /* Load settings blob */ + Error = nvs_get_blob(_State.NVS_Handle, "settings", p_Settings, &RequiredSize); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read settings: %d!", Error); + xSemaphoreGive(_State.Mutex); + return Error; + } + + /* Verify version */ + if (p_Settings->Version != SETTINGS_VERSION) { + ESP_LOGW(TAG, "Settings version mismatch (expected %d, got %lu), migration needed", + SETTINGS_VERSION, p_Settings->Version); + /* TODO: Implement migration logic here */ + } + + xSemaphoreGive(_State.Mutex); + + ESP_LOGI(TAG, "Settings loaded from NVS"); + + return ESP_OK; +} + +esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings) +{ + esp_err_t Error; + + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (p_Settings == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + + /* Save settings blob */ + Error = nvs_set_blob(_State.NVS_Handle, "settings", p_Settings, sizeof(App_Settings_t)); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to write settings: %d!", Error); + xSemaphoreGive(_State.Mutex); + return Error; + } + + /* Commit to flash */ + Error = nvs_commit(_State.NVS_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit settings: %d!", Error); + xSemaphoreGive(_State.Mutex); + return Error; + } + + _State.PendingChanges = false; + + xSemaphoreGive(_State.Mutex); + + ESP_LOGI(TAG, "Settings saved to NVS"); + + /* Post event to notify settings saved */ + esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_SAVED, NULL, 0, portMAX_DELAY); + + return ESP_OK; +} + +esp_err_t SettingsManager_Get(App_Settings_t *p_Settings) +{ + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (p_Settings == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_State.Settings, sizeof(App_Settings_t)); + xSemaphoreGive(_State.Mutex); + + return ESP_OK; +} + +esp_err_t SettingsManager_SetLepton(const App_Settings_Lepton_t *p_Lepton) +{ + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (p_Lepton == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + + memcpy(&_State.Settings.Lepton, p_Lepton, sizeof(App_Settings_Lepton_t)); + _State.PendingChanges = true; + + xSemaphoreGive(_State.Mutex); + + ESP_LOGI(TAG, "Lepton settings updated"); + + /* Broadcast event */ + esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_LEPTON_CHANGED, p_Lepton, + sizeof(App_Settings_Lepton_t), portMAX_DELAY); + + return ESP_OK; +} + +esp_err_t SettingsManager_SetWiFi(const App_Settings_WiFi_t *p_WiFi) +{ + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (p_WiFi == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + + memcpy(&_State.Settings.WiFi, p_WiFi, sizeof(App_Settings_WiFi_t)); + _State.PendingChanges = true; + + xSemaphoreGive(_State.Mutex); + + ESP_LOGI(TAG, "WiFi settings updated (SSID: %s, AP Mode: %d)", + p_WiFi->SSID, p_WiFi->AP_Mode); + + /* Broadcast event */ + esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_WIFI_CHANGED, p_WiFi, + sizeof(App_Settings_WiFi_t), portMAX_DELAY); + + return ESP_OK; +} + +esp_err_t SettingsManager_SetDisplay(const App_Settings_Display_t *p_Display) +{ + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (p_Display == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + + memcpy(&_State.Settings.Display, p_Display, sizeof(App_Settings_Display_t)); + _State.PendingChanges = true; + + xSemaphoreGive(_State.Mutex); + + ESP_LOGI(TAG, "Display settings updated (Brightness: %d%%, Timeout: %ds)", + p_Display->Brightness, p_Display->ScreenTimeout); + + /* Broadcast event */ + esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_DISPLAY_CHANGED, p_Display, + sizeof(App_Settings_Display_t), portMAX_DELAY); + + return ESP_OK; +} + +esp_err_t SettingsManager_SetSystem(const App_Settings_System_t *p_System) +{ + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (p_System == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + + memcpy(&_State.Settings.System, p_System, sizeof(App_Settings_System_t)); + _State.PendingChanges = true; + + xSemaphoreGive(_State.Mutex); + + ESP_LOGI(TAG, "System settings updated (Device: %s, SD Auto: %d)", + p_System->DeviceName, p_System->SDCard_AutoMount); + + /* Broadcast event */ + esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_SYSTEM_CHANGED, p_System, + sizeof(App_Settings_System_t), portMAX_DELAY); + + return ESP_OK; +} + +esp_err_t SettingsManager_ResetToDefaults(void) +{ + esp_err_t Error; + + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGW(TAG, "Resetting settings to factory defaults"); + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + + /* Erase settings from NVS */ + Error = nvs_erase_key(_State.NVS_Handle, "settings"); + if (Error != ESP_OK && Error != ESP_ERR_NVS_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to erase settings: %d!", Error); + xSemaphoreGive(_State.Mutex); + return Error; + } + + Error = nvs_commit(_State.NVS_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit erase: %d!", Error); + xSemaphoreGive(_State.Mutex); + return Error; + } + + /* Load factory defaults */ + _SettingsManager_InitDefaults(&_State.Settings); + _State.PendingChanges = false; + + xSemaphoreGive(_State.Mutex); + + /* Save defaults */ + SettingsManager_Save(&_State.Settings); + + ESP_LOGI(TAG, "Settings reset to factory defaults"); + + /* Broadcast event */ + esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_CHANGED, &_State.Settings, + sizeof(App_Settings_t), portMAX_DELAY); + + return ESP_OK; +} + +esp_err_t SettingsManager_GetDefaults(App_Settings_t *p_Settings) +{ + if (p_Settings == NULL) { + return ESP_ERR_INVALID_ARG; + } + + _SettingsManager_InitDefaults(p_Settings); + + return ESP_OK; +} + +esp_err_t SettingsManager_Commit(void) +{ + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (_State.PendingChanges == false) { + ESP_LOGD(TAG, "No pending changes to commit"); + return ESP_OK; + } + + return SettingsManager_Save(&_State.Settings); +} + +bool SettingsManager_HasPendingChanges(void) +{ + return _State.PendingChanges; +} diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h new file mode 100644 index 0000000..886c705 --- /dev/null +++ b/main/Application/Manager/Settings/settingsManager.h @@ -0,0 +1,120 @@ +/* + * settingsManager.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Persistent settings management using NVS storage. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef SETTINGS_MANAGER_H_ +#define SETTINGS_MANAGER_H_ + +#include +#include + +#include "settings_types.h" + +/** @brief Settings storage namespace in NVS. + */ +#define SETTINGS_NVS_NAMESPACE "pyrovision" + +/** @brief Current settings version for migration support. + */ +#define SETTINGS_VERSION 1 + +/** @brief Initialize the Settings Manager. + * @return ESP_OK on success, ESP_ERR_* on failure + */ +esp_err_t SettingsManager_Init(void); + +/** @brief Deinitialize the Settings Manager. + * @return ESP_OK on success + */ +esp_err_t SettingsManager_Deinit(void); + +/** @brief Load all settings from NVS. + * If settings don't exist, factory defaults are used. + * @param p_Settings Pointer to settings structure to populate + * @return ESP_OK on success, ESP_ERR_NVS_NOT_FOUND if no settings exist + */ +esp_err_t SettingsManager_Load(App_Settings_t *p_Settings); + +/** @brief Save all settings to NVS. + * @param p_Settings Pointer to settings structure to save + * @return ESP_OK on success, ESP_ERR_* on failure + */ +esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings); + +/** @brief Get current settings (cached in RAM). + * @param p_Settings Pointer to settings structure to populate + * @return ESP_OK on success + */ +esp_err_t SettingsManager_Get(App_Settings_t *p_Settings); + +/** @brief Update Lepton settings. + * Changes are cached and broadcasted via SETTINGS_EVENT_LEPTON_CHANGED. + * @param p_Lepton Pointer to Lepton settings + * @return ESP_OK on success + */ +esp_err_t SettingsManager_SetLepton(const App_Settings_Lepton_t *p_Lepton); + +/** @brief Update WiFi settings. + * Changes are cached and broadcasted via SETTINGS_EVENT_WIFI_CHANGED. + * @param p_WiFi Pointer to WiFi settings + * @return ESP_OK on success + */ +esp_err_t SettingsManager_SetWiFi(const App_Settings_WiFi_t *p_WiFi); + +/** @brief Update Display settings. + * Changes are cached and broadcasted via SETTINGS_EVENT_DISPLAY_CHANGED. + * @param p_Display Pointer to Display settings + * @return ESP_OK on success + */ +esp_err_t SettingsManager_SetDisplay(const App_Settings_Display_t *p_Display); + +/** @brief Update System settings. + * Changes are cached and broadcasted via SETTINGS_EVENT_SYSTEM_CHANGED. + * @param p_System Pointer to System settings + * @return ESP_OK on success + */ +esp_err_t SettingsManager_SetSystem(const App_Settings_System_t *p_System); + +/** @brief Reset all settings to factory defaults. + * Erases NVS partition and reloads defaults. + * @return ESP_OK on success + */ +esp_err_t SettingsManager_ResetToDefaults(void); + +/** @brief Get factory default settings. + * @param p_Settings Pointer to settings structure to populate with defaults + * @return ESP_OK on success + */ +esp_err_t SettingsManager_GetDefaults(App_Settings_t *p_Settings); + +/** @brief Commit cached settings to NVS storage. + * Should be called periodically or on shutdown to persist changes. + * @return ESP_OK on success + */ +esp_err_t SettingsManager_Commit(void); + +/** @brief Check if settings have unsaved changes. + * @return true if changes are pending, false otherwise + */ +bool SettingsManager_HasPendingChanges(void); + +#endif /* SETTINGS_MANAGER_H_ */ diff --git a/main/Application/Manager/Settings/settings_types.h b/main/Application/Manager/Settings/settings_types.h new file mode 100644 index 0000000..b695998 --- /dev/null +++ b/main/Application/Manager/Settings/settings_types.h @@ -0,0 +1,107 @@ +/* + * settings_types.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Settings Manager event types and definitions. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef SETTINGS_TYPES_H_ +#define SETTINGS_TYPES_H_ + +#include + +/** @brief Settings Manager events base. + */ +ESP_EVENT_DECLARE_BASE(SETTINGS_EVENTS); + +/** @brief Settings event identifiers. + */ +enum { + SETTINGS_EVENT_LOADED, /**< Settings loaded from NVS. */ + SETTINGS_EVENT_SAVED, /**< Settings saved to NVS. */ + SETTINGS_EVENT_CHANGED, /**< Settings changed. Data contains App_Settings_t structure. */ + SETTINGS_EVENT_LEPTON_CHANGED, /**< Lepton settings changed. + Data contains App_Settings_Lepton_t. */ + SETTINGS_EVENT_WIFI_CHANGED, /**< WiFi settings changed. + Data contains App_Settings_WiFi_t. */ + SETTINGS_EVENT_DISPLAY_CHANGED, /**< Display settings changed. + Data contains App_Settings_Display_t. */ + SETTINGS_EVENT_SYSTEM_CHANGED, /**< System settings changed. + Data contains App_Settings_System_t. */ + SETTINGS_EVENT_REQUEST_GET, /**< Request to get current settings. */ + SETTINGS_EVENT_REQUEST_SAVE, /**< Request to save settings to NVS. */ + SETTINGS_EVENT_REQUEST_RESET, /**< Request to reset settings to factory defaults. */ +}; + +/** @brief Region of Interest (ROI) rectangle definition. + */ +typedef struct { + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} App_Settings_ROI_t; + +/** @brief Lepton camera settings. + */ +typedef struct { + App_Settings_ROI_t SpotmeterROI; /**< Spotmeter Region of Interest. */ + uint8_t Reserved[100]; /**< Reserved for future use. */ +} App_Settings_Lepton_t; + +/** @brief WiFi settings. + */ +typedef struct { + char SSID[32]; /**< WiFi SSID. */ + char Password[64]; /**< WiFi password. */ + bool AP_Mode; /**< Access Point mode (true) or Station mode (false). */ + char AP_SSID[32]; /**< AP mode SSID. */ + char AP_Password[64]; /**< AP mode password. */ + uint8_t Reserved[100]; /**< Reserved for future use. */ +} App_Settings_WiFi_t; + +/** @brief Display settings. + */ +typedef struct { + uint8_t Brightness; /**< Display brightness (0-100%). */ + uint16_t ScreenTimeout; /**< Screen timeout in seconds (0=never). */ + uint8_t Reserved[100]; /**< Reserved for future use. */ +} App_Settings_Display_t; + +/** @brief System settings. + */ +typedef struct { + char DeviceName[32]; /**< Device name. */ + bool SDCard_AutoMount; /**< Automatically mount SD card. */ + bool Bluetooth_Enabled; /**< Bluetooth enabled. */ + char Timezone[32]; /**< Timezone string (e.g., "CET-1CEST,M3.5.0,M10.5.0/3"). */ + uint8_t Reserved[100]; /**< Reserved for future use. */ +} App_Settings_System_t; + +/** @brief Complete application settings structure. + */ +typedef struct { + uint32_t Version; /**< Settings version for migration. */ + App_Settings_Lepton_t Lepton; /**< Lepton camera settings. */ + App_Settings_WiFi_t WiFi; /**< WiFi settings. */ + App_Settings_Display_t Display; /**< Display settings. */ + App_Settings_System_t System; /**< System settings. */ +} App_Settings_t; + +#endif /* SETTINGS_TYPES_H_ */ diff --git a/main/Application/Manager/Time/timeManager.cpp b/main/Application/Manager/Time/timeManager.cpp new file mode 100644 index 0000000..52c1166 --- /dev/null +++ b/main/Application/Manager/Time/timeManager.cpp @@ -0,0 +1,400 @@ +/* + * timeManager.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Unified time management with SNTP and RTC backup. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include +#include + +#include + +#include "timeManager.h" +#include "../Devices/RTC/rtc.h" + +ESP_EVENT_DEFINE_BASE(TIME_EVENTS); + +#define TIME_MANAGER_SYNC_INTERVAL_SEC 3600 /* Sync every hour */ +#define TIME_MANAGER_RTC_BACKUP_INTERVAL_SEC 300 /* Save to RTC every 5 minutes */ +#define TIME_MANAGER_VALID_YEAR_MIN 2025 /* Minimum valid year */ + +typedef struct { + bool isInitialized; + bool hasRTC; + bool hasNetwork; + bool timeSynchronized; + i2c_master_dev_handle_t RTC_Handle; + TimeManager_Source_t activeSource; + time_t lastSNTP_Sync; + time_t lastRTC_Sync; + time_t lastRTC_Backup; + uint32_t sntpSyncCount; + uint32_t rtcSyncCount; + esp_timer_handle_t syncTimer; +} TimeManager_State_t; + +static TimeManager_State_t _TimeManager_State; + +static const char *TAG = "time-manager"; + +/** @brief SNTP time synchronization notification callback. + * @param tv Pointer to the synchronized time value + */ +static void TimeManager_SNTP_Sync_Callback(struct timeval *tv) +{ + time_t Now = tv->tv_sec; + struct tm Timeinfo; + + localtime_r(&Now, &Timeinfo); + + ESP_LOGD(TAG, "SNTP time synchronized: %04d-%02d-%02d %02d:%02d:%02d", + Timeinfo.tm_year + 1900, Timeinfo.tm_mon + 1, Timeinfo.tm_mday, + Timeinfo.tm_hour, Timeinfo.tm_min, Timeinfo.tm_sec); + + _TimeManager_State.lastSNTP_Sync = Now; + _TimeManager_State.activeSource = TIME_SOURCE_SNTP; + _TimeManager_State.timeSynchronized = true; + _TimeManager_State.sntpSyncCount++; + + /* Post time synchronized event */ + esp_event_post(TIME_EVENTS, TIME_EVENT_SYNCHRONIZED, &Timeinfo, sizeof(struct tm), portMAX_DELAY); + + /* Backup time to RTC if available */ + if (_TimeManager_State.hasRTC) { + esp_err_t Error; + + Error = RTC_SetTime(&Timeinfo); + if (Error == ESP_OK) { + _TimeManager_State.lastRTC_Backup = Now; + ESP_LOGD(TAG, "Time backed up to RTC"); + } else { + ESP_LOGW(TAG, "Failed to backup time to RTC: %d!", Error); + } + } +} + +/** @brief Periodic timer callback for time synchronization. + * @param p_Arg Timer argument + */ +static void TimeManager_Sync_Timer_Callback(void *p_Arg) +{ + time_t Now; + + time(&Now); + + /* If network is available and SNTP sync is due */ + if (_TimeManager_State.hasNetwork) { + time_t TimeSinceSync; + + TimeSinceSync = Now - _TimeManager_State.lastSNTP_Sync; + + if (TimeSinceSync >= TIME_MANAGER_SYNC_INTERVAL_SEC) { + ESP_LOGD(TAG, "Periodic SNTP synchronization (last sync: %ld sec ago)", TimeSinceSync); + + /* Restart SNTP to trigger new sync */ + esp_sntp_restart(); + } + + /* Backup system time to RTC periodically */ + if (_TimeManager_State.hasRTC && _TimeManager_State.timeSynchronized) { + time_t TimeSinceBackup = Now - _TimeManager_State.lastRTC_Backup; + + if (TimeSinceBackup >= TIME_MANAGER_RTC_BACKUP_INTERVAL_SEC) { + struct tm Timeinfo; + localtime_r(&Now, &Timeinfo); + + if (RTC_SetTime(&Timeinfo) == ESP_OK) { + ESP_LOGD(TAG, "Periodic RTC backup"); + + _TimeManager_State.lastRTC_Backup = Now; + } + } + } + } +} + +esp_err_t TimeManager_Init(void *p_RTC_Handle) +{ + esp_err_t Error; + + if (_TimeManager_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + ESP_LOGD(TAG, "Initializing Time Manager"); + + memset(&_TimeManager_State, 0, sizeof(TimeManager_State_t)); + + /* Store RTC handle if available */ + if (p_RTC_Handle != NULL) { + esp_err_t RtcError; + struct tm RtcTime; + + _TimeManager_State.RTC_Handle = *(i2c_master_dev_handle_t *)p_RTC_Handle; + _TimeManager_State.hasRTC = true; + ESP_LOGD(TAG, "RTC available for time backup"); + + /* Try to load time from RTC */ + RtcError = RTC_GetTime(&RtcTime); + if (RtcError == ESP_OK) { + /* Validate RTC time (check if year is reasonable) */ + if ((RtcTime.tm_year + 1900) >= TIME_MANAGER_VALID_YEAR_MIN) { + /* Set system time from RTC */ + time_t T = mktime(&RtcTime); + struct timeval Tv = {.tv_sec = T, .tv_usec = 0}; + + settimeofday(&Tv, NULL); + + _TimeManager_State.activeSource = TIME_SOURCE_RTC; + _TimeManager_State.timeSynchronized = true; + _TimeManager_State.lastRTC_Sync = T; + _TimeManager_State.rtcSyncCount++; + + ESP_LOGD(TAG, "System time initialized from RTC: %04d-%02d-%02d %02d:%02d:%02d", + RtcTime.tm_year + 1900, RtcTime.tm_mon + 1, RtcTime.tm_mday, + RtcTime.tm_hour, RtcTime.tm_min, RtcTime.tm_sec); + } else { + ESP_LOGW(TAG, "RTC time invalid (year: %d), waiting for SNTP", + RtcTime.tm_year + 1900); + } + } else { + ESP_LOGW(TAG, "Failed to read time from RTC: %d!", RtcError); + } + } else { + ESP_LOGD(TAG, "No RTC available, SNTP will be primary time source"); + } + + /* Set timezone to UTC by default */ + setenv("TZ", "UTC-0", 1); + tzset(); + + /* Create periodic sync timer */ + const esp_timer_create_args_t TimerArgs = { + .callback = &TimeManager_Sync_Timer_Callback, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "time_sync", + .skip_unhandled_events = false, + }; + + Error = esp_timer_create(&TimerArgs, &_TimeManager_State.syncTimer); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to create sync timer: %d!", Error); + return Error; + } + + /* Start timer with 60 second period */ + Error = esp_timer_start_periodic(_TimeManager_State.syncTimer, 60 * 1000000ULL); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to start sync timer: %d!", Error); + esp_timer_delete(_TimeManager_State.syncTimer); + return Error; + } + + _TimeManager_State.isInitialized = true; + + ESP_LOGD(TAG, "Time Manager initialized (Source: %s)", + _TimeManager_State.activeSource == TIME_SOURCE_RTC ? "RTC" : + _TimeManager_State.activeSource == TIME_SOURCE_SNTP ? "SNTP" : "None"); + + return ESP_OK; +} + +esp_err_t TimeManager_Deinit(void) +{ + if (_TimeManager_State.isInitialized == false) { + return ESP_OK; + } + + if (_TimeManager_State.syncTimer != NULL) { + esp_timer_stop(_TimeManager_State.syncTimer); + esp_timer_delete(_TimeManager_State.syncTimer); + _TimeManager_State.syncTimer = NULL; + } + + if (esp_sntp_enabled()) { + esp_sntp_stop(); + } + + _TimeManager_State.isInitialized = false; + + ESP_LOGD(TAG, "Time Manager deinitialized"); + + return ESP_OK; +} + +esp_err_t TimeManager_OnNetworkConnected(void) +{ + ESP_LOGD(TAG, "Network connected, starting SNTP synchronization"); + + _TimeManager_State.hasNetwork = true; + + /* Initialize SNTP if not already done */ + if (esp_sntp_enabled()) { + /* Restart SNTP to immediately try to sync time */ + esp_sntp_restart(); + } else { + /* First time init */ + esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); + esp_sntp_setservername(0, "pool.ntp.org"); + sntp_set_time_sync_notification_cb(TimeManager_SNTP_Sync_Callback); + esp_sntp_init(); + ESP_LOGD(TAG, "SNTP initialized"); + } + + return ESP_OK; +} + +esp_err_t TimeManager_OnNetworkDisconnected(void) +{ + ESP_LOGD(TAG, "Network disconnected, switching to RTC time source"); + + _TimeManager_State.hasNetwork = false; + + /* Switch to RTC if available */ + if (_TimeManager_State.hasRTC) { + TimeManager_Source_t OldSource = _TimeManager_State.activeSource; + _TimeManager_State.activeSource = TIME_SOURCE_RTC; + + /* Post source changed event if source actually changed */ + if (OldSource != TIME_SOURCE_RTC) { + esp_event_post(TIME_EVENTS, TIME_EVENT_SOURCE_CHANGED, + &_TimeManager_State.activeSource, + sizeof(TimeManager_Source_t), portMAX_DELAY); + } + + ESP_LOGD(TAG, "Now using RTC as time source"); + } else { + ESP_LOGW(TAG, "No RTC available, system time will drift"); + _TimeManager_State.activeSource = TIME_SOURCE_SYSTEM; + } + + return ESP_OK; +} + +esp_err_t TimeManager_GetTime(struct tm *p_Time, TimeManager_Source_t *p_Source) +{ + time_t Now; + + if (p_Time == NULL) { + return ESP_ERR_INVALID_ARG; + } + + time(&Now); + + localtime_r(&Now, p_Time); + + if (p_Source != NULL) { + *p_Source = _TimeManager_State.activeSource; + } + + return ESP_OK; +} + +esp_err_t TimeManager_GetTimestamp(time_t *p_Time, TimeManager_Source_t *p_Source) +{ + if (p_Time == NULL) { + return ESP_ERR_INVALID_ARG; + } + + time(p_Time); + + if (p_Source != NULL) { + *p_Source = _TimeManager_State.activeSource; + } + + return ESP_OK; +} + +esp_err_t TimeManager_GetStatus(TimeManager_Status_t *p_Status) +{ + if (p_Status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + p_Status->ActiveSource = _TimeManager_State.activeSource; + p_Status->SNTP_Available = _TimeManager_State.hasNetwork; + p_Status->RTC_Available = _TimeManager_State.hasRTC; + p_Status->LastSync_SNTP = _TimeManager_State.lastSNTP_Sync; + p_Status->LastSync_RTC = _TimeManager_State.lastRTC_Sync; + p_Status->SNTP_SyncCount = _TimeManager_State.sntpSyncCount; + p_Status->RTC_SyncCount = _TimeManager_State.rtcSyncCount; + + return ESP_OK; +} + +esp_err_t TimeManager_ForceSync(void) +{ + if (_TimeManager_State.hasNetwork == false) { + ESP_LOGW(TAG, "Cannot force sync: no network connection"); + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGD(TAG, "Forcing SNTP synchronization"); + esp_sntp_restart(); + + return ESP_OK; +} + +bool TimeManager_IsTimeSynchronized(void) +{ + return _TimeManager_State.timeSynchronized; +} + +esp_err_t TimeManager_GetTimeString(char *p_Buffer, size_t Size, const char *Format) +{ + esp_err_t Error; + struct tm Timeinfo; + size_t Written; + + if ((p_Buffer == NULL) || (Format == NULL) || (Size == 0)) { + return ESP_ERR_INVALID_ARG; + } + + Error = TimeManager_GetTime(&Timeinfo, NULL); + if (Error != ESP_OK) { + return Error; + } + + Written = strftime(p_Buffer, Size, Format, &Timeinfo); + if (Written == 0) { + return ESP_ERR_NO_MEM; + } + + return ESP_OK; +} + +esp_err_t TimeManager_SetTimezone(const char *p_Timezone) +{ + if (p_Timezone == NULL) { + return ESP_ERR_INVALID_ARG; + } + + ESP_LOGD(TAG, "Setting timezone to: %s", p_Timezone); + + setenv("TZ", p_Timezone, 1); + tzset(); + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/Time/timeManager.h b/main/Application/Manager/Time/timeManager.h new file mode 100644 index 0000000..be4d056 --- /dev/null +++ b/main/Application/Manager/Time/timeManager.h @@ -0,0 +1,125 @@ +/* + * timeManager.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Unified time management with SNTP and RTC backup. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef TIME_MANAGER_H_ +#define TIME_MANAGER_H_ + +#include +#include +#include + +#include "time_types.h" + +/** @brief Time source types. + */ +typedef enum { + TIME_SOURCE_NONE = 0, /**< No time source available. */ + TIME_SOURCE_RTC, /**< Time from RTC. */ + TIME_SOURCE_SNTP, /**< Time from SNTP. */ + TIME_SOURCE_SYSTEM, /**< Time from system (not synchronized). */ +} TimeManager_Source_t; + +/** @brief Time synchronization status. + */ +typedef struct { + TimeManager_Source_t ActiveSource; /**< Currently active time source. */ + bool SNTP_Available; /**< SNTP available (network connected). */ + bool RTC_Available; /**< RTC available. */ + time_t LastSync_SNTP; /**< Timestamp of last SNTP sync. */ + time_t LastSync_RTC; /**< Timestamp of last RTC sync. */ + uint32_t SNTP_SyncCount; /**< Number of successful SNTP syncs. */ + uint32_t RTC_SyncCount; /**< Number of RTC reads. */ +} TimeManager_Status_t; + +/** @brief Initialize the Time Manager. + * @param p_RTC_Handle Pointer to RTC device handle (NULL if RTC not available) + * @return ESP_OK on success + */ +esp_err_t TimeManager_Init(void *p_RTC_Handle); + +/** @brief Deinitialize the Time Manager. + * @return ESP_OK on success + */ +esp_err_t TimeManager_Deinit(void); + +/** @brief Called when network connection is established. + * Starts SNTP synchronization. + * @return ESP_OK on success + */ +esp_err_t TimeManager_OnNetworkConnected(void); + +/** @brief Called when network connection is lost. + * Switches to RTC as time source. + * @return ESP_OK on success + */ +esp_err_t TimeManager_OnNetworkDisconnected(void); + +/** @brief Get the current time (from best available source). + * @param p_Time Pointer to store the time + * @param p_Source Optional pointer to store the time source + * @return ESP_OK on success + */ +esp_err_t TimeManager_GetTime(struct tm *p_Time, TimeManager_Source_t *p_Source); + +/** @brief Get the current time as UNIX timestamp. + * @param p_Time Pointer to store the timestamp + * @param p_Source Optional pointer to store the time source + * @return ESP_OK on success + */ +esp_err_t TimeManager_GetTimestamp(time_t *p_Time, TimeManager_Source_t *p_Source); + +/** @brief Get the time manager status. + * @param p_Status Pointer to store the status + * @return ESP_OK on success + */ +esp_err_t TimeManager_GetStatus(TimeManager_Status_t *p_Status); + +/** @brief Force a time synchronization from SNTP (if available). + * @return ESP_OK on success + */ +esp_err_t TimeManager_ForceSync(void); + +/** @brief Check if time is synchronized and reliable. + * @return true if time is synchronized from SNTP or RTC + */ +bool TimeManager_IsTimeSynchronized(void); + +/** @brief Format the current time as string. + * @param p_Buffer Buffer to store the formatted time + * @param Size Buffer size + * @param Format Time format string (strftime format) + * @return ESP_OK on success + */ +esp_err_t TimeManager_GetTimeString(char *p_Buffer, size_t Size, const char *Format); + +/** @brief Set the timezone for time display. + * @param p_Timezone Timezone string in POSIX format + * Examples: + * - "UTC-0" for UTC + * - "CET-1CEST,M3.5.0,M10.5.0/3" for Central European Time + * - "EST5EDT,M3.2.0,M11.1.0" for US Eastern Time + * @return ESP_OK on success + */ +esp_err_t TimeManager_SetTimezone(const char *p_Timezone); + +#endif /* TIME_MANAGER_H_ */ diff --git a/main/Application/Manager/Time/time_types.h b/main/Application/Manager/Time/time_types.h new file mode 100644 index 0000000..b5a308a --- /dev/null +++ b/main/Application/Manager/Time/time_types.h @@ -0,0 +1,41 @@ +/* + * time_types.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Time Manager event types and definitions. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef TIME_TYPES_H_ +#define TIME_TYPES_H_ + +#include + +/** @brief Time Manager events base. + */ +ESP_EVENT_DECLARE_BASE(TIME_EVENTS); + +/** @brief Time Manager event IDs. + */ +typedef enum { + TIME_EVENT_SYNCHRONIZED, /**< Time synchronized from SNTP */ + TIME_EVENT_SOURCE_CHANGED, /**< Time source changed (SNTP/RTC/System) + Data is of type struct tm */ +} Time_Event_ID_t; + +#endif /* TIME_TYPES_H_ */ diff --git a/main/Application/Manager/managers.h b/main/Application/Manager/managers.h new file mode 100644 index 0000000..901698b --- /dev/null +++ b/main/Application/Manager/managers.h @@ -0,0 +1,33 @@ +/* + * managers.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef MANAGERS_H_ +#define MANAGERS_H_ + +#include "Network/networkManager.h" +#include "Devices/devicesManager.h" +#include "Time/timeManager.h" +#include "SD/sdManager.h" +#include "Settings/settingsManager.h" + +#endif /* MANAGERS_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/Devices/devicesTask.cpp b/main/Application/Tasks/Devices/devicesTask.cpp new file mode 100644 index 0000000..c149082 --- /dev/null +++ b/main/Application/Tasks/Devices/devicesTask.cpp @@ -0,0 +1,244 @@ +/* + * devicesTask.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Devices Task implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "devicesTask.h" +#include "Application/application.h" +#include "Application/Manager/Time/time_types.h" + +#define DEVICES_TASK_STOP_REQUEST BIT0 +#define DEVICES_TASK_TIME_SYNCED BIT1 + +ESP_EVENT_DEFINE_BASE(DEVICE_EVENTS); + +typedef struct { + bool isInitialized; + bool Running; + bool RunTask; + TaskHandle_t TaskHandle; + EventGroupHandle_t EventGroup; + uint32_t LastBatteryUpdate; + uint32_t LastTimeUpdate; + struct timeval TimeOfDay; +} Devices_Task_State_t; + +static Devices_Task_State_t _DevicesTask_State; + +static const char *TAG = "devices_task"; + +/** @brief Event handler for GUI events. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "GUI event received: ID=%d", ID); +} + +/** @brief Devices task main loop. + * @param p_Parameters Pointer to App_Context_t structure + */ +static void Task_Devices(void *p_Parameters) +{ + uint32_t Now; + App_Context_t *App_Context; + + esp_task_wdt_add(NULL); + + App_Context = reinterpret_cast(p_Parameters); + + ESP_LOGD(TAG, "Devices task started on core %d", xPortGetCoreID()); + + _DevicesTask_State.RunTask = true; + while (_DevicesTask_State.RunTask) { + EventBits_t EventBits; + + esp_task_wdt_reset(); + + EventBits = xEventGroupGetBits(_DevicesTask_State.EventGroup); + if (EventBits & DEVICES_TASK_STOP_REQUEST) { + ESP_LOGD(TAG, "Stop request received"); + + xEventGroupClearBits(_DevicesTask_State.EventGroup, DEVICES_TASK_STOP_REQUEST); + + break; + } + + Now = esp_timer_get_time() / 1000; + + if ((Now - _DevicesTask_State.LastBatteryUpdate) >= 1000) { + App_Devices_Battery_t BatteryInfo; + + ESP_LOGD(TAG, "Updating battery voltage..."); + + if (DevicesManager_GetBatteryVoltage(&BatteryInfo.Voltage, &BatteryInfo.Percentage) == ESP_OK) { + esp_event_post(DEVICE_EVENTS, DEVICE_EVENT_RESPONSE_BATTERY_VOLTAGE, &BatteryInfo, sizeof(BatteryInfo), portMAX_DELAY); + } else { + ESP_LOGE(TAG, "Failed to read battery voltage!"); + } + + _DevicesTask_State.LastBatteryUpdate = esp_timer_get_time() / 1000; + } + + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + ESP_LOGD(TAG, "Devices task shutting down"); + DevicesManager_Deinit(); + + _DevicesTask_State.Running = false; + _DevicesTask_State.TaskHandle = NULL; + + esp_task_wdt_delete(NULL); + vTaskDelete(NULL); +} + +/** @brief Initialize the devices task. + * @return ESP_OK on success, error code otherwise + */ +esp_err_t DevicesTask_Init(void) +{ + esp_err_t Error; + + if (_DevicesTask_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + /* Create event group */ + _DevicesTask_State.EventGroup = xEventGroupCreate(); + if (_DevicesTask_State.EventGroup == NULL) { + ESP_LOGE(TAG, "Failed to create event group!"); + return ESP_ERR_NO_MEM; + } + + Error = DevicesManager_Init(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize Devices Manager: %d!", Error); + return Error; + } + + /* Use the event loop to receive control signals from other tasks */ + esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL); + + _DevicesTask_State.isInitialized = true; + + return ESP_OK; +} + +void DevicesTask_Deinit(void) +{ + if (_DevicesTask_State.isInitialized == false) { + return; + } + + esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); + + DevicesManager_Deinit(); + + if (_DevicesTask_State.EventGroup != NULL) { + vEventGroupDelete(_DevicesTask_State.EventGroup); + _DevicesTask_State.EventGroup = NULL; + } + + _DevicesTask_State.isInitialized = false; + + return; +} + +esp_err_t DevicesTask_Start(App_Context_t *p_AppContext) +{ + BaseType_t ret; + + if (p_AppContext == NULL) { + return ESP_ERR_INVALID_ARG; + } else if (_DevicesTask_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (_DevicesTask_State.Running) { + ESP_LOGW(TAG, "Task already running"); + return ESP_OK; + } + + ESP_LOGD(TAG, "Starting Devices Task"); + + ret = xTaskCreatePinnedToCore( + Task_Devices, + "Task_Devices", + CONFIG_DEVICES_TASK_STACKSIZE, + p_AppContext, + CONFIG_DEVICES_TASK_PRIO, + &_DevicesTask_State.TaskHandle, + CONFIG_DEVICES_TASK_CORE + ); + + if (ret != pdPASS) { + ESP_LOGE(TAG, "Failed to create Devices Task: %d!", ret); + return ESP_ERR_NO_MEM; + } + + _DevicesTask_State.Running = true; + + return ESP_OK; +} + +esp_err_t DevicesTask_Task_Stop(void) +{ + if (_DevicesTask_State.Running == false) { + return ESP_OK; + } + + ESP_LOGD(TAG, "Stopping Devices Task"); + xEventGroupSetBits(_DevicesTask_State.EventGroup, DEVICES_TASK_STOP_REQUEST); + + /* Wait for task to exit (with timeout) */ + for (uint8_t i = 0; i < 100 && _DevicesTask_State.Running; i++) { + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + if (_DevicesTask_State.Running) { + ESP_LOGE(TAG, "Task did not stop in time"); + return ESP_ERR_TIMEOUT; + } + + _DevicesTask_State.TaskHandle = NULL; + + return ESP_OK; +} + +bool DevicesTask_Task_isRunning(void) +{ + return _DevicesTask_State.Running; +} \ No newline at end of file diff --git a/main/Application/Tasks/Devices/devicesTask.h b/main/Application/Tasks/Devices/devicesTask.h new file mode 100644 index 0000000..763ee41 --- /dev/null +++ b/main/Application/Tasks/Devices/devicesTask.h @@ -0,0 +1,44 @@ +/* + * devicesTask.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Devices task for peripheral monitoring and management. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef DEVICESTASK_H_ +#define DEVICESTASK_H_ + +#include +#include + +#include + +#include "Application/application.h" + +esp_err_t DevicesTask_Init(void); + +void DevicesTask_Deinit(void); + +esp_err_t DevicesTask_Start(App_Context_t *p_AppContext); + +esp_err_t DevicesTask_Stop(void); + +bool DevicesTask_isRunning(void); + +#endif /* DEVICESTASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/Export/CMakeLists.txt b/main/Application/Tasks/GUI/Export/CMakeLists.txt new file mode 100644 index 0000000..a135262 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/CMakeLists.txt @@ -0,0 +1,13 @@ +SET(SOURCES screens/ui_Splash.c + screens/ui_Main.c + screens/ui_Menu.c + screens/ui_Info.c + ui.c + components/ui_comp_hook.c + ui_helpers.c + ui_events.cpp + images/ui_img_logo_80x44_png.c + images/ui_img_text_218x40_png.c + fonts/ui_font_fa.c) + +add_library(ui ${SOURCES}) diff --git a/main/Application/Tasks/GUI/Export/components/ui_comp_hook.c b/main/Application/Tasks/GUI/Export/components/ui_comp_hook.c new file mode 100644 index 0000000..d00cee9 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/components/ui_comp_hook.c @@ -0,0 +1,5 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + diff --git a/main/Application/Tasks/GUI/Export/filelist.txt b/main/Application/Tasks/GUI/Export/filelist.txt new file mode 100644 index 0000000..49c08b9 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/filelist.txt @@ -0,0 +1,11 @@ +screens/ui_Splash.c +screens/ui_Main.c +screens/ui_Menu.c +screens/ui_Info.c +ui.c +components/ui_comp_hook.c +ui_helpers.c +ui_events.cpp +images/ui_img_logo_80x44_png.c +images/ui_img_text_218x40_png.c +fonts/ui_font_fa.c diff --git a/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c b/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c new file mode 100644 index 0000000..4544656 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c @@ -0,0 +1,17288 @@ +/******************************************************************************* + * Size: 16 px + * Bpp: 1 + * Opts: --bpp 1 --size 16 --font C:/Users/konta/Desktop/ThermalCam/firmware/ui/assets/Font-Awesome/otfs/Font Awesome 7 Free-Solid-900.otf -o C:/Users/konta/Desktop/ThermalCam/firmware/ui/assets/Font-Awesome/otfs\ui_font_fa.c --format lvgl -r 0x20-0xFFFF --no-compress --no-prefilter + ******************************************************************************/ + +#include "../ui.h" + +#ifndef UI_FONT_FA +#define UI_FONT_FA 1 +#endif + +#if UI_FONT_FA + +/*----------------- + * BITMAPS + *----------------*/ + +/*Store the image of the glyphs*/ +static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { + /* U+0020 " " */ + 0x0, + + /* U+0021 "!" */ + 0xff, 0xff, 0xff, 0xf, + + /* U+0022 "\"" */ + 0x0, + + /* U+0023 "#" */ + 0x2, 0xc, 0x6, 0xc, 0x6, 0x18, 0x6, 0x18, + 0x7f, 0xff, 0x7f, 0xff, 0xc, 0x38, 0xc, 0x30, + 0xc, 0x30, 0x1c, 0x30, 0xff, 0xfe, 0xff, 0xfe, + 0x18, 0x60, 0x18, 0x60, 0x30, 0x60, 0x30, 0x40, + + /* U+0024 "$" */ + 0x18, 0xc, 0x1f, 0xdf, 0xec, 0x6, 0x3, 0x80, + 0xfc, 0x3f, 0x1, 0xc0, 0x60, 0x37, 0xf3, 0xf0, + 0x60, 0x30, + + /* U+0025 "%" */ + 0x78, 0xf, 0xf0, 0x7f, 0xc3, 0xbf, 0x1c, 0xfc, + 0xe1, 0xe7, 0x0, 0x38, 0x1, 0xc0, 0xe, 0x78, + 0x73, 0xf3, 0x8f, 0xdc, 0x3f, 0xe0, 0xff, 0x1, + 0xe0, + + /* U+0026 "&" */ + 0x0, + + /* U+0027 "'" */ + 0x0, + + /* U+0028 "(" */ + 0x0, + + /* U+0029 ")" */ + 0x0, + + /* U+002A "*" */ + 0x3, 0x0, 0xc, 0x0, 0x30, 0x0, 0xc0, 0xe3, + 0x1d, 0xed, 0xe3, 0xff, 0x3, 0xf0, 0xf, 0xc0, + 0xff, 0xc7, 0xb7, 0xb8, 0xc7, 0x3, 0x0, 0xc, + 0x0, 0x30, 0x0, 0xc0, + + /* U+002B "+" */ + 0x3, 0x0, 0xc, 0x0, 0x30, 0x0, 0xc0, 0x3, + 0x0, 0xc, 0xf, 0xff, 0xff, 0xff, 0x3, 0x0, + 0xc, 0x0, 0x30, 0x0, 0xc0, 0x3, 0x0, 0xc, + 0x0, + + /* U+002C "," */ + 0x0, + + /* U+002D "-" */ + 0xff, 0xff, 0xf0, + + /* U+002E "." */ + 0x0, + + /* U+002F "/" */ + 0x0, + + /* U+0030 "0" */ + 0x1e, 0x1f, 0xe6, 0x1b, 0x3, 0xc0, 0xf0, 0x3c, + 0xf, 0x3, 0xc0, 0xf0, 0x3c, 0xd, 0x86, 0x7f, + 0x87, 0x80, + + /* U+0031 "1" */ + 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, + + /* U+0032 "2" */ + 0x7f, 0x1f, 0xe0, 0xc, 0x3, 0x1, 0xc1, 0xe1, + 0xf0, 0xf0, 0x70, 0x30, 0xc, 0x3, 0x0, 0xff, + 0xff, 0xf0, + + /* U+0033 "3" */ + 0xff, 0x3f, 0xe0, 0x1c, 0x3, 0x0, 0xc0, 0x73, + 0xf8, 0xfe, 0x1, 0xc0, 0x30, 0xc, 0x7, 0xff, + 0xbf, 0xc0, + + /* U+0034 "4" */ + 0xc0, 0xcc, 0xc, 0xc0, 0xcc, 0xc, 0xc0, 0xcc, + 0xc, 0xc0, 0xcc, 0xc, 0xff, 0xf7, 0xff, 0x0, + 0xc0, 0xc, 0x0, 0xc0, 0xc, + + /* U+0035 "5" */ + 0xff, 0xbf, 0xec, 0x3, 0x0, 0xc0, 0x30, 0xf, + 0xf3, 0xfe, 0x1, 0xc0, 0x30, 0xc, 0x7, 0xff, + 0xbf, 0xc0, + + /* U+0036 "6" */ + 0x1f, 0x8f, 0xf1, 0x80, 0x60, 0xc, 0x1, 0xfe, + 0x3f, 0xf7, 0x6, 0xc0, 0x78, 0xf, 0x1, 0xf0, + 0x77, 0xfc, 0x7f, 0x0, + + /* U+0037 "7" */ + 0xff, 0xff, 0xf0, 0x18, 0xe, 0x3, 0x1, 0xc0, + 0x60, 0x30, 0x1c, 0x6, 0x3, 0x80, 0xc0, 0x60, + 0x18, 0x0, + + /* U+0038 "8" */ + 0x1f, 0xf, 0xe7, 0x1d, 0x83, 0x60, 0xdc, 0x73, + 0xf9, 0xfe, 0xe1, 0xf0, 0x3c, 0xf, 0x87, 0x7f, + 0x8f, 0xc0, + + /* U+0039 "9" */ + 0x1f, 0xf, 0xfb, 0x83, 0xe0, 0x3c, 0x7, 0x80, + 0xf8, 0x3b, 0xff, 0x1f, 0xe0, 0xc, 0x1, 0x80, + 0x63, 0xfc, 0x7e, 0x0, + + /* U+003A ":" */ + 0x0, + + /* U+003B ";" */ + 0x0, + + /* U+003C "<" */ + 0x0, 0x6, 0x0, 0x3c, 0x1, 0xe0, 0x1f, 0x0, + 0xf8, 0x7, 0xc0, 0x3e, 0x0, 0x78, 0x0, 0x3e, + 0x0, 0x1f, 0x0, 0xf, 0x80, 0x7, 0xc0, 0x1, + 0xe0, 0x0, 0xc0, + + /* U+003D "=" */ + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, + + /* U+003E ">" */ + 0xc0, 0x1, 0xe0, 0x0, 0xf0, 0x0, 0x7c, 0x0, + 0x3e, 0x0, 0x1f, 0x0, 0xf, 0x80, 0xf, 0x0, + 0xf8, 0x7, 0xc0, 0x3e, 0x1, 0xf0, 0xf, 0x80, + 0x18, 0x0, 0x0, + + /* U+003F "?" */ + 0x1e, 0x1f, 0xe6, 0x1b, 0x3, 0xc0, 0xf0, 0x30, + 0xc, 0x6, 0x7, 0x83, 0xc0, 0xc0, 0x30, 0x0, + 0x0, 0x0, 0xc0, 0x30, + + /* U+0040 "@" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, + 0x63, 0xc6, 0xe7, 0xf7, 0xce, 0x73, 0xcc, 0x33, + 0xcc, 0x33, 0xce, 0x73, 0xe7, 0xff, 0x63, 0xde, + 0x70, 0x0, 0x3c, 0x0, 0x1f, 0x80, 0x7, 0x80, + + /* U+0041 "A" */ + 0x6, 0x0, 0x60, 0xf, 0x0, 0xf0, 0x1f, 0x81, + 0x98, 0x19, 0x83, 0xc, 0x30, 0xc7, 0xfe, 0x7f, + 0xe6, 0x6, 0xc0, 0x3c, 0x3, + + /* U+0042 "B" */ + 0xfe, 0x3f, 0xcc, 0x3b, 0x6, 0xc1, 0xb0, 0xef, + 0xf3, 0xfe, 0xc1, 0xf0, 0x3c, 0xf, 0x7, 0xff, + 0xbf, 0xc0, + + /* U+0043 "C" */ + 0x0, 0x0, 0x7f, 0x7, 0xfc, 0x70, 0x37, 0x0, + 0x30, 0x1, 0x80, 0xc, 0x0, 0x60, 0x3, 0x0, + 0x1c, 0x0, 0x70, 0x31, 0xff, 0x87, 0xf0, 0x0, + 0x0, + + /* U+0044 "D" */ + 0xff, 0xf, 0xf8, 0xc1, 0xcc, 0x6, 0xc0, 0x7c, + 0x3, 0xc0, 0x3c, 0x3, 0xc0, 0x3c, 0x7, 0xc0, + 0x6c, 0x1c, 0xff, 0x8f, 0xf0, + + /* U+0045 "E" */ + 0xff, 0xff, 0xfc, 0x3, 0x0, 0xc0, 0x30, 0xf, + 0xf3, 0xfc, 0xc0, 0x30, 0xc, 0x3, 0x0, 0xff, + 0xff, 0xf0, + + /* U+0046 "F" */ + 0xff, 0xff, 0xfc, 0x3, 0x0, 0xc0, 0x30, 0xf, + 0xf3, 0xfc, 0xc0, 0x30, 0xc, 0x3, 0x0, 0xc0, + 0x30, 0x0, + + /* U+0047 "G" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0x0, 0xe0, + 0x3, 0x0, 0xc, 0x1f, 0xf0, 0x7f, 0xc0, 0xf, + 0x80, 0x76, 0x3, 0x8e, 0x1c, 0x1f, 0xe0, 0x3f, + 0x0, + + /* U+0048 "H" */ + 0xc0, 0x3c, 0x3, 0xc0, 0x3c, 0x3, 0xc0, 0x3c, + 0x3, 0xff, 0xff, 0xff, 0xc0, 0x3c, 0x3, 0xc0, + 0x3c, 0x3, 0xc0, 0x3c, 0x3, + + /* U+0049 "I" */ + 0xff, 0xff, 0xf0, 0xc0, 0x30, 0xc, 0x3, 0x0, + 0xc0, 0x30, 0xc, 0x3, 0x0, 0xc0, 0x30, 0xff, + 0xff, 0xf0, + + /* U+004A "J" */ + 0x0, 0xc0, 0x30, 0xc, 0x3, 0x0, 0xc0, 0x30, + 0xf, 0x3, 0xc0, 0xf0, 0x3c, 0xd, 0x86, 0x7f, + 0x87, 0x80, + + /* U+004B "K" */ + 0xc0, 0xf0, 0x7c, 0x3b, 0x1c, 0xce, 0x37, 0xf, + 0xc3, 0xf0, 0xe6, 0x31, 0xcc, 0x33, 0x6, 0xc1, + 0xf0, 0x30, + + /* U+004C "L" */ + 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x3, 0x1, + 0x80, 0xc0, 0x60, 0x30, 0x18, 0xf, 0xff, 0xfc, + + /* U+004D "M" */ + 0xc0, 0xf, 0x0, 0x3e, 0x1, 0xfc, 0xf, 0xf8, + 0x7f, 0x61, 0xbd, 0xce, 0xf3, 0xf3, 0xc7, 0x8f, + 0x1e, 0x3c, 0x30, 0xf0, 0x3, 0xc0, 0xf, 0x0, + 0x30, + + /* U+004E "N" */ + 0xc0, 0x3e, 0x3, 0xe0, 0x3f, 0x3, 0xd8, 0x3d, + 0xc3, 0xce, 0x3c, 0x73, 0xc3, 0xbc, 0x1b, 0xc0, + 0xfc, 0xf, 0xc0, 0x7c, 0x3, + + /* U+004F "O" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0x6, 0xe0, + 0x1f, 0x0, 0x3c, 0x0, 0xf0, 0x3, 0xc0, 0xf, + 0x80, 0x76, 0x1, 0x8e, 0x1c, 0x1f, 0xe0, 0x3f, + 0x0, + + /* U+0050 "P" */ + 0xfe, 0x3f, 0xec, 0x1b, 0x3, 0xc0, 0xf0, 0x3c, + 0xf, 0x6, 0xff, 0xbf, 0x8c, 0x3, 0x0, 0xc0, + 0x30, 0x0, + + /* U+0051 "Q" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0x6, 0xe0, + 0x1f, 0x0, 0x3c, 0x0, 0xf0, 0x63, 0xc1, 0xcf, + 0x83, 0xf6, 0x7, 0x8e, 0x1c, 0x1f, 0xf8, 0x3f, + 0x70, 0x0, 0xc0, + + /* U+0052 "R" */ + 0xff, 0x3f, 0xec, 0x1f, 0x3, 0xc0, 0xf0, 0x3c, + 0x1f, 0xfe, 0xff, 0x31, 0xcc, 0x33, 0x6, 0xc1, + 0xf0, 0x30, + + /* U+0053 "S" */ + 0x3f, 0x9f, 0xee, 0x3, 0x0, 0xc0, 0x38, 0x7, + 0xf0, 0xfe, 0x1, 0xc0, 0x30, 0xc, 0x7, 0x7f, + 0x9f, 0xc0, + + /* U+0054 "T" */ + 0xff, 0xff, 0xff, 0x6, 0x0, 0x60, 0x6, 0x0, + 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x6, 0x0, 0x60, + + /* U+0055 "U" */ + 0xc0, 0x3c, 0x3, 0xc0, 0x3c, 0x3, 0xc0, 0x3c, + 0x3, 0xc0, 0x3c, 0x3, 0xc0, 0x3c, 0x3, 0x60, + 0x67, 0xe, 0x3f, 0xc0, 0xf0, + + /* U+0056 "V" */ + 0xc0, 0x3c, 0x3, 0x60, 0x76, 0x6, 0x70, 0x63, + 0xc, 0x30, 0xc1, 0x98, 0x19, 0x81, 0xf8, 0xf, + 0x0, 0xf0, 0x6, 0x0, 0x60, + + /* U+0057 "W" */ + 0xc0, 0xc0, 0xf0, 0x30, 0x3e, 0x1c, 0x1d, 0x87, + 0x86, 0x61, 0xe1, 0x8c, 0x78, 0xc3, 0x33, 0x30, + 0xcc, 0xdc, 0x1b, 0x36, 0x7, 0xcf, 0x81, 0xe1, + 0xe0, 0x38, 0x70, 0xe, 0x1c, 0x1, 0x2, 0x0, + + /* U+0058 "X" */ + 0xc0, 0x3e, 0x7, 0x60, 0x63, 0xc, 0x19, 0x81, + 0xf8, 0xf, 0x0, 0xf0, 0x1f, 0x81, 0x98, 0x30, + 0xc7, 0xe, 0xe0, 0x7c, 0x3, + + /* U+0059 "Y" */ + 0xc0, 0x3e, 0x7, 0x60, 0x67, 0xe, 0x39, 0xc1, + 0x98, 0xf, 0x0, 0xf0, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x6, 0x0, 0x60, + + /* U+005A "Z" */ + 0xff, 0xff, 0xff, 0x0, 0xe0, 0xc, 0x1, 0x80, + 0x38, 0x7, 0x0, 0xe0, 0x1c, 0x1, 0x80, 0x30, + 0x7, 0x0, 0xff, 0xff, 0xff, + + /* U+005B "[" */ + 0x0, + + /* U+005C "\\" */ + 0x0, + + /* U+005D "]" */ + 0x0, + + /* U+005E "^" */ + 0x0, + + /* U+005F "_" */ + 0x0, + + /* U+0060 "`" */ + 0x0, + + /* U+0061 "a" */ + 0x6, 0x0, 0x60, 0xf, 0x0, 0xf0, 0x1f, 0x81, + 0x98, 0x19, 0x83, 0xc, 0x30, 0xc7, 0xfe, 0x7f, + 0xe6, 0x6, 0xc0, 0x3c, 0x3, + + /* U+0062 "b" */ + 0xfe, 0x3f, 0xcc, 0x3b, 0x6, 0xc1, 0xb0, 0xef, + 0xf3, 0xfe, 0xc1, 0xf0, 0x3c, 0xf, 0x7, 0xff, + 0xbf, 0xc0, + + /* U+0063 "c" */ + 0x0, 0x0, 0x7f, 0x7, 0xfc, 0x70, 0x37, 0x0, + 0x30, 0x1, 0x80, 0xc, 0x0, 0x60, 0x3, 0x0, + 0x1c, 0x0, 0x70, 0x31, 0xff, 0x87, 0xf0, 0x0, + 0x0, + + /* U+0064 "d" */ + 0xff, 0xf, 0xf8, 0xc1, 0xcc, 0x6, 0xc0, 0x7c, + 0x3, 0xc0, 0x3c, 0x3, 0xc0, 0x3c, 0x7, 0xc0, + 0x6c, 0x1c, 0xff, 0x8f, 0xf0, + + /* U+0065 "e" */ + 0xff, 0xff, 0xfc, 0x3, 0x0, 0xc0, 0x30, 0xf, + 0xf3, 0xfc, 0xc0, 0x30, 0xc, 0x3, 0x0, 0xff, + 0xff, 0xf0, + + /* U+0066 "f" */ + 0xff, 0xff, 0xfc, 0x3, 0x0, 0xc0, 0x30, 0xf, + 0xf3, 0xfc, 0xc0, 0x30, 0xc, 0x3, 0x0, 0xc0, + 0x30, 0x0, + + /* U+0067 "g" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0x0, 0xe0, + 0x3, 0x0, 0xc, 0x1f, 0xf0, 0x7f, 0xc0, 0xf, + 0x80, 0x76, 0x3, 0x8e, 0x1c, 0x1f, 0xe0, 0x3f, + 0x0, + + /* U+0068 "h" */ + 0xc0, 0x3c, 0x3, 0xc0, 0x3c, 0x3, 0xc0, 0x3c, + 0x3, 0xff, 0xff, 0xff, 0xc0, 0x3c, 0x3, 0xc0, + 0x3c, 0x3, 0xc0, 0x3c, 0x3, + + /* U+0069 "i" */ + 0xff, 0xff, 0xf0, 0xc0, 0x30, 0xc, 0x3, 0x0, + 0xc0, 0x30, 0xc, 0x3, 0x0, 0xc0, 0x30, 0xff, + 0xff, 0xf0, + + /* U+006A "j" */ + 0x0, 0xc0, 0x30, 0xc, 0x3, 0x0, 0xc0, 0x30, + 0xf, 0x3, 0xc0, 0xf0, 0x3c, 0xd, 0x86, 0x7f, + 0x87, 0x80, + + /* U+006B "k" */ + 0xc0, 0xf0, 0x7c, 0x3b, 0x1c, 0xce, 0x37, 0xf, + 0xc3, 0xf0, 0xe6, 0x31, 0xcc, 0x33, 0x6, 0xc1, + 0xf0, 0x30, + + /* U+006C "l" */ + 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x3, 0x1, + 0x80, 0xc0, 0x60, 0x30, 0x18, 0xf, 0xff, 0xfc, + + /* U+006D "m" */ + 0xc0, 0xf, 0x0, 0x3e, 0x1, 0xfc, 0xf, 0xf8, + 0x7f, 0x61, 0xbd, 0xce, 0xf3, 0xf3, 0xc7, 0x8f, + 0x1e, 0x3c, 0x30, 0xf0, 0x3, 0xc0, 0xf, 0x0, + 0x30, + + /* U+006E "n" */ + 0xc0, 0x3e, 0x3, 0xe0, 0x3f, 0x3, 0xd8, 0x3d, + 0xc3, 0xce, 0x3c, 0x73, 0xc3, 0xbc, 0x1b, 0xc0, + 0xfc, 0xf, 0xc0, 0x7c, 0x3, + + /* U+006F "o" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0x6, 0xe0, + 0x1f, 0x0, 0x3c, 0x0, 0xf0, 0x3, 0xc0, 0xf, + 0x80, 0x76, 0x1, 0x8e, 0x1c, 0x1f, 0xe0, 0x3f, + 0x0, + + /* U+0070 "p" */ + 0xfe, 0x3f, 0xec, 0x1b, 0x3, 0xc0, 0xf0, 0x3c, + 0xf, 0x6, 0xff, 0xbf, 0x8c, 0x3, 0x0, 0xc0, + 0x30, 0x0, + + /* U+0071 "q" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0x6, 0xe0, + 0x1f, 0x0, 0x3c, 0x0, 0xf0, 0x63, 0xc1, 0xcf, + 0x83, 0xf6, 0x7, 0x8e, 0x1c, 0x1f, 0xf8, 0x3f, + 0x70, 0x0, 0xc0, + + /* U+0072 "r" */ + 0xff, 0x3f, 0xec, 0x1f, 0x3, 0xc0, 0xf0, 0x3c, + 0x1f, 0xfe, 0xff, 0x31, 0xcc, 0x33, 0x6, 0xc1, + 0xf0, 0x30, + + /* U+0073 "s" */ + 0x3f, 0x9f, 0xee, 0x3, 0x0, 0xc0, 0x38, 0x7, + 0xf0, 0xfe, 0x1, 0xc0, 0x30, 0xc, 0x7, 0x7f, + 0x9f, 0xc0, + + /* U+0074 "t" */ + 0xff, 0xff, 0xff, 0x6, 0x0, 0x60, 0x6, 0x0, + 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x6, 0x0, 0x60, + + /* U+0075 "u" */ + 0xc0, 0x3c, 0x3, 0xc0, 0x3c, 0x3, 0xc0, 0x3c, + 0x3, 0xc0, 0x3c, 0x3, 0xc0, 0x3c, 0x3, 0x60, + 0x67, 0xe, 0x3f, 0xc0, 0xf0, + + /* U+0076 "v" */ + 0xc0, 0x3c, 0x3, 0x60, 0x76, 0x6, 0x70, 0x63, + 0xc, 0x30, 0xc1, 0x98, 0x19, 0x81, 0xf8, 0xf, + 0x0, 0xf0, 0x6, 0x0, 0x60, + + /* U+0077 "w" */ + 0xc0, 0xc0, 0xf0, 0x30, 0x3e, 0x1c, 0x1d, 0x87, + 0x86, 0x61, 0xe1, 0x8c, 0x78, 0xc3, 0x33, 0x30, + 0xcc, 0xdc, 0x1b, 0x36, 0x7, 0xcf, 0x81, 0xe1, + 0xe0, 0x38, 0x70, 0xe, 0x1c, 0x1, 0x2, 0x0, + + /* U+0078 "x" */ + 0xc0, 0x3e, 0x7, 0x60, 0x63, 0xc, 0x19, 0x81, + 0xf8, 0xf, 0x0, 0xf0, 0x1f, 0x81, 0x98, 0x30, + 0xc7, 0xe, 0xe0, 0x7c, 0x3, + + /* U+0079 "y" */ + 0xc0, 0x3e, 0x7, 0x60, 0x67, 0xe, 0x39, 0xc1, + 0x98, 0xf, 0x0, 0xf0, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x6, 0x0, 0x60, + + /* U+007A "z" */ + 0xff, 0xff, 0xff, 0x0, 0xe0, 0xc, 0x1, 0x80, + 0x38, 0x7, 0x0, 0xe0, 0x1c, 0x1, 0x80, 0x30, + 0x7, 0x0, 0xff, 0xff, 0xff, + + /* U+007B "{" */ + 0x0, + + /* U+007C "|" */ + 0x0, + + /* U+007D "}" */ + 0x0, + + /* U+007E "~" */ + 0x0, + + /* U+007F "" */ + 0x0, + + /* U+0080 "€" */ + 0x0, + + /* U+0081 "" */ + 0x0, + + /* U+0082 "‚" */ + 0x0, + + /* U+0083 "ƒ" */ + 0x0, + + /* U+0084 "„" */ + 0x0, + + /* U+0085 "…" */ + 0x0, + + /* U+0086 "†" */ + 0x0, + + /* U+0087 "‡" */ + 0x0, + + /* U+0088 "ˆ" */ + 0x0, + + /* U+0089 "‰" */ + 0x0, + + /* U+008A "Š" */ + 0x0, + + /* U+008B "‹" */ + 0x0, + + /* U+008C "Œ" */ + 0x0, + + /* U+008D "" */ + 0x0, + + /* U+008E "Ž" */ + 0x0, + + /* U+008F "" */ + 0x0, + + /* U+0090 "" */ + 0x0, + + /* U+0091 "‘" */ + 0x0, + + /* U+0092 "’" */ + 0x0, + + /* U+0093 "“" */ + 0x0, + + /* U+0094 "”" */ + 0x0, + + /* U+0095 "•" */ + 0x0, + + /* U+0096 "–" */ + 0x0, + + /* U+0097 "—" */ + 0x0, + + /* U+0098 "˜" */ + 0x0, + + /* U+0099 "™" */ + 0x0, + + /* U+009A "š" */ + 0x0, + + /* U+009B "›" */ + 0x0, + + /* U+009C "œ" */ + 0x0, + + /* U+009D "" */ + 0x0, + + /* U+009E "ž" */ + 0x0, + + /* U+009F "Ÿ" */ + 0x0, + + /* U+00A0 " " */ + 0x0, + + /* U+00A1 "¡" */ + 0x0, + + /* U+00A2 "¢" */ + 0x0, + + /* U+00A3 "£" */ + 0xf, 0xf, 0xe3, 0x1d, 0x80, 0x60, 0x1c, 0xf, + 0xfb, 0xfe, 0x30, 0xc, 0x6, 0x3, 0x80, 0xff, + 0xff, 0xf0, + + /* U+00A4 "¤" */ + 0x0, + + /* U+00A5 "¥" */ + 0x0, 0x6, 0x6, 0x60, 0x63, 0xc, 0x39, 0xc1, + 0x98, 0xf, 0x0, 0xf0, 0x3f, 0xc3, 0xfc, 0x6, + 0x3, 0xfc, 0x3f, 0xc0, 0x60, 0x6, 0x0, + + /* U+00A6 "¦" */ + 0x0, + + /* U+00A7 "§" */ + 0x0, + + /* U+00A8 "¨" */ + 0x0, + + /* U+00A9 "©" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xf8, 0x1f, 0xf9, 0x9f, 0xf3, 0xff, + 0xf3, 0xff, 0xfb, 0xdf, 0xf9, 0x1f, 0x7e, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+00AA "ª" */ + 0x0, + + /* U+00AB "«" */ + 0x6, 0x18, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, + 0x71, 0xc3, 0x8e, 0xe, 0x38, 0x38, 0xe0, 0xe3, + 0x83, 0x8e, 0xc, 0x30, + + /* U+00AC "¬" */ + 0x0, + + /* U+00AD "­" */ + 0x0, + + /* U+00AE "®" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7c, 0x3e, 0xfc, 0x1f, 0xfd, 0x9f, 0xfd, 0x9f, + 0xfc, 0x3f, 0xfd, 0x7f, 0xfd, 0x3f, 0x7d, 0xbe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+00AF "¯" */ + 0x0, + + /* U+00B0 "°" */ + 0x0, + + /* U+00B1 "±" */ + 0x0, + + /* U+00B2 "²" */ + 0x0, + + /* U+00B3 "³" */ + 0x0, + + /* U+00B4 "´" */ + 0x0, + + /* U+00B5 "µ" */ + 0x0, + + /* U+00B6 "¶" */ + 0x1f, 0xfc, 0x7f, 0xf9, 0xfe, 0x63, 0xfc, 0xc7, + 0xf9, 0x8f, 0xf3, 0x1f, 0xe6, 0x3f, 0xcc, 0x3f, + 0x98, 0x3f, 0x30, 0x6, 0x60, 0xc, 0xc0, 0x19, + 0x80, 0x33, 0x0, 0x66, 0x0, 0xcc, + + /* U+00B7 "·" */ + 0x0, + + /* U+00B8 "¸" */ + 0x0, + + /* U+00B9 "¹" */ + 0x0, + + /* U+00BA "º" */ + 0x0, + + /* U+00BB "»" */ + 0xc3, 0x7, 0x1c, 0x1c, 0x70, 0x71, 0xc1, 0xc7, + 0x7, 0x1c, 0x38, 0xe3, 0x8e, 0x38, 0xe3, 0x8e, + 0x38, 0xe1, 0x86, 0x0, + + /* U+00BC "¼" */ + 0x0, + + /* U+00BD "½" */ + 0x0, + + /* U+00BE "¾" */ + 0x0, + + /* U+00BF "¿" */ + 0x0, + + /* U+00C0 "À" */ + 0x0, + + /* U+00C1 "Á" */ + 0x0, + + /* U+00C2 "Â" */ + 0x0, + + /* U+00C3 "Ã" */ + 0x0, + + /* U+00C4 "Ä" */ + 0x0, + + /* U+00C5 "Å" */ + 0x0, + + /* U+00C6 "Æ" */ + 0x0, + + /* U+00C7 "Ç" */ + 0x0, + + /* U+00C8 "È" */ + 0x0, + + /* U+00C9 "É" */ + 0x0, + + /* U+00CA "Ê" */ + 0x0, + + /* U+00CB "Ë" */ + 0x0, + + /* U+00CC "Ì" */ + 0x0, + + /* U+00CD "Í" */ + 0x0, + + /* U+00CE "Î" */ + 0x0, + + /* U+00CF "Ï" */ + 0x0, + + /* U+00D0 "Ð" */ + 0x0, + + /* U+00D1 "Ñ" */ + 0x0, + + /* U+00D2 "Ò" */ + 0x0, + + /* U+00D3 "Ó" */ + 0x0, + + /* U+00D4 "Ô" */ + 0x0, + + /* U+00D5 "Õ" */ + 0x0, + + /* U+00D6 "Ö" */ + 0x0, + + /* U+00D7 "×" */ + 0xc0, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, 0x80, + 0xf0, 0xf, 0x1, 0xf8, 0x39, 0xc7, 0xe, 0xe0, + 0x7c, 0x3, + + /* U+00D8 "Ø" */ + 0x0, + + /* U+00D9 "Ù" */ + 0x0, + + /* U+00DA "Ú" */ + 0x0, + + /* U+00DB "Û" */ + 0x0, + + /* U+00DC "Ü" */ + 0x0, + + /* U+00DD "Ý" */ + 0x0, + + /* U+00DE "Þ" */ + 0x0, + + /* U+00DF "ß" */ + 0x0, + + /* U+00E0 "à" */ + 0x0, + + /* U+00E1 "á" */ + 0x0, + + /* U+00E2 "â" */ + 0x0, + + /* U+00E3 "ã" */ + 0x0, + + /* U+00E4 "ä" */ + 0x0, + + /* U+00E5 "å" */ + 0x0, + + /* U+00E6 "æ" */ + 0x0, + + /* U+00E7 "ç" */ + 0x0, + + /* U+00E8 "è" */ + 0x0, + + /* U+00E9 "é" */ + 0x0, + + /* U+00EA "ê" */ + 0x0, + + /* U+00EB "ë" */ + 0x0, + + /* U+00EC "ì" */ + 0x0, + + /* U+00ED "í" */ + 0x0, + + /* U+00EE "î" */ + 0x0, + + /* U+00EF "ï" */ + 0x0, + + /* U+00F0 "ð" */ + 0x0, + + /* U+00F1 "ñ" */ + 0x0, + + /* U+00F2 "ò" */ + 0x0, + + /* U+00F3 "ó" */ + 0x0, + + /* U+00F4 "ô" */ + 0x0, + + /* U+00F5 "õ" */ + 0x0, + + /* U+00F6 "ö" */ + 0x0, + + /* U+00F7 "÷" */ + 0x3, 0x0, 0x1e, 0x0, 0x30, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x30, 0x1, 0xe0, 0x3, 0x0, + + /* U+00F8 "ø" */ + 0x0, + + /* U+00F9 "ù" */ + 0x0, + + /* U+00FA "ú" */ + 0x0, + + /* U+00FB "û" */ + 0x0, + + /* U+00FC "ü" */ + 0x0, + + /* U+00FD "ý" */ + 0x0, + + /* U+00FE "þ" */ + 0x0, + + /* U+00FF "ÿ" */ + 0x0, + + /* U+0100 "Ā" */ + 0x0, + + /* U+0101 "ā" */ + 0x0, + + /* U+0102 "Ă" */ + 0x0, + + /* U+0103 "ă" */ + 0x0, + + /* U+0104 "Ą" */ + 0x0, + + /* U+0105 "ą" */ + 0x0, + + /* U+0106 "Ć" */ + 0x0, + + /* U+0107 "ć" */ + 0x0, + + /* U+0108 "Ĉ" */ + 0x0, + + /* U+0109 "ĉ" */ + 0x0, + + /* U+010A "Ċ" */ + 0x0, + + /* U+010B "ċ" */ + 0x0, + + /* U+010C "Č" */ + 0x0, + + /* U+010D "č" */ + 0x0, + + /* U+010E "Ď" */ + 0x0, + + /* U+010F "ď" */ + 0x0, + + /* U+0110 "Đ" */ + 0x0, + + /* U+0111 "đ" */ + 0x0, + + /* U+0112 "Ē" */ + 0x0, + + /* U+0113 "ē" */ + 0x0, + + /* U+0114 "Ĕ" */ + 0x0, + + /* U+0115 "ĕ" */ + 0x0, + + /* U+0116 "Ė" */ + 0x0, + + /* U+0117 "ė" */ + 0x0, + + /* U+0118 "Ę" */ + 0x0, + + /* U+0119 "ę" */ + 0x0, + + /* U+011A "Ě" */ + 0x0, + + /* U+011B "ě" */ + 0x0, + + /* U+011C "Ĝ" */ + 0x0, + + /* U+011D "ĝ" */ + 0x0, + + /* U+011E "Ğ" */ + 0x0, + + /* U+011F "ğ" */ + 0x0, + + /* U+0120 "Ġ" */ + 0x0, + + /* U+0121 "ġ" */ + 0x0, + + /* U+0122 "Ģ" */ + 0x0, + + /* U+0123 "ģ" */ + 0x0, + + /* U+0124 "Ĥ" */ + 0x0, + + /* U+0125 "ĥ" */ + 0x0, + + /* U+0126 "Ħ" */ + 0x0, + + /* U+0127 "ħ" */ + 0x0, + + /* U+0128 "Ĩ" */ + 0x0, + + /* U+0129 "ĩ" */ + 0x0, + + /* U+012A "Ī" */ + 0x0, + + /* U+012B "ī" */ + 0x0, + + /* U+012C "Ĭ" */ + 0x0, + + /* U+012D "ĭ" */ + 0x0, + + /* U+012E "Į" */ + 0x0, + + /* U+012F "į" */ + 0x0, + + /* U+0130 "İ" */ + 0x0, + + /* U+0131 "ı" */ + 0x0, + + /* U+0132 "IJ" */ + 0x0, + + /* U+0133 "ij" */ + 0x0, + + /* U+0134 "Ĵ" */ + 0x0, + + /* U+0135 "ĵ" */ + 0x0, + + /* U+0136 "Ķ" */ + 0x0, + + /* U+0137 "ķ" */ + 0x0, + + /* U+0138 "ĸ" */ + 0x0, + + /* U+0139 "Ĺ" */ + 0x0, + + /* U+013A "ĺ" */ + 0x0, + + /* U+013B "Ļ" */ + 0x0, + + /* U+013C "ļ" */ + 0x0, + + /* U+013D "Ľ" */ + 0x0, + + /* U+013E "ľ" */ + 0x0, + + /* U+013F "Ŀ" */ + 0x0, + + /* U+0140 "ŀ" */ + 0x0, + + /* U+0141 "Ł" */ + 0x0, + + /* U+0142 "ł" */ + 0x0, + + /* U+0143 "Ń" */ + 0x0, + + /* U+0144 "ń" */ + 0x0, + + /* U+0145 "Ņ" */ + 0x0, + + /* U+0146 "ņ" */ + 0x0, + + /* U+0147 "Ň" */ + 0x0, + + /* U+0148 "ň" */ + 0x0, + + /* U+0149 "ʼn" */ + 0x0, + + /* U+014A "Ŋ" */ + 0x0, + + /* U+014B "ŋ" */ + 0x0, + + /* U+014C "Ō" */ + 0x0, + + /* U+014D "ō" */ + 0x0, + + /* U+014E "Ŏ" */ + 0x0, + + /* U+014F "ŏ" */ + 0x0, + + /* U+0150 "Ő" */ + 0x0, + + /* U+0151 "ő" */ + 0x0, + + /* U+0152 "Œ" */ + 0x0, + + /* U+0153 "œ" */ + 0x0, + + /* U+0154 "Ŕ" */ + 0x0, + + /* U+0155 "ŕ" */ + 0x0, + + /* U+0156 "Ŗ" */ + 0x0, + + /* U+0157 "ŗ" */ + 0x0, + + /* U+0158 "Ř" */ + 0x0, + + /* U+0159 "ř" */ + 0x0, + + /* U+015A "Ś" */ + 0x0, + + /* U+015B "ś" */ + 0x0, + + /* U+015C "Ŝ" */ + 0x0, + + /* U+015D "ŝ" */ + 0x0, + + /* U+015E "Ş" */ + 0x0, + + /* U+015F "ş" */ + 0x0, + + /* U+0160 "Š" */ + 0x0, + + /* U+0161 "š" */ + 0x0, + + /* U+0162 "Ţ" */ + 0x0, + + /* U+0163 "ţ" */ + 0x0, + + /* U+0164 "Ť" */ + 0x0, + + /* U+0165 "ť" */ + 0x0, + + /* U+0166 "Ŧ" */ + 0x0, + + /* U+0167 "ŧ" */ + 0x0, + + /* U+0168 "Ũ" */ + 0x0, + + /* U+0169 "ũ" */ + 0x0, + + /* U+016A "Ū" */ + 0x0, + + /* U+016B "ū" */ + 0x0, + + /* U+016C "Ŭ" */ + 0x0, + + /* U+016D "ŭ" */ + 0x0, + + /* U+016E "Ů" */ + 0x0, + + /* U+016F "ů" */ + 0x0, + + /* U+0170 "Ű" */ + 0x0, + + /* U+0171 "ű" */ + 0x0, + + /* U+0172 "Ų" */ + 0x0, + + /* U+0173 "ų" */ + 0x0, + + /* U+0174 "Ŵ" */ + 0x0, + + /* U+0175 "ŵ" */ + 0x0, + + /* U+0176 "Ŷ" */ + 0x0, + + /* U+0177 "ŷ" */ + 0x0, + + /* U+0178 "Ÿ" */ + 0x0, + + /* U+0179 "Ź" */ + 0x0, + + /* U+017A "ź" */ + 0x0, + + /* U+017B "Ż" */ + 0x0, + + /* U+017C "ż" */ + 0x0, + + /* U+017D "Ž" */ + 0x0, + + /* U+017E "ž" */ + 0x0, + + /* U+017F "ſ" */ + 0x0, + + /* U+0180 "ƀ" */ + 0x0, + + /* U+0181 "Ɓ" */ + 0x0, + + /* U+0182 "Ƃ" */ + 0x0, + + /* U+0183 "ƃ" */ + 0x0, + + /* U+0184 "Ƅ" */ + 0x0, + + /* U+0185 "ƅ" */ + 0x0, + + /* U+0186 "Ɔ" */ + 0x0, + + /* U+0187 "Ƈ" */ + 0x0, + + /* U+0188 "ƈ" */ + 0x0, + + /* U+0189 "Ɖ" */ + 0x0, + + /* U+018A "Ɗ" */ + 0x0, + + /* U+018B "Ƌ" */ + 0x0, + + /* U+018C "ƌ" */ + 0x0, + + /* U+018D "ƍ" */ + 0x0, + + /* U+018E "Ǝ" */ + 0x0, + + /* U+018F "Ə" */ + 0x0, + + /* U+0190 "Ɛ" */ + 0x0, + + /* U+0191 "Ƒ" */ + 0x0, + + /* U+0192 "ƒ" */ + 0x0, + + /* U+0193 "Ɠ" */ + 0x0, + + /* U+0194 "Ɣ" */ + 0x0, + + /* U+0195 "ƕ" */ + 0x0, + + /* U+0196 "Ɩ" */ + 0x0, + + /* U+0197 "Ɨ" */ + 0x0, + + /* U+0198 "Ƙ" */ + 0x0, + + /* U+0199 "ƙ" */ + 0x0, + + /* U+019A "ƚ" */ + 0x0, + + /* U+019B "ƛ" */ + 0x0, + + /* U+019C "Ɯ" */ + 0x0, + + /* U+019D "Ɲ" */ + 0x0, + + /* U+019E "ƞ" */ + 0x0, + + /* U+019F "Ɵ" */ + 0x0, + + /* U+01A0 "Ơ" */ + 0x0, + + /* U+01A1 "ơ" */ + 0x0, + + /* U+01A2 "Ƣ" */ + 0x0, + + /* U+01A3 "ƣ" */ + 0x0, + + /* U+01A4 "Ƥ" */ + 0x0, + + /* U+01A5 "ƥ" */ + 0x0, + + /* U+01A6 "Ʀ" */ + 0x0, + + /* U+01A7 "Ƨ" */ + 0x0, + + /* U+01A8 "ƨ" */ + 0x0, + + /* U+01A9 "Ʃ" */ + 0x0, + + /* U+01AA "ƪ" */ + 0x0, + + /* U+01AB "ƫ" */ + 0x0, + + /* U+01AC "Ƭ" */ + 0x0, + + /* U+01AD "ƭ" */ + 0x0, + + /* U+01AE "Ʈ" */ + 0x0, + + /* U+01AF "Ư" */ + 0x0, + + /* U+01B0 "ư" */ + 0x0, + + /* U+01B1 "Ʊ" */ + 0x0, + + /* U+01B2 "Ʋ" */ + 0x0, + + /* U+01B3 "Ƴ" */ + 0x0, + + /* U+01B4 "ƴ" */ + 0x0, + + /* U+01B5 "Ƶ" */ + 0x0, + + /* U+01B6 "ƶ" */ + 0x0, + + /* U+01B7 "Ʒ" */ + 0x0, + + /* U+01B8 "Ƹ" */ + 0x0, + + /* U+01B9 "ƹ" */ + 0x0, + + /* U+01BA "ƺ" */ + 0x0, + + /* U+01BB "ƻ" */ + 0x0, + + /* U+01BC "Ƽ" */ + 0x0, + + /* U+01BD "ƽ" */ + 0x0, + + /* U+01BE "ƾ" */ + 0x0, + + /* U+01BF "ƿ" */ + 0x0, + + /* U+01C0 "ǀ" */ + 0x0, + + /* U+01C1 "ǁ" */ + 0x0, + + /* U+01C2 "ǂ" */ + 0x0, + + /* U+01C3 "ǃ" */ + 0x0, + + /* U+01C4 "DŽ" */ + 0x0, + + /* U+01C5 "Dž" */ + 0x0, + + /* U+01C6 "dž" */ + 0x0, + + /* U+01C7 "LJ" */ + 0x0, + + /* U+01C8 "Lj" */ + 0x0, + + /* U+01C9 "lj" */ + 0x0, + + /* U+01CA "NJ" */ + 0x0, + + /* U+01CB "Nj" */ + 0x0, + + /* U+01CC "nj" */ + 0x0, + + /* U+01CD "Ǎ" */ + 0x0, + + /* U+01CE "ǎ" */ + 0x0, + + /* U+01CF "Ǐ" */ + 0x0, + + /* U+01D0 "ǐ" */ + 0x0, + + /* U+01D1 "Ǒ" */ + 0x0, + + /* U+01D2 "ǒ" */ + 0x0, + + /* U+01D3 "Ǔ" */ + 0x0, + + /* U+01D4 "ǔ" */ + 0x0, + + /* U+01D5 "Ǖ" */ + 0x0, + + /* U+01D6 "ǖ" */ + 0x0, + + /* U+01D7 "Ǘ" */ + 0x0, + + /* U+01D8 "ǘ" */ + 0x0, + + /* U+01D9 "Ǚ" */ + 0x0, + + /* U+01DA "ǚ" */ + 0x0, + + /* U+01DB "Ǜ" */ + 0x0, + + /* U+01DC "ǜ" */ + 0x0, + + /* U+01DD "ǝ" */ + 0x0, + + /* U+01DE "Ǟ" */ + 0x0, + + /* U+01DF "ǟ" */ + 0x0, + + /* U+01E0 "Ǡ" */ + 0x0, + + /* U+01E1 "ǡ" */ + 0x0, + + /* U+01E2 "Ǣ" */ + 0x0, + + /* U+01E3 "ǣ" */ + 0x0, + + /* U+01E4 "Ǥ" */ + 0x0, + + /* U+01E5 "ǥ" */ + 0x0, + + /* U+01E6 "Ǧ" */ + 0x0, + + /* U+01E7 "ǧ" */ + 0x0, + + /* U+01E8 "Ǩ" */ + 0x0, + + /* U+01E9 "ǩ" */ + 0x0, + + /* U+01EA "Ǫ" */ + 0x0, + + /* U+01EB "ǫ" */ + 0x0, + + /* U+01EC "Ǭ" */ + 0x0, + + /* U+01ED "ǭ" */ + 0x0, + + /* U+01EE "Ǯ" */ + 0x0, + + /* U+01EF "ǯ" */ + 0x0, + + /* U+01F0 "ǰ" */ + 0x0, + + /* U+01F1 "DZ" */ + 0x0, + + /* U+01F2 "Dz" */ + 0x0, + + /* U+01F3 "dz" */ + 0x0, + + /* U+01F4 "Ǵ" */ + 0x0, + + /* U+01F5 "ǵ" */ + 0x0, + + /* U+01F6 "Ƕ" */ + 0x0, + + /* U+01F7 "Ƿ" */ + 0x0, + + /* U+01F8 "Ǹ" */ + 0x0, + + /* U+01F9 "ǹ" */ + 0x0, + + /* U+01FA "Ǻ" */ + 0x0, + + /* U+01FB "ǻ" */ + 0x0, + + /* U+01FC "Ǽ" */ + 0x0, + + /* U+01FD "ǽ" */ + 0x0, + + /* U+01FE "Ǿ" */ + 0x0, + + /* U+01FF "ǿ" */ + 0x0, + + /* U+0200 "Ȁ" */ + 0x0, + + /* U+0201 "ȁ" */ + 0x0, + + /* U+0202 "Ȃ" */ + 0x0, + + /* U+0203 "ȃ" */ + 0x0, + + /* U+0204 "Ȅ" */ + 0x0, + + /* U+0205 "ȅ" */ + 0x0, + + /* U+0206 "Ȇ" */ + 0x0, + + /* U+0207 "ȇ" */ + 0x0, + + /* U+0208 "Ȉ" */ + 0x0, + + /* U+0209 "ȉ" */ + 0x0, + + /* U+020A "Ȋ" */ + 0x0, + + /* U+020B "ȋ" */ + 0x0, + + /* U+020C "Ȍ" */ + 0x0, + + /* U+020D "ȍ" */ + 0x0, + + /* U+020E "Ȏ" */ + 0x0, + + /* U+020F "ȏ" */ + 0x0, + + /* U+0210 "Ȑ" */ + 0x0, + + /* U+0211 "ȑ" */ + 0x0, + + /* U+0212 "Ȓ" */ + 0x0, + + /* U+0213 "ȓ" */ + 0x0, + + /* U+0214 "Ȕ" */ + 0x0, + + /* U+0215 "ȕ" */ + 0x0, + + /* U+0216 "Ȗ" */ + 0x0, + + /* U+0217 "ȗ" */ + 0x0, + + /* U+0218 "Ș" */ + 0x0, + + /* U+0219 "ș" */ + 0x0, + + /* U+021A "Ț" */ + 0x0, + + /* U+021B "ț" */ + 0x0, + + /* U+021C "Ȝ" */ + 0x0, + + /* U+021D "ȝ" */ + 0x0, + + /* U+021E "Ȟ" */ + 0x0, + + /* U+021F "ȟ" */ + 0x0, + + /* U+0220 "Ƞ" */ + 0x0, + + /* U+0221 "ȡ" */ + 0x0, + + /* U+0222 "Ȣ" */ + 0x0, + + /* U+0223 "ȣ" */ + 0x0, + + /* U+0224 "Ȥ" */ + 0x0, + + /* U+0225 "ȥ" */ + 0x0, + + /* U+0226 "Ȧ" */ + 0x0, + + /* U+0227 "ȧ" */ + 0x0, + + /* U+0228 "Ȩ" */ + 0x0, + + /* U+0229 "ȩ" */ + 0x0, + + /* U+022A "Ȫ" */ + 0x0, + + /* U+022B "ȫ" */ + 0x0, + + /* U+022C "Ȭ" */ + 0x0, + + /* U+022D "ȭ" */ + 0x0, + + /* U+022E "Ȯ" */ + 0x0, + + /* U+022F "ȯ" */ + 0x0, + + /* U+0230 "Ȱ" */ + 0x0, + + /* U+0231 "ȱ" */ + 0x0, + + /* U+0232 "Ȳ" */ + 0x0, + + /* U+0233 "ȳ" */ + 0x0, + + /* U+0234 "ȴ" */ + 0x0, + + /* U+0235 "ȵ" */ + 0x0, + + /* U+0236 "ȶ" */ + 0x0, + + /* U+0237 "ȷ" */ + 0x0, + + /* U+0238 "ȸ" */ + 0x0, + + /* U+0239 "ȹ" */ + 0x0, + + /* U+023A "Ⱥ" */ + 0x0, + + /* U+023B "Ȼ" */ + 0x0, + + /* U+023C "ȼ" */ + 0x0, + + /* U+023D "Ƚ" */ + 0x0, + + /* U+023E "Ⱦ" */ + 0x0, + + /* U+023F "ȿ" */ + 0x0, + + /* U+0240 "ɀ" */ + 0x0, + + /* U+0241 "Ɂ" */ + 0x0, + + /* U+0242 "ɂ" */ + 0x0, + + /* U+0243 "Ƀ" */ + 0x0, + + /* U+0244 "Ʉ" */ + 0x0, + + /* U+0245 "Ʌ" */ + 0x0, + + /* U+0246 "Ɇ" */ + 0x0, + + /* U+0247 "ɇ" */ + 0x0, + + /* U+0248 "Ɉ" */ + 0x0, + + /* U+0249 "ɉ" */ + 0x0, + + /* U+024A "Ɋ" */ + 0x0, + + /* U+024B "ɋ" */ + 0x0, + + /* U+024C "Ɍ" */ + 0x0, + + /* U+024D "ɍ" */ + 0x0, + + /* U+024E "Ɏ" */ + 0x0, + + /* U+024F "ɏ" */ + 0x0, + + /* U+0250 "ɐ" */ + 0x0, + + /* U+0251 "ɑ" */ + 0x0, + + /* U+0252 "ɒ" */ + 0x0, + + /* U+0253 "ɓ" */ + 0x0, + + /* U+0254 "ɔ" */ + 0x0, + + /* U+0255 "ɕ" */ + 0x0, + + /* U+0256 "ɖ" */ + 0x0, + + /* U+0257 "ɗ" */ + 0x0, + + /* U+0258 "ɘ" */ + 0x0, + + /* U+0259 "ə" */ + 0x0, + + /* U+025A "ɚ" */ + 0x0, + + /* U+025B "ɛ" */ + 0x0, + + /* U+025C "ɜ" */ + 0x0, + + /* U+025D "ɝ" */ + 0x0, + + /* U+025E "ɞ" */ + 0x0, + + /* U+025F "ɟ" */ + 0x0, + + /* U+0260 "ɠ" */ + 0x0, + + /* U+0261 "ɡ" */ + 0x0, + + /* U+0262 "ɢ" */ + 0x0, + + /* U+0263 "ɣ" */ + 0x0, + + /* U+0264 "ɤ" */ + 0x0, + + /* U+0265 "ɥ" */ + 0x0, + + /* U+0266 "ɦ" */ + 0x0, + + /* U+0267 "ɧ" */ + 0x0, + + /* U+0268 "ɨ" */ + 0x0, + + /* U+0269 "ɩ" */ + 0x0, + + /* U+026A "ɪ" */ + 0x0, + + /* U+026B "ɫ" */ + 0x0, + + /* U+026C "ɬ" */ + 0x0, + + /* U+026D "ɭ" */ + 0x0, + + /* U+026E "ɮ" */ + 0x0, + + /* U+026F "ɯ" */ + 0x0, + + /* U+0270 "ɰ" */ + 0x0, + + /* U+0271 "ɱ" */ + 0x0, + + /* U+0272 "ɲ" */ + 0x0, + + /* U+0273 "ɳ" */ + 0x0, + + /* U+0274 "ɴ" */ + 0x0, + + /* U+0275 "ɵ" */ + 0x0, + + /* U+0276 "ɶ" */ + 0x0, + + /* U+0277 "ɷ" */ + 0x0, + + /* U+0278 "ɸ" */ + 0x0, + + /* U+0279 "ɹ" */ + 0x0, + + /* U+027A "ɺ" */ + 0x0, + + /* U+027B "ɻ" */ + 0x0, + + /* U+027C "ɼ" */ + 0x0, + + /* U+027D "ɽ" */ + 0x0, + + /* U+027E "ɾ" */ + 0x0, + + /* U+027F "ɿ" */ + 0x0, + + /* U+0280 "ʀ" */ + 0x0, + + /* U+0281 "ʁ" */ + 0x0, + + /* U+0282 "ʂ" */ + 0x0, + + /* U+0283 "ʃ" */ + 0x0, + + /* U+0284 "ʄ" */ + 0x0, + + /* U+0285 "ʅ" */ + 0x0, + + /* U+0286 "ʆ" */ + 0x0, + + /* U+0287 "ʇ" */ + 0x0, + + /* U+0288 "ʈ" */ + 0x0, + + /* U+0289 "ʉ" */ + 0x0, + + /* U+028A "ʊ" */ + 0x0, + + /* U+028B "ʋ" */ + 0x0, + + /* U+028C "ʌ" */ + 0x0, + + /* U+028D "ʍ" */ + 0x0, + + /* U+028E "ʎ" */ + 0x0, + + /* U+028F "ʏ" */ + 0x0, + + /* U+0290 "ʐ" */ + 0x0, + + /* U+0291 "ʑ" */ + 0x0, + + /* U+0292 "ʒ" */ + 0x0, + + /* U+0293 "ʓ" */ + 0x0, + + /* U+0294 "ʔ" */ + 0x0, + + /* U+0295 "ʕ" */ + 0x0, + + /* U+0296 "ʖ" */ + 0x0, + + /* U+0297 "ʗ" */ + 0x0, + + /* U+0298 "ʘ" */ + 0x0, + + /* U+0299 "ʙ" */ + 0x0, + + /* U+029A "ʚ" */ + 0x0, + + /* U+029B "ʛ" */ + 0x0, + + /* U+029C "ʜ" */ + 0x0, + + /* U+029D "ʝ" */ + 0x0, + + /* U+029E "ʞ" */ + 0x0, + + /* U+029F "ʟ" */ + 0x0, + + /* U+02A0 "ʠ" */ + 0x0, + + /* U+02A1 "ʡ" */ + 0x0, + + /* U+02A2 "ʢ" */ + 0x0, + + /* U+02A3 "ʣ" */ + 0x0, + + /* U+02A4 "ʤ" */ + 0x0, + + /* U+02A5 "ʥ" */ + 0x0, + + /* U+02A6 "ʦ" */ + 0x0, + + /* U+02A7 "ʧ" */ + 0x0, + + /* U+02A8 "ʨ" */ + 0x0, + + /* U+02A9 "ʩ" */ + 0x0, + + /* U+02AA "ʪ" */ + 0x0, + + /* U+02AB "ʫ" */ + 0x0, + + /* U+02AC "ʬ" */ + 0x0, + + /* U+02AD "ʭ" */ + 0x0, + + /* U+02AE "ʮ" */ + 0x0, + + /* U+02AF "ʯ" */ + 0x0, + + /* U+02B0 "ʰ" */ + 0x0, + + /* U+02B1 "ʱ" */ + 0x0, + + /* U+02B2 "ʲ" */ + 0x0, + + /* U+02B3 "ʳ" */ + 0x0, + + /* U+02B4 "ʴ" */ + 0x0, + + /* U+02B5 "ʵ" */ + 0x0, + + /* U+02B6 "ʶ" */ + 0x0, + + /* U+02B7 "ʷ" */ + 0x0, + + /* U+02B8 "ʸ" */ + 0x0, + + /* U+02B9 "ʹ" */ + 0x0, + + /* U+02BA "ʺ" */ + 0x0, + + /* U+02BB "ʻ" */ + 0x0, + + /* U+02BC "ʼ" */ + 0x0, + + /* U+02BD "ʽ" */ + 0x0, + + /* U+02BE "ʾ" */ + 0x0, + + /* U+02BF "ʿ" */ + 0x0, + + /* U+02C0 "ˀ" */ + 0x0, + + /* U+02C1 "ˁ" */ + 0x0, + + /* U+02C2 "˂" */ + 0x0, + + /* U+02C3 "˃" */ + 0x0, + + /* U+02C4 "˄" */ + 0x0, + + /* U+02C5 "˅" */ + 0x0, + + /* U+02C6 "ˆ" */ + 0x0, + + /* U+02C7 "ˇ" */ + 0x0, + + /* U+02C8 "ˈ" */ + 0x0, + + /* U+02C9 "ˉ" */ + 0x0, + + /* U+02CA "ˊ" */ + 0x0, + + /* U+02CB "ˋ" */ + 0x0, + + /* U+02CC "ˌ" */ + 0x0, + + /* U+02CD "ˍ" */ + 0x0, + + /* U+02CE "ˎ" */ + 0x0, + + /* U+02CF "ˏ" */ + 0x0, + + /* U+02D0 "ː" */ + 0x0, + + /* U+02D1 "ˑ" */ + 0x0, + + /* U+02D2 "˒" */ + 0x0, + + /* U+02D3 "˓" */ + 0x0, + + /* U+02D4 "˔" */ + 0x0, + + /* U+02D5 "˕" */ + 0x0, + + /* U+02D6 "˖" */ + 0x0, + + /* U+02D7 "˗" */ + 0x0, + + /* U+02D8 "˘" */ + 0x0, + + /* U+02D9 "˙" */ + 0x0, + + /* U+02DA "˚" */ + 0x0, + + /* U+02DB "˛" */ + 0x0, + + /* U+02DC "˜" */ + 0x0, + + /* U+02DD "˝" */ + 0x0, + + /* U+02DE "˞" */ + 0x0, + + /* U+02DF "˟" */ + 0x0, + + /* U+02E0 "ˠ" */ + 0x0, + + /* U+02E1 "ˡ" */ + 0x0, + + /* U+02E2 "ˢ" */ + 0x0, + + /* U+02E3 "ˣ" */ + 0x0, + + /* U+02E4 "ˤ" */ + 0x0, + + /* U+02E5 "˥" */ + 0x0, + + /* U+02E6 "˦" */ + 0x0, + + /* U+02E7 "˧" */ + 0x0, + + /* U+02E8 "˨" */ + 0x0, + + /* U+02E9 "˩" */ + 0x0, + + /* U+02EA "˪" */ + 0x0, + + /* U+02EB "˫" */ + 0x0, + + /* U+02EC "ˬ" */ + 0x0, + + /* U+02ED "˭" */ + 0x0, + + /* U+02EE "ˮ" */ + 0x0, + + /* U+02EF "˯" */ + 0x0, + + /* U+02F0 "˰" */ + 0x0, + + /* U+02F1 "˱" */ + 0x0, + + /* U+02F2 "˲" */ + 0x0, + + /* U+02F3 "˳" */ + 0x0, + + /* U+02F4 "˴" */ + 0x0, + + /* U+02F5 "˵" */ + 0x0, + + /* U+02F6 "˶" */ + 0x0, + + /* U+02F7 "˷" */ + 0x0, + + /* U+02F8 "˸" */ + 0x0, + + /* U+02F9 "˹" */ + 0x0, + + /* U+02FA "˺" */ + 0x0, + + /* U+02FB "˻" */ + 0x0, + + /* U+02FC "˼" */ + 0x0, + + /* U+02FD "˽" */ + 0x0, + + /* U+02FE "˾" */ + 0x0, + + /* U+02FF "˿" */ + 0x0, + + /* U+0300 "̀" */ + 0x0, + + /* U+0301 "́" */ + 0x0, + + /* U+0302 "̂" */ + 0x0, + + /* U+0303 "̃" */ + 0x0, + + /* U+0304 "̄" */ + 0x0, + + /* U+0305 "̅" */ + 0x0, + + /* U+0306 "̆" */ + 0x0, + + /* U+0307 "̇" */ + 0x0, + + /* U+0308 "̈" */ + 0x0, + + /* U+0309 "̉" */ + 0x0, + + /* U+030A "̊" */ + 0x0, + + /* U+030B "̋" */ + 0x0, + + /* U+030C "̌" */ + 0x0, + + /* U+030D "̍" */ + 0x0, + + /* U+030E "̎" */ + 0x0, + + /* U+030F "̏" */ + 0x0, + + /* U+0310 "̐" */ + 0x0, + + /* U+0311 "̑" */ + 0x0, + + /* U+0312 "̒" */ + 0x0, + + /* U+0313 "̓" */ + 0x0, + + /* U+0314 "̔" */ + 0x0, + + /* U+0315 "̕" */ + 0x0, + + /* U+0316 "̖" */ + 0x0, + + /* U+0317 "̗" */ + 0x0, + + /* U+0318 "̘" */ + 0x0, + + /* U+0319 "̙" */ + 0x0, + + /* U+031A "̚" */ + 0x0, + + /* U+031B "̛" */ + 0x0, + + /* U+031C "̜" */ + 0x0, + + /* U+031D "̝" */ + 0x0, + + /* U+031E "̞" */ + 0x0, + + /* U+031F "̟" */ + 0x0, + + /* U+0320 "̠" */ + 0x0, + + /* U+0321 "̡" */ + 0x0, + + /* U+0322 "̢" */ + 0x0, + + /* U+0323 "̣" */ + 0x0, + + /* U+0324 "̤" */ + 0x0, + + /* U+0325 "̥" */ + 0x0, + + /* U+0326 "̦" */ + 0x0, + + /* U+0327 "̧" */ + 0x0, + + /* U+0328 "̨" */ + 0x0, + + /* U+0329 "̩" */ + 0x0, + + /* U+032A "̪" */ + 0x0, + + /* U+032B "̫" */ + 0x0, + + /* U+032C "̬" */ + 0x0, + + /* U+032D "̭" */ + 0x0, + + /* U+032E "̮" */ + 0x0, + + /* U+032F "̯" */ + 0x0, + + /* U+0330 "̰" */ + 0x0, + + /* U+0331 "̱" */ + 0x0, + + /* U+0332 "̲" */ + 0x0, + + /* U+0333 "̳" */ + 0x0, + + /* U+0334 "̴" */ + 0x0, + + /* U+0335 "̵" */ + 0x0, + + /* U+0336 "̶" */ + 0x0, + + /* U+0337 "̷" */ + 0x0, + + /* U+0338 "̸" */ + 0x0, + + /* U+0339 "̹" */ + 0x0, + + /* U+033A "̺" */ + 0x0, + + /* U+033B "̻" */ + 0x0, + + /* U+033C "̼" */ + 0x0, + + /* U+033D "̽" */ + 0x0, + + /* U+033E "̾" */ + 0x0, + + /* U+033F "̿" */ + 0x0, + + /* U+0340 "̀" */ + 0x0, + + /* U+0341 "́" */ + 0x0, + + /* U+0342 "͂" */ + 0x0, + + /* U+0343 "̓" */ + 0x0, + + /* U+0344 "̈́" */ + 0x0, + + /* U+0345 "ͅ" */ + 0x0, + + /* U+0346 "͆" */ + 0x0, + + /* U+0347 "͇" */ + 0x0, + + /* U+0348 "͈" */ + 0x0, + + /* U+0349 "͉" */ + 0x0, + + /* U+034A "͊" */ + 0x0, + + /* U+034B "͋" */ + 0x0, + + /* U+034C "͌" */ + 0x0, + + /* U+034D "͍" */ + 0x0, + + /* U+034E "͎" */ + 0x0, + + /* U+034F "͏" */ + 0x0, + + /* U+0350 "͐" */ + 0x0, + + /* U+0351 "͑" */ + 0x0, + + /* U+0352 "͒" */ + 0x0, + + /* U+0353 "͓" */ + 0x0, + + /* U+0354 "͔" */ + 0x0, + + /* U+0355 "͕" */ + 0x0, + + /* U+0356 "͖" */ + 0x0, + + /* U+0357 "͗" */ + 0x0, + + /* U+0358 "͘" */ + 0x0, + + /* U+0359 "͙" */ + 0x0, + + /* U+035A "͚" */ + 0x0, + + /* U+035B "͛" */ + 0x0, + + /* U+035C "͜" */ + 0x0, + + /* U+035D "͝" */ + 0x0, + + /* U+035E "͞" */ + 0x0, + + /* U+035F "͟" */ + 0x0, + + /* U+0360 "͠" */ + 0x0, + + /* U+0361 "͡" */ + 0x0, + + /* U+0362 "͢" */ + 0x0, + + /* U+0363 "ͣ" */ + 0x0, + + /* U+0364 "ͤ" */ + 0x0, + + /* U+0365 "ͥ" */ + 0x0, + + /* U+0366 "ͦ" */ + 0x0, + + /* U+0367 "ͧ" */ + 0x0, + + /* U+0368 "ͨ" */ + 0x0, + + /* U+0369 "ͩ" */ + 0x0, + + /* U+036A "ͪ" */ + 0x0, + + /* U+036B "ͫ" */ + 0x0, + + /* U+036C "ͬ" */ + 0x0, + + /* U+036D "ͭ" */ + 0x0, + + /* U+036E "ͮ" */ + 0x0, + + /* U+036F "ͯ" */ + 0x0, + + /* U+0370 "Ͱ" */ + 0x0, + + /* U+0371 "ͱ" */ + 0x0, + + /* U+0372 "Ͳ" */ + 0x0, + + /* U+0373 "ͳ" */ + 0x0, + + /* U+0374 "ʹ" */ + 0x0, + + /* U+0375 "͵" */ + 0x0, + + /* U+0376 "Ͷ" */ + 0x0, + + /* U+0377 "ͷ" */ + 0x0, + + /* U+0378 "͸" */ + 0x0, + + /* U+0379 "͹" */ + 0x0, + + /* U+037A "ͺ" */ + 0x0, + + /* U+037B "ͻ" */ + 0x0, + + /* U+037C "ͼ" */ + 0x0, + + /* U+037D "ͽ" */ + 0x0, + + /* U+037E ";" */ + 0x0, + + /* U+037F "Ϳ" */ + 0x0, + + /* U+0380 "΀" */ + 0x0, + + /* U+0381 "΁" */ + 0x0, + + /* U+0382 "΂" */ + 0x0, + + /* U+0383 "΃" */ + 0x0, + + /* U+0384 "΄" */ + 0x0, + + /* U+0385 "΅" */ + 0x0, + + /* U+0386 "Ά" */ + 0x0, + + /* U+0387 "·" */ + 0x0, + + /* U+0388 "Έ" */ + 0x0, + + /* U+0389 "Ή" */ + 0x0, + + /* U+038A "Ί" */ + 0x0, + + /* U+038B "΋" */ + 0x0, + + /* U+038C "Ό" */ + 0x0, + + /* U+038D "΍" */ + 0x0, + + /* U+038E "Ύ" */ + 0x0, + + /* U+038F "Ώ" */ + 0x0, + + /* U+0390 "ΐ" */ + 0x0, + + /* U+0391 "Α" */ + 0x0, + + /* U+0392 "Β" */ + 0x0, + + /* U+0393 "Γ" */ + 0x0, + + /* U+0394 "Δ" */ + 0x0, + + /* U+0395 "Ε" */ + 0x0, + + /* U+0396 "Ζ" */ + 0x0, + + /* U+0397 "Η" */ + 0x0, + + /* U+0398 "Θ" */ + 0x0, + + /* U+0399 "Ι" */ + 0x0, + + /* U+039A "Κ" */ + 0x0, + + /* U+039B "Λ" */ + 0x0, + + /* U+039C "Μ" */ + 0x0, + + /* U+039D "Ν" */ + 0x0, + + /* U+039E "Ξ" */ + 0x0, + + /* U+039F "Ο" */ + 0x0, + + /* U+03A0 "Π" */ + 0x0, + + /* U+03A1 "Ρ" */ + 0x0, + + /* U+03A2 "΢" */ + 0x0, + + /* U+03A3 "Σ" */ + 0x0, + + /* U+03A4 "Τ" */ + 0x0, + + /* U+03A5 "Υ" */ + 0x0, + + /* U+03A6 "Φ" */ + 0x0, + + /* U+03A7 "Χ" */ + 0x0, + + /* U+03A8 "Ψ" */ + 0x0, + + /* U+03A9 "Ω" */ + 0x0, + + /* U+03AA "Ϊ" */ + 0x0, + + /* U+03AB "Ϋ" */ + 0x0, + + /* U+03AC "ά" */ + 0x0, + + /* U+03AD "έ" */ + 0x0, + + /* U+03AE "ή" */ + 0x0, + + /* U+03AF "ί" */ + 0x0, + + /* U+03B0 "ΰ" */ + 0x0, + + /* U+03B1 "α" */ + 0x0, + + /* U+03B2 "β" */ + 0x0, + + /* U+03B3 "γ" */ + 0x0, + + /* U+03B4 "δ" */ + 0x0, + + /* U+03B5 "ε" */ + 0x0, + + /* U+03B6 "ζ" */ + 0x0, + + /* U+03B7 "η" */ + 0x0, + + /* U+03B8 "θ" */ + 0x0, + + /* U+03B9 "ι" */ + 0x0, + + /* U+03BA "κ" */ + 0x0, + + /* U+03BB "λ" */ + 0x0, + + /* U+03BC "μ" */ + 0x0, + + /* U+03BD "ν" */ + 0x0, + + /* U+03BE "ξ" */ + 0x0, + + /* U+03BF "ο" */ + 0x0, + + /* U+03C0 "π" */ + 0x0, + + /* U+03C1 "ρ" */ + 0x0, + + /* U+03C2 "ς" */ + 0x0, + + /* U+03C3 "σ" */ + 0x0, + + /* U+03C4 "τ" */ + 0x0, + + /* U+03C5 "υ" */ + 0x0, + + /* U+03C6 "φ" */ + 0x0, + + /* U+03C7 "χ" */ + 0x0, + + /* U+03C8 "ψ" */ + 0x0, + + /* U+03C9 "ω" */ + 0x0, + + /* U+03CA "ϊ" */ + 0x0, + + /* U+03CB "ϋ" */ + 0x0, + + /* U+03CC "ό" */ + 0x0, + + /* U+03CD "ύ" */ + 0x0, + + /* U+03CE "ώ" */ + 0x0, + + /* U+03CF "Ϗ" */ + 0x0, + + /* U+03D0 "ϐ" */ + 0x0, + + /* U+03D1 "ϑ" */ + 0x0, + + /* U+03D2 "ϒ" */ + 0x0, + + /* U+03D3 "ϓ" */ + 0x0, + + /* U+03D4 "ϔ" */ + 0x0, + + /* U+03D5 "ϕ" */ + 0x0, + + /* U+03D6 "ϖ" */ + 0x0, + + /* U+03D7 "ϗ" */ + 0x0, + + /* U+03D8 "Ϙ" */ + 0x0, + + /* U+03D9 "ϙ" */ + 0x0, + + /* U+03DA "Ϛ" */ + 0x0, + + /* U+03DB "ϛ" */ + 0x0, + + /* U+03DC "Ϝ" */ + 0x0, + + /* U+03DD "ϝ" */ + 0x0, + + /* U+03DE "Ϟ" */ + 0x0, + + /* U+03DF "ϟ" */ + 0x0, + + /* U+03E0 "Ϡ" */ + 0x0, + + /* U+03E1 "ϡ" */ + 0x0, + + /* U+03E2 "Ϣ" */ + 0x0, + + /* U+03E3 "ϣ" */ + 0x0, + + /* U+03E4 "Ϥ" */ + 0x0, + + /* U+03E5 "ϥ" */ + 0x0, + + /* U+03E6 "Ϧ" */ + 0x0, + + /* U+03E7 "ϧ" */ + 0x0, + + /* U+03E8 "Ϩ" */ + 0x0, + + /* U+03E9 "ϩ" */ + 0x0, + + /* U+03EA "Ϫ" */ + 0x0, + + /* U+03EB "ϫ" */ + 0x0, + + /* U+03EC "Ϭ" */ + 0x0, + + /* U+03ED "ϭ" */ + 0x0, + + /* U+03EE "Ϯ" */ + 0x0, + + /* U+03EF "ϯ" */ + 0x0, + + /* U+03F0 "ϰ" */ + 0x0, + + /* U+03F1 "ϱ" */ + 0x0, + + /* U+03F2 "ϲ" */ + 0x0, + + /* U+03F3 "ϳ" */ + 0x0, + + /* U+03F4 "ϴ" */ + 0x0, + + /* U+03F5 "ϵ" */ + 0x0, + + /* U+03F6 "϶" */ + 0x0, + + /* U+03F7 "Ϸ" */ + 0x0, + + /* U+03F8 "ϸ" */ + 0x0, + + /* U+03F9 "Ϲ" */ + 0x0, + + /* U+03FA "Ϻ" */ + 0x0, + + /* U+03FB "ϻ" */ + 0x0, + + /* U+03FC "ϼ" */ + 0x0, + + /* U+03FD "Ͻ" */ + 0x0, + + /* U+03FE "Ͼ" */ + 0x0, + + /* U+03FF "Ͽ" */ + 0x0, + + /* U+0400 "Ѐ" */ + 0x0, + + /* U+0401 "Ё" */ + 0x0, + + /* U+0402 "Ђ" */ + 0x0, + + /* U+0403 "Ѓ" */ + 0x0, + + /* U+0404 "Є" */ + 0x0, + + /* U+0405 "Ѕ" */ + 0x0, + + /* U+0406 "І" */ + 0x0, + + /* U+0407 "Ї" */ + 0x0, + + /* U+0408 "Ј" */ + 0x0, + + /* U+0409 "Љ" */ + 0x0, + + /* U+040A "Њ" */ + 0x0, + + /* U+040B "Ћ" */ + 0x0, + + /* U+040C "Ќ" */ + 0x0, + + /* U+040D "Ѝ" */ + 0x0, + + /* U+040E "Ў" */ + 0x0, + + /* U+040F "Џ" */ + 0x0, + + /* U+0410 "А" */ + 0x0, + + /* U+0411 "Б" */ + 0x0, + + /* U+0412 "В" */ + 0x0, + + /* U+0413 "Г" */ + 0x0, + + /* U+0414 "Д" */ + 0x0, + + /* U+0415 "Е" */ + 0x0, + + /* U+0416 "Ж" */ + 0x0, + + /* U+0417 "З" */ + 0x0, + + /* U+0418 "И" */ + 0x0, + + /* U+0419 "Й" */ + 0x0, + + /* U+041A "К" */ + 0x0, + + /* U+041B "Л" */ + 0x0, + + /* U+041C "М" */ + 0x0, + + /* U+041D "Н" */ + 0x0, + + /* U+041E "О" */ + 0x0, + + /* U+041F "П" */ + 0x0, + + /* U+0420 "Р" */ + 0x0, + + /* U+0421 "С" */ + 0x0, + + /* U+0422 "Т" */ + 0x0, + + /* U+0423 "У" */ + 0x0, + + /* U+0424 "Ф" */ + 0x0, + + /* U+0425 "Х" */ + 0x0, + + /* U+0426 "Ц" */ + 0x0, + + /* U+0427 "Ч" */ + 0x0, + + /* U+0428 "Ш" */ + 0x0, + + /* U+0429 "Щ" */ + 0x0, + + /* U+042A "Ъ" */ + 0x0, + + /* U+042B "Ы" */ + 0x0, + + /* U+042C "Ь" */ + 0x0, + + /* U+042D "Э" */ + 0x0, + + /* U+042E "Ю" */ + 0x0, + + /* U+042F "Я" */ + 0x0, + + /* U+0430 "а" */ + 0x0, + + /* U+0431 "б" */ + 0x0, + + /* U+0432 "в" */ + 0x0, + + /* U+0433 "г" */ + 0x0, + + /* U+0434 "д" */ + 0x0, + + /* U+0435 "е" */ + 0x0, + + /* U+0436 "ж" */ + 0x0, + + /* U+0437 "з" */ + 0x0, + + /* U+0438 "и" */ + 0x0, + + /* U+0439 "й" */ + 0x0, + + /* U+043A "к" */ + 0x0, + + /* U+043B "л" */ + 0x0, + + /* U+043C "м" */ + 0x0, + + /* U+043D "н" */ + 0x0, + + /* U+043E "о" */ + 0x0, + + /* U+043F "п" */ + 0x0, + + /* U+0440 "р" */ + 0x0, + + /* U+0441 "с" */ + 0x0, + + /* U+0442 "т" */ + 0x0, + + /* U+0443 "у" */ + 0x0, + + /* U+0444 "ф" */ + 0x0, + + /* U+0445 "х" */ + 0x0, + + /* U+0446 "ц" */ + 0x0, + + /* U+0447 "ч" */ + 0x0, + + /* U+0448 "ш" */ + 0x0, + + /* U+0449 "щ" */ + 0x0, + + /* U+044A "ъ" */ + 0x0, + + /* U+044B "ы" */ + 0x0, + + /* U+044C "ь" */ + 0x0, + + /* U+044D "э" */ + 0x0, + + /* U+044E "ю" */ + 0x0, + + /* U+044F "я" */ + 0x0, + + /* U+0450 "ѐ" */ + 0x0, + + /* U+0451 "ё" */ + 0x0, + + /* U+0452 "ђ" */ + 0x0, + + /* U+0453 "ѓ" */ + 0x0, + + /* U+0454 "є" */ + 0x0, + + /* U+0455 "ѕ" */ + 0x0, + + /* U+0456 "і" */ + 0x0, + + /* U+0457 "ї" */ + 0x0, + + /* U+0458 "ј" */ + 0x0, + + /* U+0459 "љ" */ + 0x0, + + /* U+045A "њ" */ + 0x0, + + /* U+045B "ћ" */ + 0x0, + + /* U+045C "ќ" */ + 0x0, + + /* U+045D "ѝ" */ + 0x0, + + /* U+045E "ў" */ + 0x0, + + /* U+045F "џ" */ + 0x0, + + /* U+0460 "Ѡ" */ + 0x0, + + /* U+0461 "ѡ" */ + 0x0, + + /* U+0462 "Ѣ" */ + 0x0, + + /* U+0463 "ѣ" */ + 0x0, + + /* U+0464 "Ѥ" */ + 0x0, + + /* U+0465 "ѥ" */ + 0x0, + + /* U+0466 "Ѧ" */ + 0x0, + + /* U+0467 "ѧ" */ + 0x0, + + /* U+0468 "Ѩ" */ + 0x0, + + /* U+0469 "ѩ" */ + 0x0, + + /* U+046A "Ѫ" */ + 0x0, + + /* U+046B "ѫ" */ + 0x0, + + /* U+046C "Ѭ" */ + 0x0, + + /* U+046D "ѭ" */ + 0x0, + + /* U+046E "Ѯ" */ + 0x0, + + /* U+046F "ѯ" */ + 0x0, + + /* U+0470 "Ѱ" */ + 0x0, + + /* U+0471 "ѱ" */ + 0x0, + + /* U+0472 "Ѳ" */ + 0x0, + + /* U+0473 "ѳ" */ + 0x0, + + /* U+0474 "Ѵ" */ + 0x0, + + /* U+0475 "ѵ" */ + 0x0, + + /* U+0476 "Ѷ" */ + 0x0, + + /* U+0477 "ѷ" */ + 0x0, + + /* U+0478 "Ѹ" */ + 0x0, + + /* U+0479 "ѹ" */ + 0x0, + + /* U+047A "Ѻ" */ + 0x0, + + /* U+047B "ѻ" */ + 0x0, + + /* U+047C "Ѽ" */ + 0x0, + + /* U+047D "ѽ" */ + 0x0, + + /* U+047E "Ѿ" */ + 0x0, + + /* U+047F "ѿ" */ + 0x0, + + /* U+0480 "Ҁ" */ + 0x0, + + /* U+0481 "ҁ" */ + 0x0, + + /* U+0482 "҂" */ + 0x0, + + /* U+0483 "҃" */ + 0x0, + + /* U+0484 "҄" */ + 0x0, + + /* U+0485 "҅" */ + 0x0, + + /* U+0486 "҆" */ + 0x0, + + /* U+0487 "҇" */ + 0x0, + + /* U+0488 "҈" */ + 0x0, + + /* U+0489 "҉" */ + 0x0, + + /* U+048A "Ҋ" */ + 0x0, + + /* U+048B "ҋ" */ + 0x0, + + /* U+048C "Ҍ" */ + 0x0, + + /* U+048D "ҍ" */ + 0x0, + + /* U+048E "Ҏ" */ + 0x0, + + /* U+048F "ҏ" */ + 0x0, + + /* U+0490 "Ґ" */ + 0x0, + + /* U+0491 "ґ" */ + 0x0, + + /* U+0492 "Ғ" */ + 0x0, + + /* U+0493 "ғ" */ + 0x0, + + /* U+0494 "Ҕ" */ + 0x0, + + /* U+0495 "ҕ" */ + 0x0, + + /* U+0496 "Җ" */ + 0x0, + + /* U+0497 "җ" */ + 0x0, + + /* U+0498 "Ҙ" */ + 0x0, + + /* U+0499 "ҙ" */ + 0x0, + + /* U+049A "Қ" */ + 0x0, + + /* U+049B "қ" */ + 0x0, + + /* U+049C "Ҝ" */ + 0x0, + + /* U+049D "ҝ" */ + 0x0, + + /* U+049E "Ҟ" */ + 0x0, + + /* U+049F "ҟ" */ + 0x0, + + /* U+04A0 "Ҡ" */ + 0x0, + + /* U+04A1 "ҡ" */ + 0x0, + + /* U+04A2 "Ң" */ + 0x0, + + /* U+04A3 "ң" */ + 0x0, + + /* U+04A4 "Ҥ" */ + 0x0, + + /* U+04A5 "ҥ" */ + 0x0, + + /* U+04A6 "Ҧ" */ + 0x0, + + /* U+04A7 "ҧ" */ + 0x0, + + /* U+04A8 "Ҩ" */ + 0x0, + + /* U+04A9 "ҩ" */ + 0x0, + + /* U+04AA "Ҫ" */ + 0x0, + + /* U+04AB "ҫ" */ + 0x0, + + /* U+04AC "Ҭ" */ + 0x0, + + /* U+04AD "ҭ" */ + 0x0, + + /* U+04AE "Ү" */ + 0x0, + + /* U+04AF "ү" */ + 0x0, + + /* U+04B0 "Ұ" */ + 0x0, + + /* U+04B1 "ұ" */ + 0x0, + + /* U+04B2 "Ҳ" */ + 0x0, + + /* U+04B3 "ҳ" */ + 0x0, + + /* U+04B4 "Ҵ" */ + 0x0, + + /* U+04B5 "ҵ" */ + 0x0, + + /* U+04B6 "Ҷ" */ + 0x0, + + /* U+04B7 "ҷ" */ + 0x0, + + /* U+04B8 "Ҹ" */ + 0x0, + + /* U+04B9 "ҹ" */ + 0x0, + + /* U+04BA "Һ" */ + 0x0, + + /* U+04BB "һ" */ + 0x0, + + /* U+04BC "Ҽ" */ + 0x0, + + /* U+04BD "ҽ" */ + 0x0, + + /* U+04BE "Ҿ" */ + 0x0, + + /* U+04BF "ҿ" */ + 0x0, + + /* U+04C0 "Ӏ" */ + 0x0, + + /* U+04C1 "Ӂ" */ + 0x0, + + /* U+04C2 "ӂ" */ + 0x0, + + /* U+04C3 "Ӄ" */ + 0x0, + + /* U+04C4 "ӄ" */ + 0x0, + + /* U+04C5 "Ӆ" */ + 0x0, + + /* U+04C6 "ӆ" */ + 0x0, + + /* U+04C7 "Ӈ" */ + 0x0, + + /* U+04C8 "ӈ" */ + 0x0, + + /* U+04C9 "Ӊ" */ + 0x0, + + /* U+04CA "ӊ" */ + 0x0, + + /* U+04CB "Ӌ" */ + 0x0, + + /* U+04CC "ӌ" */ + 0x0, + + /* U+04CD "Ӎ" */ + 0x0, + + /* U+04CE "ӎ" */ + 0x0, + + /* U+04CF "ӏ" */ + 0x0, + + /* U+04D0 "Ӑ" */ + 0x0, + + /* U+04D1 "ӑ" */ + 0x0, + + /* U+04D2 "Ӓ" */ + 0x0, + + /* U+04D3 "ӓ" */ + 0x0, + + /* U+04D4 "Ӕ" */ + 0x0, + + /* U+04D5 "ӕ" */ + 0x0, + + /* U+04D6 "Ӗ" */ + 0x0, + + /* U+04D7 "ӗ" */ + 0x0, + + /* U+04D8 "Ә" */ + 0x0, + + /* U+04D9 "ә" */ + 0x0, + + /* U+04DA "Ӛ" */ + 0x0, + + /* U+04DB "ӛ" */ + 0x0, + + /* U+04DC "Ӝ" */ + 0x0, + + /* U+04DD "ӝ" */ + 0x0, + + /* U+04DE "Ӟ" */ + 0x0, + + /* U+04DF "ӟ" */ + 0x0, + + /* U+04E0 "Ӡ" */ + 0x0, + + /* U+04E1 "ӡ" */ + 0x0, + + /* U+04E2 "Ӣ" */ + 0x0, + + /* U+04E3 "ӣ" */ + 0x0, + + /* U+04E4 "Ӥ" */ + 0x0, + + /* U+04E5 "ӥ" */ + 0x0, + + /* U+04E6 "Ӧ" */ + 0x0, + + /* U+04E7 "ӧ" */ + 0x0, + + /* U+04E8 "Ө" */ + 0x0, + + /* U+04E9 "ө" */ + 0x0, + + /* U+04EA "Ӫ" */ + 0x0, + + /* U+04EB "ӫ" */ + 0x0, + + /* U+04EC "Ӭ" */ + 0x0, + + /* U+04ED "ӭ" */ + 0x0, + + /* U+04EE "Ӯ" */ + 0x0, + + /* U+04EF "ӯ" */ + 0x0, + + /* U+04F0 "Ӱ" */ + 0x0, + + /* U+04F1 "ӱ" */ + 0x0, + + /* U+04F2 "Ӳ" */ + 0x0, + + /* U+04F3 "ӳ" */ + 0x0, + + /* U+04F4 "Ӵ" */ + 0x0, + + /* U+04F5 "ӵ" */ + 0x0, + + /* U+04F6 "Ӷ" */ + 0x0, + + /* U+04F7 "ӷ" */ + 0x0, + + /* U+04F8 "Ӹ" */ + 0x0, + + /* U+04F9 "ӹ" */ + 0x0, + + /* U+04FA "Ӻ" */ + 0x0, + + /* U+04FB "ӻ" */ + 0x0, + + /* U+04FC "Ӽ" */ + 0x0, + + /* U+04FD "ӽ" */ + 0x0, + + /* U+04FE "Ӿ" */ + 0x0, + + /* U+04FF "ӿ" */ + 0x0, + + /* U+0500 "Ԁ" */ + 0x0, + + /* U+0501 "ԁ" */ + 0x0, + + /* U+0502 "Ԃ" */ + 0x0, + + /* U+0503 "ԃ" */ + 0x0, + + /* U+0504 "Ԅ" */ + 0x0, + + /* U+0505 "ԅ" */ + 0x0, + + /* U+0506 "Ԇ" */ + 0x0, + + /* U+0507 "ԇ" */ + 0x0, + + /* U+0508 "Ԉ" */ + 0x0, + + /* U+0509 "ԉ" */ + 0x0, + + /* U+050A "Ԋ" */ + 0x0, + + /* U+050B "ԋ" */ + 0x0, + + /* U+050C "Ԍ" */ + 0x0, + + /* U+050D "ԍ" */ + 0x0, + + /* U+050E "Ԏ" */ + 0x0, + + /* U+050F "ԏ" */ + 0x0, + + /* U+0510 "Ԑ" */ + 0x0, + + /* U+0511 "ԑ" */ + 0x0, + + /* U+0512 "Ԓ" */ + 0x0, + + /* U+0513 "ԓ" */ + 0x0, + + /* U+0514 "Ԕ" */ + 0x0, + + /* U+0515 "ԕ" */ + 0x0, + + /* U+0516 "Ԗ" */ + 0x0, + + /* U+0517 "ԗ" */ + 0x0, + + /* U+0518 "Ԙ" */ + 0x0, + + /* U+0519 "ԙ" */ + 0x0, + + /* U+051A "Ԛ" */ + 0x0, + + /* U+051B "ԛ" */ + 0x0, + + /* U+051C "Ԝ" */ + 0x0, + + /* U+051D "ԝ" */ + 0x0, + + /* U+051E "Ԟ" */ + 0x0, + + /* U+051F "ԟ" */ + 0x0, + + /* U+0520 "Ԡ" */ + 0x0, + + /* U+0521 "ԡ" */ + 0x0, + + /* U+0522 "Ԣ" */ + 0x0, + + /* U+0523 "ԣ" */ + 0x0, + + /* U+0524 "Ԥ" */ + 0x0, + + /* U+0525 "ԥ" */ + 0x0, + + /* U+0526 "Ԧ" */ + 0x0, + + /* U+0527 "ԧ" */ + 0x0, + + /* U+0528 "Ԩ" */ + 0x0, + + /* U+0529 "ԩ" */ + 0x0, + + /* U+052A "Ԫ" */ + 0x0, + + /* U+052B "ԫ" */ + 0x0, + + /* U+052C "Ԭ" */ + 0x0, + + /* U+052D "ԭ" */ + 0x0, + + /* U+052E "Ԯ" */ + 0x0, + + /* U+052F "ԯ" */ + 0x0, + + /* U+200B "​" */ + 0x0, + + /* U+2010 "‐" */ + 0x0, + + /* U+2011 "‑" */ + 0x0, + + /* U+2013 "–" */ + 0xff, 0xff, 0xff, 0xf0, + + /* U+2014 "—" */ + 0x0, + + /* U+2018 "‘" */ + 0x0, + + /* U+2019 "’" */ + 0x0, + + /* U+201C "“" */ + 0x38, 0x39, 0xe1, 0xee, 0xe, 0x30, 0x30, 0xf8, + 0xfb, 0xf3, 0xff, 0xcf, 0xff, 0x3f, 0xfc, 0xfd, + 0xe1, 0xe0, + + /* U+201D "”" */ + 0x78, 0x7b, 0xf3, 0xff, 0xcf, 0xff, 0x3f, 0xfc, + 0xfd, 0xf1, 0xf0, 0xc0, 0xc7, 0x7, 0x78, 0x79, + 0xc1, 0xc0, + + /* U+2020 "†" */ + 0x0, + + /* U+2021 "‡" */ + 0x0, + + /* U+2026 "…" */ + 0x0, + + /* U+2030 "‰" */ + 0x0, + + /* U+2032 "′" */ + 0x0, + + /* U+2033 "″" */ + 0x0, + + /* U+2039 "‹" */ + 0x6, 0x1c, 0x71, 0xc7, 0x1c, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x30, + + /* U+203A "›" */ + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc3, 0x8e, 0x38, + 0xe3, 0x86, 0x0, + + /* U+20A4 "₤" */ + 0xf, 0x83, 0xf8, 0xe3, 0x18, 0x3, 0x0, 0xff, + 0x9f, 0xf0, 0xc0, 0x7f, 0xcf, 0xf8, 0xc0, 0x38, + 0x7, 0xfe, 0xff, 0xc0, + + /* U+20A8 "₨" */ + 0xfc, 0x3, 0xf8, 0xc, 0x70, 0x30, 0xc0, 0xc3, + 0x3, 0xc, 0xc, 0x77, 0xbf, 0x9e, 0xfc, 0x63, + 0x31, 0xec, 0xc3, 0xf1, 0x83, 0xc6, 0x7f, 0x19, + 0xe0, + + /* U+20A9 "₩" */ + 0x0, 0x0, 0xc1, 0x83, 0xc1, 0x83, 0xe3, 0xc7, + 0x63, 0xc6, 0x63, 0xc6, 0x73, 0xce, 0xff, 0xff, + 0xff, 0xff, 0x36, 0x6c, 0x1e, 0x78, 0x1e, 0x78, + 0x1c, 0x38, 0xc, 0x30, 0xc, 0x30, + + /* U+20AA "₪" */ + 0xff, 0xf, 0xfe, 0x3c, 0x1c, 0xf0, 0x33, 0xcc, + 0xcf, 0x33, 0x3c, 0xcc, 0xf3, 0x33, 0xcc, 0xcf, + 0x33, 0x3c, 0xc0, 0xf3, 0x7, 0xcf, 0xfb, 0x3f, + 0xc0, + + /* U+20AC "€" */ + 0x3, 0xe0, 0xfe, 0x1c, 0x3, 0x80, 0x30, 0xf, + 0xf8, 0xff, 0x8f, 0xf8, 0xff, 0x83, 0x0, 0x38, + 0x1, 0xc0, 0xf, 0xe0, 0x3e, + + /* U+20B4 "₴" */ + 0x3, 0x81, 0xfc, 0x1c, 0xe0, 0x6, 0x0, 0x6f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x0, 0x30, + 0x3, 0xbe, 0x1f, 0xe0, 0xc0, + + /* U+20B8 "₸" */ + 0xff, 0xff, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, + 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x6, 0x0, 0x60, + + /* U+20BD "₽" */ + 0x3f, 0xc3, 0xfe, 0x30, 0x73, 0x3, 0x30, 0x33, + 0x3, 0x30, 0x7f, 0xfe, 0xff, 0xc3, 0x0, 0xff, + 0xcf, 0xfc, 0x30, 0x3, 0x0, + + /* U+2122 "™" */ + 0xff, 0x60, 0x7f, 0xee, 0x1c, 0x61, 0xc3, 0x8c, + 0x3c, 0xf1, 0x87, 0xfe, 0x30, 0xde, 0xc6, 0x1b, + 0xd8, 0xc3, 0x33, 0x18, 0x60, 0x63, 0xc, 0xc, + + /* U+2190 "←" */ + 0x6, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x38, 0x0, + 0x70, 0x0, 0xff, 0xff, 0xff, 0xff, 0x70, 0x0, + 0x38, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x6, 0x0, + + /* U+2191 "↑" */ + 0x6, 0x0, 0xf0, 0x1f, 0x83, 0xfc, 0x76, 0xee, + 0x67, 0xc6, 0x30, 0x60, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, + + /* U+2192 "→" */ + 0x0, 0x60, 0x0, 0x70, 0x0, 0x38, 0x0, 0x1c, + 0x0, 0xe, 0xff, 0xff, 0xff, 0xff, 0x0, 0xe, + 0x0, 0x1c, 0x0, 0x38, 0x0, 0x70, 0x0, 0x60, + + /* U+2193 "↓" */ + 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, + 0x60, 0x6, 0x0, 0x60, 0x6, 0xc, 0x63, 0xe6, + 0x77, 0x6e, 0x3f, 0xc1, 0xf8, 0xf, 0x0, 0x60, + + /* U+2194 "↔" */ + 0x18, 0x0, 0x38, 0x0, 0x78, 0x0, 0xff, 0xff, + 0xff, 0xff, 0x78, 0x0, 0x38, 0x0, 0x18, 0x0, + 0x0, 0x18, 0x0, 0x1c, 0x0, 0x1e, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x1e, 0x0, 0x1c, 0x0, 0x18, + + /* U+2195 "↕" */ + 0x18, 0x18, 0x3c, 0x18, 0x7e, 0x18, 0xff, 0x18, + 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x18, 0xff, 0x18, 0x7e, 0x18, 0x3c, 0x18, 0x18, + + /* U+2197 "↗" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x3f, 0xe0, 0xff, 0x83, 0xfe, 0xf, 0xf1, 0x3f, + 0x8e, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+21BA "↺" */ + 0xc7, 0xe0, 0xdf, 0xf8, 0xfc, 0x3c, 0xf0, 0xe, + 0xfc, 0x6, 0xfc, 0x7, 0x0, 0x3, 0x0, 0x3, + 0x0, 0x3, 0x0, 0x3, 0x0, 0x7, 0x60, 0x6, + 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+21BB "↻" */ + 0x0, 0x0, 0x1, 0xf8, 0xc3, 0xff, 0x63, 0x81, + 0xf3, 0x0, 0x79, 0x80, 0xfd, 0x80, 0x7e, 0xc0, + 0x0, 0x60, 0x0, 0x30, 0x0, 0x18, 0x0, 0xc, + 0x0, 0x7, 0x0, 0x21, 0x80, 0x30, 0x70, 0x38, + 0x1f, 0xf8, 0x7, 0xf0, 0x0, 0x0, 0x0, + + /* U+21C4 "⇄" */ + 0x0, 0x18, 0x0, 0x1c, 0x0, 0xe, 0xff, 0xff, + 0xff, 0xff, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x18, + 0x18, 0x0, 0x38, 0x0, 0x70, 0x0, 0xff, 0xff, + 0xff, 0xff, 0x70, 0x0, 0x38, 0x0, 0x18, 0x0, + + /* U+2212 "−" */ + 0xff, 0xff, 0xff, 0xf0, + + /* U+221E "∞" */ + 0x1e, 0x7, 0x87, 0xf9, 0xfe, 0x61, 0x98, 0x6c, + 0xf, 0x3, 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0, + 0xf0, 0x36, 0x19, 0x86, 0x7f, 0x9f, 0xe1, 0xe0, + 0x78, + + /* U+2303 "⌃" */ + 0x6, 0x0, 0xf0, 0x1f, 0x83, 0x9c, 0x70, 0xee, + 0x7, 0xc0, 0x30, + + /* U+2304 "⌄" */ + 0xc0, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, 0x80, + 0xf0, 0x6, 0x0, + + /* U+231B "⌛" */ + 0xff, 0xff, 0xff, 0x60, 0x66, 0x6, 0x70, 0xc3, + 0x9c, 0x1f, 0x80, 0xf0, 0xf, 0x1, 0xf8, 0x3f, + 0xc7, 0xfc, 0x7f, 0xe7, 0xfe, 0xff, 0xff, 0xff, + + /* U+2328 "⌨" */ + 0x7f, 0xff, 0xbf, 0xff, 0xfc, 0x92, 0x4f, 0x24, + 0x93, 0xff, 0xff, 0xf2, 0x49, 0x3c, 0x92, 0x4f, + 0xff, 0xff, 0xf8, 0x7, 0xfe, 0x1, 0xff, 0xff, + 0xfd, 0xff, 0xfe, + + /* U+2329 "〈" */ + 0x3, 0x7, 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xe0, + 0x70, 0x38, 0x1c, 0xe, 0x7, 0x3, + + /* U+232A "〉" */ + 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x7, + 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xc0, + + /* U+232B "⌫" */ + 0x7, 0xff, 0x83, 0xff, 0xf1, 0xff, 0xfc, 0xfc, + 0xdf, 0x7f, 0x27, 0xff, 0xe3, 0xff, 0xf8, 0xfd, + 0xfc, 0x9f, 0x3f, 0x37, 0xc7, 0xff, 0xf0, 0xff, + 0xfc, 0x1f, 0xfe, + + /* U+2399 "⎙" */ + 0x1f, 0xf0, 0x3f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf, + 0x30, 0xc, 0x30, 0xc, 0x3f, 0xfc, 0x1f, 0xf8, + + /* U+23CF "⏏" */ + 0x3, 0x0, 0x1e, 0x0, 0xfc, 0x7, 0xf8, 0x3f, + 0xf1, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, + 0xf0, + + /* U+23E9 "⏩" */ + 0xc0, 0xc0, 0xe1, 0xe0, 0xf1, 0xf0, 0xf9, 0xf8, + 0xfd, 0xfc, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0xfd, 0xfc, 0xf9, 0xf8, 0xf1, 0xf0, + 0xe1, 0xe0, 0xc0, 0xc0, + + /* U+23EA "⏪" */ + 0x3, 0x3, 0x7, 0x87, 0xf, 0x8f, 0x1f, 0x9f, + 0x3f, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xff, 0x3f, 0xbf, 0x1f, 0x9f, 0xf, 0x8f, + 0x7, 0x87, 0x3, 0x3, + + /* U+23ED "⏭" */ + 0xc1, 0x83, 0xe1, 0xc3, 0xf1, 0xe3, 0xf9, 0xf3, + 0xfd, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xfb, 0xf9, 0xf3, 0xf1, 0xe3, + 0xe1, 0xc3, 0xc1, 0x83, + + /* U+23EE "⏮" */ + 0xc1, 0x83, 0xc3, 0x87, 0xc7, 0x8f, 0xcf, 0x9f, + 0xdf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xdf, 0xbf, 0xcf, 0x9f, 0xc7, 0x8f, + 0xc3, 0x87, 0xc1, 0x83, + + /* U+23F0 "⏰" */ + 0x78, 0x1e, 0xf0, 0xf, 0xe7, 0xe7, 0xcf, 0xf3, + 0x1f, 0xf8, 0x3e, 0x7c, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x3e, 0x7f, 0xbe, 0x7f, 0xfc, + 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfe, 0x63, 0xc6, + + /* U+23F1 "⏱" */ + 0xf, 0x80, 0x10, 0x3, 0xe0, 0x7f, 0xf7, 0xff, + 0xbe, 0xfb, 0xf7, 0xff, 0xbf, 0xfd, 0xff, 0xef, + 0xff, 0xff, 0xff, 0xf7, 0xff, 0x1f, 0xf0, 0x7f, + 0x1, 0xf0, + + /* U+23F3 "⏳" */ + 0xff, 0xff, 0xff, 0x60, 0x66, 0x6, 0x70, 0xc3, + 0x9c, 0x1f, 0x80, 0xf0, 0xf, 0x1, 0xf8, 0x39, + 0xc7, 0xc, 0x60, 0x66, 0x6, 0xff, 0xff, 0xff, + + /* U+23F8 "⏸" */ + 0xf9, 0xff, 0x9f, 0xf9, 0xff, 0x9f, 0xf9, 0xff, + 0x9f, 0xf9, 0xff, 0x9f, 0xf9, 0xff, 0x9f, 0xf9, + 0xff, 0x9f, 0xf9, 0xff, 0x9f, + + /* U+23F9 "⏹" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+23FB "⏻" */ + 0x1, 0x80, 0x1, 0x80, 0x19, 0x98, 0x39, 0x9c, + 0x71, 0x8e, 0x61, 0x86, 0xe1, 0x87, 0xc1, 0x83, + 0xc1, 0x83, 0xc1, 0x83, 0xc0, 0x3, 0xe0, 0x7, + 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, + 0x7, 0xe0, + + /* U+23FE "⏾" */ + 0xf, 0xe0, 0x7f, 0x3, 0xf0, 0x1f, 0xc0, 0x7e, + 0x3, 0xf8, 0xf, 0xe0, 0x3f, 0x80, 0xfe, 0x3, + 0xfc, 0x7, 0xf8, 0x1f, 0xf0, 0x3f, 0xfc, 0x7f, + 0xe0, 0x7e, 0x0, + + /* U+24BD "Ⓗ" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7b, 0x9e, 0xfb, 0x9f, 0xfb, 0x9f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xfb, 0x9f, 0xfb, 0x9f, 0x7b, 0x9e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+25A0 "■" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+25B6 "▶" */ + 0xc0, 0x7, 0x80, 0x3f, 0x1, 0xfe, 0xf, 0xfc, + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, + 0x3f, 0xc1, 0xf8, 0xf, 0x0, 0x60, 0x0, + + /* U+25CF "●" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+25D0 "◐" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0x3c, 0x7f, 0xe, + 0x7f, 0x6, 0xff, 0x7, 0xff, 0x3, 0xff, 0x3, + 0xff, 0x3, 0xff, 0x3, 0xff, 0x7, 0x7f, 0x6, + 0x7f, 0xe, 0x3f, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+25FB "◻" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+25FC "◼" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2600 "☀" */ + 0x4, 0x10, 0x7, 0xbc, 0x3, 0xfe, 0x1, 0xff, + 0x7, 0xff, 0xf7, 0xe0, 0xfd, 0xe7, 0x3c, 0xf7, + 0xde, 0x3b, 0xee, 0x3d, 0xf7, 0x9e, 0x73, 0xdf, + 0x83, 0xf7, 0xff, 0xf0, 0x7f, 0xc0, 0x3f, 0xe0, + 0x1e, 0xf0, 0x4, 0x10, 0x0, + + /* U+2601 "☁" */ + 0x7, 0x80, 0x3, 0xf8, 0x1, 0xff, 0xe0, 0x7f, + 0xfc, 0x1f, 0xff, 0xf, 0xff, 0xc7, 0xff, 0xf3, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0x8f, 0xff, 0xc0, + + /* U+2603 "☃" */ + 0x0, 0xf0, 0x0, 0x1f, 0x80, 0x3, 0xfc, 0x0, + 0x36, 0xc0, 0x3, 0xfc, 0x0, 0x39, 0xc0, 0x1, + 0x98, 0x3, 0x1f, 0x8c, 0xf3, 0xfc, 0xf7, 0xff, + 0xfe, 0x1f, 0x9f, 0x80, 0x79, 0xe0, 0x7, 0xfe, + 0x0, 0x79, 0xe0, 0x7, 0x9e, 0x0, 0x7f, 0xe0, + 0x3, 0xfc, 0x0, 0x1f, 0x80, + + /* U+2604 "☄" */ + 0x0, 0x3, 0x0, 0x8f, 0x3, 0xfe, 0xf, 0xfe, + 0x1f, 0xfc, 0x3f, 0xfc, 0x70, 0xfc, 0xe0, 0x7e, + 0xcc, 0x3c, 0xcc, 0x3c, 0xc0, 0x38, 0xc2, 0x38, + 0x60, 0x70, 0x70, 0xe0, 0x3f, 0xc0, 0xf, 0x80, + + /* U+2611 "☑" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x9f, 0xfe, 0xff, 0xf3, 0xf9, 0x9f, 0xe4, 0xff, + 0xc7, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2615 "☕" */ + 0x0, 0x0, 0x36, 0x0, 0x33, 0x0, 0x19, 0x80, + 0x9, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfc, + 0xff, 0xfe, 0xff, 0xf7, 0xff, 0xf3, 0xff, 0xf3, + 0xff, 0xf7, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xf0, + 0x7f, 0xe0, + + /* U+261D "☝" */ + 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, 0x6c, 0x6, + 0xd8, 0x6d, 0xb0, 0x1b, 0x1, 0xb7, 0xc3, 0xfd, + 0xce, 0x3f, 0xff, 0xf7, 0xfe, 0x7f, 0xe1, 0xf8, + + /* U+2620 "☠" */ + 0x7, 0x80, 0x7f, 0x81, 0xfe, 0xf, 0xfc, 0x33, + 0x30, 0xcc, 0xc1, 0xfe, 0x7, 0xf8, 0xf, 0xc0, + 0x3f, 0xc, 0x0, 0xfe, 0x1f, 0x3f, 0xf0, 0x3f, + 0x3, 0xff, 0x3e, 0x1f, 0xc0, 0xc, + + /* U+2622 "☢" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x73, 0xce, + 0x63, 0xc6, 0xe3, 0xc7, 0xc6, 0x63, 0xc6, 0x63, + 0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0x7c, 0x3e, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+2623 "☣" */ + 0x2, 0x20, 0x2, 0x8, 0x3, 0x76, 0x1, 0xbb, + 0x0, 0xc1, 0x80, 0x71, 0xc0, 0x7f, 0xf0, 0x7e, + 0xfe, 0x66, 0x33, 0x65, 0xf6, 0xe3, 0x76, 0x31, + 0xbb, 0x10, 0x1c, 0x0, 0x1b, 0x0, 0xf8, 0xf8, + 0x0, 0x0, + + /* U+2625 "☥" */ + 0x1e, 0xf, 0xc7, 0x39, 0x86, 0x61, 0x98, 0x63, + 0x30, 0xfc, 0xff, 0xff, 0xf0, 0xc0, 0x30, 0xc, + 0x3, 0x0, 0xc0, 0x30, + + /* U+262A "☪" */ + 0x7, 0xe0, 0x1f, 0x0, 0x3e, 0x0, 0x7c, 0x0, + 0x78, 0x8, 0xf0, 0x18, 0xf0, 0x3e, 0xf0, 0x7f, + 0xf0, 0x3e, 0xf0, 0x3c, 0xf0, 0x3e, 0x78, 0x2, + 0x7c, 0x0, 0x3c, 0x0, 0x1f, 0x0, 0x7, 0xe0, + + /* U+262C "☬" */ + 0x1, 0x80, 0x3, 0xc0, 0x13, 0xc4, 0x67, 0xe6, + 0x6d, 0xb6, 0xed, 0xb7, 0xed, 0xb7, 0xe7, 0xe7, + 0xf3, 0xcf, 0x7b, 0xde, 0x7d, 0xbe, 0x3f, 0xfc, + 0x19, 0x98, 0x7, 0xe0, 0x5, 0xa0, 0x1, 0x80, + + /* U+262E "☮" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3d, 0xbc, 0x71, 0x8e, + 0x61, 0x86, 0xe1, 0x87, 0xc1, 0x83, 0xc1, 0x83, + 0xc3, 0xc3, 0xc7, 0xe3, 0xff, 0xff, 0x79, 0x9e, + 0x71, 0x8e, 0x3d, 0xbc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+262F "☯" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0x1e, + 0x61, 0x9e, 0xe1, 0x9f, 0xc0, 0x1f, 0xc0, 0x3f, + 0xc3, 0xff, 0xc7, 0xff, 0xe6, 0x7f, 0x66, 0x7e, + 0x77, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+2638 "☸" */ + 0x1, 0x80, 0x7, 0xe0, 0x3f, 0xfc, 0x3d, 0xbc, + 0x3d, 0xbc, 0x7f, 0xfe, 0x67, 0xe6, 0xfe, 0x7f, + 0xfe, 0x7f, 0x67, 0xe6, 0x7f, 0xfe, 0x3d, 0xbc, + 0x3d, 0xbc, 0x3f, 0xfc, 0x7, 0xe0, 0x1, 0x80, + + /* U+2639 "☹" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xfc, 0x3f, 0xf8, 0x1f, 0x73, 0xce, + 0x77, 0xee, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+263F "☿" */ + 0x0, 0xc, 0x31, 0xfe, 0x3f, 0xc7, 0x1d, 0xc1, + 0xf0, 0x1e, 0x3, 0xc0, 0x7c, 0x1d, 0xc7, 0x3f, + 0xc1, 0xe0, 0x18, 0xf, 0xc1, 0xf8, 0xc, 0x1, + 0x80, + + /* U+2640 "♀" */ + 0x1f, 0x7, 0xf1, 0xc7, 0x70, 0x7c, 0x7, 0x80, + 0xf0, 0x1f, 0x7, 0x71, 0xcf, 0xf0, 0x78, 0x6, + 0x0, 0xc0, 0x7e, 0xf, 0xc0, 0x60, 0xc, 0x0, + + /* U+2642 "♂" */ + 0x0, 0x7e, 0x0, 0xfc, 0x0, 0x78, 0x1, 0xf1, + 0xf7, 0x67, 0xfc, 0xdc, 0x70, 0x70, 0x70, 0xc0, + 0x61, 0x80, 0xc3, 0x1, 0x87, 0x7, 0x7, 0x1c, + 0x7, 0xf0, 0x7, 0xc0, 0x0, + + /* U+265A "♚" */ + 0x3, 0x0, 0xc, 0x0, 0xfc, 0x3, 0xf0, 0x3, + 0x0, 0xc, 0xf, 0xff, 0xff, 0xff, 0x7f, 0xf9, + 0xff, 0xe3, 0xff, 0xf, 0xfc, 0x1f, 0xe0, 0x7f, + 0x83, 0xff, 0x1f, 0xfe, 0x7f, 0xf8, + + /* U+265B "♛" */ + 0x1, 0x80, 0x3, 0xc0, 0x1, 0x80, 0x4, 0x20, + 0x4e, 0x72, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf0, + 0xf, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, + + /* U+265C "♜" */ + 0xee, 0x7e, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0x7f, 0xe3, 0xfc, 0x3f, 0xc3, 0xfc, 0x3f, + 0xc3, 0xfc, 0x3f, 0xc7, 0xfe, 0xff, 0xff, 0xff, + + /* U+265D "♝" */ + 0x3f, 0xf, 0xc1, 0xe0, 0xfc, 0x7e, 0x1f, 0x2f, + 0x8f, 0xe7, 0xff, 0xff, 0xf7, 0xf9, 0xfc, 0x3f, + 0x1f, 0xef, 0xff, 0xff, + + /* U+265E "♞" */ + 0x1f, 0x1, 0xfc, 0x3f, 0xe3, 0x3e, 0x73, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x67, 0xf0, 0xff, 0x1f, + 0xf3, 0xfe, 0x3f, 0xe7, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xf0, + + /* U+265F "♟" */ + 0xe, 0x7, 0xe0, 0xfe, 0x1f, 0xc3, 0xf8, 0x7f, + 0xf, 0xe1, 0xfc, 0x1f, 0x3, 0xe0, 0xfe, 0x1f, + 0xc3, 0xf8, 0x7f, 0x1f, 0xf7, 0xff, 0xff, 0xe0, + + /* U+2665 "♥" */ + 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, + 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf0, + 0x7, 0xe0, 0x1, 0x80, + + /* U+2666 "♦" */ + 0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0xf, 0xf0, + 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, + 0xf, 0xf0, 0x7, 0xe0, 0x3, 0xc0, 0x1, 0x80, + + /* U+2672 "♲" */ + 0x0, 0x0, 0x0, 0xfc, 0x0, 0x33, 0x0, 0x8, + 0x68, 0x0, 0x1e, 0xf, 0x7, 0x87, 0xc1, 0xe0, + 0xf0, 0x0, 0x34, 0x0, 0x1c, 0x0, 0x66, 0x0, + 0x19, 0x80, 0x86, 0x60, 0x61, 0x8f, 0x3f, 0xc1, + 0xcf, 0xe0, 0x1, 0x80, 0x0, 0x20, 0x0, + + /* U+267A "♺" */ + 0x0, 0x0, 0x0, 0xfc, 0x0, 0x33, 0x0, 0x8, + 0x68, 0x0, 0x1e, 0xf, 0x7, 0x87, 0xc1, 0xe0, + 0xf0, 0x0, 0x34, 0x0, 0x1c, 0x0, 0x66, 0x0, + 0x19, 0x80, 0x86, 0x60, 0x61, 0x8f, 0x3f, 0xc1, + 0xcf, 0xe0, 0x1, 0x80, 0x0, 0x20, 0x0, + + /* U+267B "♻" */ + 0x0, 0x0, 0x0, 0xfc, 0x0, 0x33, 0x0, 0x8, + 0x68, 0x0, 0x1e, 0xf, 0x7, 0x87, 0xc1, 0xe0, + 0xf0, 0x0, 0x34, 0x0, 0x1c, 0x0, 0x66, 0x0, + 0x19, 0x80, 0x86, 0x60, 0x61, 0x8f, 0x3f, 0xc1, + 0xcf, 0xe0, 0x1, 0x80, 0x0, 0x20, 0x0, + + /* U+267E "♾" */ + 0x1e, 0x7, 0x87, 0xf9, 0xfe, 0x61, 0x98, 0x6c, + 0xf, 0x3, 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0, + 0xf0, 0x36, 0x19, 0x86, 0x7f, 0x9f, 0xe1, 0xe0, + 0x78, + + /* U+2680 "⚀" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2681 "⚁" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xe7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0x7f, 0xf9, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2682 "⚂" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xe7, + 0xff, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xff, 0xff, + 0xfe, 0x7f, 0xf9, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2683 "⚃" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0xe7, + 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x9e, 0x7e, 0x79, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2684 "⚄" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0xe7, + 0x9f, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xff, 0xff, + 0x9e, 0x7e, 0x79, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2685 "⚅" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0xe7, + 0x9f, 0xff, 0xfe, 0x79, 0xf9, 0xe7, 0xff, 0xff, + 0x9e, 0x7e, 0x79, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2693 "⚓" */ + 0x3, 0xc0, 0x3, 0xf0, 0x1, 0x98, 0x0, 0xcc, + 0x0, 0x7e, 0x0, 0x1e, 0x0, 0x6, 0x0, 0x63, + 0xc, 0x79, 0x8f, 0x7e, 0xcf, 0xcc, 0x61, 0x86, + 0x31, 0xc1, 0x98, 0xc0, 0xed, 0xe0, 0x3f, 0xe0, + 0x7, 0xc0, + + /* U+2696 "⚖" */ + 0x0, 0x60, 0x1, 0xff, 0xf8, 0x1f, 0xff, 0x80, + 0xf, 0x0, 0x18, 0xe1, 0x81, 0x86, 0x18, 0x3c, + 0x63, 0xc6, 0x46, 0x66, 0x66, 0x66, 0x6c, 0x36, + 0xc3, 0xff, 0x6f, 0xff, 0xe6, 0x7e, 0x3c, 0x63, + 0xc0, 0x6, 0x0, 0x1f, 0xff, 0x81, 0xff, 0xf8, + + /* U+2699 "⚙" */ + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x77, 0xee, + 0x7f, 0xff, 0xff, 0xff, 0x7e, 0x7e, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff, + 0x7f, 0xff, 0x77, 0xee, 0x3, 0xc0, 0x3, 0xc0, + 0x3, 0xc0, + + /* U+269B "⚛" */ + 0x7, 0x0, 0x1e, 0x0, 0xcc, 0x1f, 0xfe, 0xff, + 0xff, 0x7f, 0xbf, 0x87, 0xde, 0xde, 0x7b, 0x7b, + 0xe1, 0xfd, 0xfe, 0xff, 0xff, 0x7f, 0xf8, 0x33, + 0x0, 0x78, 0x1, 0xc0, + + /* U+26A0 "⚠" */ + 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, + 0x7, 0xe0, 0xe, 0x70, 0xe, 0x70, 0x1e, 0x78, + 0x1e, 0x78, 0x3e, 0x7c, 0x3f, 0xfc, 0x7e, 0x7e, + 0x7e, 0x7e, 0xff, 0xff, 0xff, 0xff, + + /* U+26A1 "⚡" */ + 0x0, 0x0, 0x3, 0x80, 0x1e, 0x0, 0xf0, 0x7, + 0xc0, 0x3f, 0x3, 0xf8, 0x1f, 0xe0, 0xff, 0xff, + 0xff, 0xf0, 0x7f, 0x81, 0xfc, 0x7, 0xc0, 0x3e, + 0x0, 0xf0, 0x7, 0x80, 0x1c, 0x0, 0x0, 0x0, + + /* U+26A2 "⚢" */ + 0x1f, 0x1f, 0x7, 0xf3, 0xf1, 0xc7, 0x7, 0x70, + 0x70, 0x7c, 0x6, 0x7, 0x80, 0xc0, 0xf0, 0x18, + 0x1f, 0x7, 0x7, 0x71, 0xc1, 0xcf, 0xf3, 0xf0, + 0x78, 0x7c, 0x6, 0x7, 0x0, 0xc0, 0xe0, 0x7e, + 0x3e, 0xf, 0xc7, 0xc0, 0x60, 0x70, 0xc, 0x4, + 0x0, + + /* U+26A3 "⚣" */ + 0x0, 0x7e, 0xf0, 0x7, 0xef, 0x0, 0x1e, 0xf0, + 0x3, 0xef, 0x1f, 0x76, 0xb3, 0xfe, 0x63, 0x71, + 0xc0, 0xe, 0xe, 0x70, 0xc0, 0x63, 0xc, 0x6, + 0x30, 0xc0, 0x63, 0xe, 0xe, 0x70, 0x71, 0xce, + 0x3, 0xf9, 0xc0, 0x1f, 0x38, 0x0, + + /* U+26A4 "⚤" */ + 0x0, 0x7, 0xe0, 0x0, 0xfc, 0x0, 0x3, 0x8f, + 0x3f, 0xf3, 0xff, 0xf6, 0xe7, 0x8e, 0xf8, 0xf8, + 0xe6, 0x1b, 0xc, 0xc7, 0x61, 0x98, 0x6c, 0x33, + 0x8f, 0x8e, 0x39, 0xe3, 0x87, 0xff, 0xe0, 0x3c, + 0xf8, 0x3, 0x0, 0x1, 0xf8, 0x0, 0x3f, 0x0, + 0x1, 0x80, 0x0, 0x30, 0x0, 0x0, + + /* U+26A5 "⚥" */ + 0x0, 0x7c, 0x1, 0xf0, 0x3, 0xc7, 0xdf, 0x3f, + 0xed, 0xc7, 0xe, 0xe, 0x30, 0x18, 0xc0, 0x63, + 0x1, 0x8e, 0xe, 0x1c, 0x70, 0x3f, 0x80, 0x7c, + 0x0, 0xe0, 0x7, 0xc0, 0x1f, 0x0, 0x38, 0x0, + 0x40, 0x0, + + /* U+26A6 "⚦" */ + 0x0, 0x3f, 0x0, 0x3f, 0x0, 0xf, 0x0, 0x5f, + 0x0, 0x7b, 0x1f, 0x73, 0x3f, 0xf8, 0x71, 0xc0, + 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, + 0xe0, 0xe0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0, + + /* U+26A7 "⚧" */ + 0xf8, 0x7, 0xfe, 0x1, 0xfe, 0x0, 0x3f, 0xf0, + 0x1f, 0xdb, 0xfe, 0xc7, 0xff, 0x0, 0x61, 0xc0, + 0x30, 0x30, 0xc, 0xc, 0x3, 0x3, 0x0, 0xc0, + 0xc0, 0x18, 0x60, 0x7, 0xf8, 0x0, 0x78, 0x0, + 0xc, 0x0, 0xf, 0xc0, 0x3, 0xf0, 0x0, 0x30, + 0x0, 0x0, 0x0, + + /* U+26A8 "⚨" */ + 0xc, 0x3, 0xc0, 0xfc, 0x16, 0x80, 0xc0, 0x7e, + 0xf, 0xc0, 0x60, 0x3f, 0xf, 0xfb, 0x83, 0x60, + 0x3c, 0x7, 0x80, 0xf8, 0x3b, 0x8e, 0x3f, 0x83, + 0xe0, + + /* U+26A9 "⚩" */ + 0x0, 0x0, 0xf, 0xc0, 0x7, 0xf8, 0x1, 0x87, + 0x6c, 0xc0, 0xd9, 0xb0, 0x3f, 0xfc, 0xf, 0xff, + 0x3, 0x66, 0xe0, 0xdb, 0x1c, 0x60, 0x3, 0xf8, + 0x0, 0x78, 0x0, + + /* U+26AA "⚪" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+26AB "⚫" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+26B2 "⚲" */ + 0x1e, 0xf, 0xc6, 0x3b, 0x87, 0xc0, 0xf0, 0x3c, + 0xf, 0x87, 0x63, 0x9f, 0xc1, 0xe0, 0x30, 0xc, + 0x3, 0x0, 0xc0, 0x30, 0xc, 0x0, + + /* U+26BD "⚽" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x71, 0x8e, + 0x60, 0x6, 0xf0, 0xf, 0xf1, 0x8f, 0xe3, 0xc7, + 0xc3, 0xc3, 0xc3, 0xc3, 0xe0, 0x7, 0x7c, 0x3e, + 0x7c, 0x3e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+26BE "⚾" */ + 0x6, 0x60, 0x1e, 0x78, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7d, 0xfe, 0xf9, 0xff, 0xf3, 0xff, 0x3f, 0xfc, + 0x3f, 0xfc, 0xff, 0xcf, 0xff, 0x9f, 0x7f, 0xbe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1e, 0x78, 0x6, 0x60, + + /* U+26C4 "⛄" */ + 0x0, 0xf0, 0x0, 0x1f, 0x80, 0x3, 0xfc, 0x0, + 0x36, 0xc0, 0x3, 0xfc, 0x0, 0x39, 0xc0, 0x1, + 0x98, 0x3, 0x1f, 0x8c, 0xf3, 0xfc, 0xf7, 0xff, + 0xfe, 0x1f, 0x9f, 0x80, 0x79, 0xe0, 0x7, 0xfe, + 0x0, 0x79, 0xe0, 0x7, 0x9e, 0x0, 0x7f, 0xe0, + 0x3, 0xfc, 0x0, 0x1f, 0x80, + + /* U+26C5 "⛅" */ + 0x0, 0x44, 0x0, 0x3b, 0x80, 0xf, 0xe0, 0xf, + 0xfe, 0x7, 0x83, 0xc0, 0x2e, 0xe0, 0x0, 0xb8, + 0x38, 0xe, 0x1f, 0x73, 0x8f, 0xfe, 0xf3, 0xff, + 0x81, 0xff, 0xf8, 0xff, 0xff, 0x3f, 0xff, 0xcf, + 0xff, 0xf3, 0xff, 0xfc, 0x7f, 0xfe, 0x0, + + /* U+26C6 "⛆" */ + 0xe, 0x0, 0x1f, 0x70, 0x3f, 0xf8, 0x3f, 0xf8, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x10, 0x8, 0x31, 0x8c, 0x31, 0x8c, 0x31, 0x8c, + + /* U+26DF "⛟" */ + 0x7f, 0xf8, 0x3f, 0xfe, 0xf, 0xff, 0xc3, 0xff, + 0xfc, 0xff, 0xff, 0xbf, 0xff, 0x7f, 0xff, 0xcf, + 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xcf, 0xcf, 0x73, 0xf3, 0x84, 0x84, 0xc1, + 0xc0, 0xe0, + + /* U+26E9 "⛩" */ + 0x0, 0x3, 0x0, 0x3f, 0xff, 0xff, 0xff, 0x7f, + 0xf8, 0xcc, 0xc3, 0x33, 0x1f, 0xfe, 0x7f, 0xf8, + 0xc0, 0xc3, 0x3, 0xc, 0xc, 0x30, 0x30, 0xc0, + 0xc3, 0x3, 0xc, 0xc, + + /* U+26EA "⛪" */ + 0x0, 0x0, 0x1, 0x80, 0x7, 0xe0, 0x1, 0x80, + 0x1, 0x80, 0x3, 0xc0, 0xf, 0xf0, 0xf, 0xf0, + 0x1f, 0xf8, 0x1f, 0xf8, 0x7f, 0xfe, 0xfe, 0x7f, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0x7f, 0xfe, + + /* U+26F7 "⛷" */ + 0x0, 0x3, 0xc, 0x3, 0xc7, 0x1c, 0xc2, 0x7f, + 0x0, 0xf, 0x80, 0x10, 0xf0, 0x6, 0x3c, 0x1, + 0x80, 0x0, 0xe0, 0x60, 0x30, 0x38, 0x18, 0x7, + 0x18, 0x0, 0xfc, 0x0, 0x1c, 0x0, 0x3, 0x80, + 0x0, 0x70, 0x0, 0xf, 0x0, + + /* U+26FA "⛺" */ + 0x6, 0x60, 0x7, 0xe0, 0x3, 0xc0, 0x1, 0x80, + 0x3, 0xc0, 0x7, 0xe0, 0xf, 0xf0, 0x1f, 0xf8, + 0x1f, 0xf8, 0x3f, 0xfc, 0x7e, 0x7e, 0xfc, 0x3f, + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, + + /* U+26FD "⛽" */ + 0x7f, 0x80, 0x7f, 0x80, 0xe1, 0xcc, 0xe1, 0xce, + 0xe1, 0xcf, 0xe1, 0xc7, 0xff, 0xc7, 0xff, 0xc3, + 0xff, 0xf3, 0xff, 0xdb, 0xff, 0xdb, 0xff, 0xdb, + 0xff, 0xdb, 0xff, 0xce, 0xff, 0xc0, 0x7f, 0x80, + + /* U+2700 "✀" */ + 0x38, 0x0, 0x7c, 0x6, 0xc6, 0x1f, 0xc6, 0x3e, + 0xc6, 0x7c, 0x7f, 0xf8, 0x3f, 0xf0, 0x7, 0xe0, + 0x3, 0xc0, 0x3f, 0x90, 0x7f, 0x38, 0xc6, 0x7c, + 0xc6, 0x3e, 0xc6, 0x1f, 0x7c, 0x6, 0x38, 0x0, + + /* U+2702 "✂" */ + 0x38, 0x0, 0x7c, 0x6, 0xc6, 0x1f, 0xc6, 0x3e, + 0xc6, 0x7c, 0x7f, 0xf8, 0x3f, 0xf0, 0x7, 0xe0, + 0x3, 0xc0, 0x3f, 0x90, 0x7f, 0x38, 0xc6, 0x7c, + 0xc6, 0x3e, 0xc6, 0x1f, 0x7c, 0x6, 0x38, 0x0, + + /* U+2704 "✄" */ + 0x38, 0x0, 0x7c, 0x6, 0xc6, 0x1f, 0xc6, 0x3e, + 0xc6, 0x7c, 0x7f, 0xf8, 0x3f, 0xf0, 0x7, 0xe0, + 0x3, 0xc0, 0x3f, 0x90, 0x7f, 0x38, 0xc6, 0x7c, + 0xc6, 0x3e, 0xc6, 0x1f, 0x7c, 0x6, 0x38, 0x0, + + /* U+2705 "✅" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x9f, 0xfe, 0xff, 0xf3, 0xf9, 0x9f, 0xe4, 0xff, + 0xc7, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2709 "✉" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, + 0x1f, 0xf8, 0xcf, 0xf3, 0xe3, 0xc7, 0xf1, 0x8f, + 0xf8, 0x1f, 0xfe, 0x7f, 0xff, 0xff, 0x7f, 0xfe, + + /* U+270A "✊" */ + 0x4, 0x6, 0xf8, 0x7f, 0x87, 0xfb, 0x1, 0xb0, + 0x1b, 0x7c, 0x3f, 0xdc, 0xe3, 0xff, 0xff, 0x7f, + 0xe3, 0xfe, 0x1f, 0xc1, 0xfc, 0x1f, 0xc0, 0xfc, + + /* U+270B "✋" */ + 0x1, 0x80, 0x1b, 0x60, 0x36, 0xc0, 0x6d, 0xb0, + 0xdb, 0x61, 0xb6, 0xc3, 0x6d, 0x86, 0xdb, 0xf, + 0xff, 0xdf, 0xff, 0xff, 0xfb, 0xff, 0xf3, 0xff, + 0xe3, 0xff, 0x83, 0xfe, 0x1, 0xf8, + + /* U+270C "✌" */ + 0x6, 0x6, 0x30, 0x19, 0x80, 0xcc, 0x7, 0x60, + 0x1b, 0x60, 0xdb, 0x60, 0x1b, 0x0, 0xd9, 0xf0, + 0xdf, 0xb8, 0xe3, 0xf7, 0xff, 0x9f, 0xf8, 0xff, + 0xc1, 0xf8, + + /* U+270F "✏" */ + 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x9f, + 0x1, 0xcf, 0x3, 0xe6, 0x7, 0xf0, 0xf, 0xf8, + 0x1f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0, 0x7f, 0x80, + 0x4f, 0x0, 0xce, 0x0, 0xfc, 0x0, 0xe0, 0x0, + + /* U+2711 "✑" */ + 0x0, 0xc, 0x0, 0x1e, 0x0, 0x3f, 0x1, 0x9f, + 0xf, 0xce, 0x1f, 0xe4, 0x1f, 0xf0, 0x3f, 0xf8, + 0x38, 0xf8, 0x38, 0xf0, 0x70, 0xf0, 0x63, 0xf0, + 0x47, 0xe0, 0x8f, 0x80, 0x1c, 0x0, 0x20, 0x0, + + /* U+2712 "✒" */ + 0x0, 0xe, 0x0, 0x1f, 0x0, 0x3f, 0x0, 0x7f, + 0x0, 0xfe, 0x0, 0xfc, 0x1, 0xf8, 0x1, 0xf0, + 0x18, 0xc0, 0x3c, 0x0, 0x7e, 0x0, 0x67, 0x0, + 0x67, 0x0, 0x5e, 0x0, 0xbc, 0x0, 0x40, 0x0, + + /* U+2713 "✓" */ + 0x0, 0xc, 0x0, 0x70, 0x1, 0x80, 0xc, 0x0, + 0x70, 0x3, 0x80, 0xc, 0x30, 0x70, 0xe3, 0x81, + 0xcc, 0x3, 0xe0, 0x7, 0x80, 0xc, 0x0, + + /* U+2714 "✔" */ + 0x0, 0xc, 0x0, 0x70, 0x1, 0x80, 0xc, 0x0, + 0x70, 0x3, 0x80, 0xc, 0x30, 0x70, 0xe3, 0x81, + 0xcc, 0x3, 0xe0, 0x7, 0x80, 0xc, 0x0, + + /* U+2715 "✕" */ + 0xc0, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, 0x80, + 0xf0, 0xf, 0x1, 0xf8, 0x39, 0xc7, 0xe, 0xe0, + 0x7c, 0x3, + + /* U+2716 "✖" */ + 0xc0, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, 0x80, + 0xf0, 0xf, 0x1, 0xf8, 0x39, 0xc7, 0xe, 0xe0, + 0x7c, 0x3, + + /* U+271D "✝" */ + 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf, 0x0, 0xf0, 0xf, + 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, + + /* U+2721 "✡" */ + 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x6, 0x60, + 0xff, 0xff, 0xff, 0xff, 0x4c, 0x32, 0x78, 0x1e, + 0x30, 0xc, 0x30, 0xc, 0x78, 0x1e, 0x4c, 0x32, + 0xff, 0xff, 0xff, 0xff, 0x6, 0x60, 0x3, 0xc0, + 0x3, 0xc0, 0x1, 0x80, + + /* U+2731 "✱" */ + 0x3, 0x0, 0xc, 0x0, 0x30, 0x0, 0xc0, 0xe3, + 0x1d, 0xed, 0xe3, 0xff, 0x3, 0xf0, 0xf, 0xc0, + 0xff, 0xc7, 0xb7, 0xb8, 0xc7, 0x3, 0x0, 0xc, + 0x0, 0x30, 0x0, 0xc0, + + /* U+2744 "❄" */ + 0x1, 0x80, 0x1, 0x80, 0x7, 0xe0, 0x7, 0xe0, + 0xdb, 0xdb, 0xf9, 0x9f, 0x3d, 0xbc, 0x7f, 0xfe, + 0x7, 0xe0, 0x7, 0xe0, 0x7f, 0xfe, 0x3d, 0xbc, + 0xf9, 0x9f, 0xdb, 0xdb, 0x7, 0xe0, 0x7, 0xe0, + 0x1, 0x80, 0x1, 0x80, + + /* U+2746 "❆" */ + 0x1, 0x80, 0x1, 0x80, 0x7, 0xe0, 0x7, 0xe0, + 0xdb, 0xdb, 0xf9, 0x9f, 0x3d, 0xbc, 0x7f, 0xfe, + 0x7, 0xe0, 0x7, 0xe0, 0x7f, 0xfe, 0x3d, 0xbc, + 0xf9, 0x9f, 0xdb, 0xdb, 0x7, 0xe0, 0x7, 0xe0, + 0x1, 0x80, 0x1, 0x80, + + /* U+274C "❌" */ + 0xc0, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, 0x80, + 0xf0, 0xf, 0x1, 0xf8, 0x39, 0xc7, 0xe, 0xe0, + 0x7c, 0x3, + + /* U+274E "❎" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, + 0x3f, 0xc0, 0xff, 0x87, 0xfe, 0x1f, 0xf0, 0x3f, + 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+2753 "❓" */ + 0x1e, 0x1f, 0xe6, 0x1b, 0x3, 0xc0, 0xf0, 0x30, + 0xc, 0x6, 0x7, 0x83, 0xc0, 0xc0, 0x30, 0x0, + 0x0, 0x0, 0xc0, 0x30, + + /* U+2754 "❔" */ + 0x1e, 0x1f, 0xe6, 0x1b, 0x3, 0xc0, 0xf0, 0x30, + 0xc, 0x6, 0x7, 0x83, 0xc0, 0xc0, 0x30, 0x0, + 0x0, 0x0, 0xc0, 0x30, + + /* U+2755 "❕" */ + 0xff, 0xff, 0xff, 0xf, + + /* U+2757 "❗" */ + 0xff, 0xff, 0xff, 0xf, + + /* U+2764 "❤" */ + 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, + 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf0, + 0x7, 0xe0, 0x1, 0x80, + + /* U+2795 "➕" */ + 0x3, 0x0, 0xc, 0x0, 0x30, 0x0, 0xc0, 0x3, + 0x0, 0xc, 0xf, 0xff, 0xff, 0xff, 0x3, 0x0, + 0xc, 0x0, 0x30, 0x0, 0xc0, 0x3, 0x0, 0xc, + 0x0, + + /* U+2796 "➖" */ + 0xff, 0xff, 0xff, 0xf0, + + /* U+2797 "➗" */ + 0x3, 0x0, 0x1e, 0x0, 0x30, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x30, 0x1, 0xe0, 0x3, 0x0, + + /* U+2934 "⤴" */ + 0x6, 0x1, 0xe0, 0x7e, 0x1f, 0xe7, 0xfe, 0xff, + 0xc3, 0xc0, 0x78, 0xf, 0x1, 0xe0, 0x3c, 0x7, + 0x8f, 0xf1, 0xfc, 0x3f, 0x87, 0xc0, + + /* U+2935 "⤵" */ + 0xf8, 0x1f, 0xc3, 0xf8, 0x7f, 0x80, 0xf0, 0x1e, + 0x3, 0xc0, 0x78, 0xf, 0x1, 0xe1, 0xff, 0xbf, + 0xf3, 0xfc, 0x3f, 0x3, 0xc0, 0x30, + + /* U+2B0D "⬍" */ + 0x18, 0x18, 0x3c, 0x18, 0x7e, 0x18, 0xff, 0x18, + 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x18, 0xff, 0x18, 0x7e, 0x18, 0x3c, 0x18, 0x18, + + /* U+2B1B "⬛" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+2B1C "⬜" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+2B23 "⬣" */ + 0xf, 0xf8, 0xf, 0xfe, 0x7, 0xff, 0x7, 0xff, + 0xc7, 0xff, 0xf3, 0xff, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xbf, 0xff, 0x9f, 0xff, 0xc7, + 0xff, 0xc1, 0xff, 0xc0, 0xff, 0xe0, 0x3f, 0xe0, + + /* U+2B24 "⬤" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+2B50 "⭐" */ + 0x0, 0xc0, 0x0, 0x30, 0x0, 0x1e, 0x0, 0x7, + 0x80, 0x3, 0xf0, 0xf, 0xff, 0xcf, 0xff, 0xfd, + 0xff, 0xfe, 0x3f, 0xff, 0x7, 0xff, 0x80, 0xff, + 0xc0, 0x3f, 0xf0, 0xf, 0xfc, 0x3, 0xff, 0x0, + 0xf3, 0xc0, 0x70, 0x38, + + /* U+E005 "" */ + 0x3, 0x0, 0x3f, 0xf0, 0x3f, 0xf0, 0x3, 0x0, + 0x3, 0x0, 0xf, 0xc0, 0xff, 0xf8, 0xff, 0xfe, + 0xff, 0xfe, 0x7f, 0xff, 0x7, 0x8f, 0x0, 0xf, + + /* U+E006 "" */ + 0x3, 0x0, 0x3f, 0xf0, 0x3f, 0xf0, 0x3, 0x0, + 0x3, 0x0, 0xf, 0xc0, 0xff, 0xf8, 0xff, 0xfe, + 0xff, 0xfe, 0x7f, 0xff, 0x7, 0x8f, 0x0, 0xf, + 0x0, 0x0, 0x0, 0x4, 0x0, 0x6, 0x0, 0x6, + + /* U+E00D "" */ + 0x1, 0x80, 0x1, 0xe2, 0x1, 0xfb, 0x81, 0xff, + 0xc1, 0xff, 0xe1, 0xff, 0xf1, 0xff, 0xfd, 0xfc, + 0x7e, 0x7e, 0x3f, 0x1f, 0x1f, 0xf, 0x8f, 0x87, + 0xff, 0xc3, 0xff, 0xe1, 0xff, 0xf0, 0xff, 0xf8, + 0x3f, 0xf8, + + /* U+E012 "" */ + 0x0, 0xe0, 0x0, 0x7c, 0x0, 0x3f, 0x80, 0x1f, + 0xf0, 0xf, 0xfe, 0xf, 0xff, 0xe3, 0xf1, 0xf8, + 0xfc, 0x7e, 0xf, 0x1f, 0x38, 0xff, 0xc7, 0x9f, + 0xf0, 0x33, 0xfc, 0xe6, 0x7f, 0x1d, 0x9f, 0x83, + 0xb0, 0x3, 0x6c, 0x0, 0xdb, 0x0, 0x0, + + /* U+E03F "" */ + 0x1c, 0xc, 0x3e, 0xc, 0x3e, 0xc, 0x3e, 0xc, + 0x3e, 0xc, 0x3e, 0xc, 0x3e, 0x3f, 0x3e, 0x3f, + 0x77, 0x1e, 0x77, 0xc, 0xe3, 0x80, 0xe3, 0x80, + 0xe3, 0x80, 0xf7, 0x80, 0x7f, 0x0, 0x3e, 0x0, + + /* U+E040 "" */ + 0x1e, 0xc, 0x3f, 0x1e, 0x3b, 0x3f, 0x33, 0x3f, + 0x33, 0xc, 0x33, 0xc, 0x33, 0xc, 0x33, 0xc, + 0x73, 0xc, 0x73, 0x8c, 0xe1, 0x80, 0xe1, 0xc0, + 0xe1, 0x80, 0xf3, 0x80, 0x7f, 0x0, 0x1e, 0x0, + + /* U+E041 "" */ + 0x7f, 0xfe, 0xf, 0xff, 0xf0, 0xee, 0x77, 0xe, + 0xe7, 0x70, 0xee, 0x77, 0xe, 0xe7, 0x70, 0xee, + 0x77, 0xe, 0xe7, 0x70, 0xee, 0x77, 0xf, 0xff, + 0xf0, 0xff, 0xff, 0xe7, 0x9f, 0xfe, 0x19, 0x80, + 0x0, 0x98, 0x0, 0x7, 0x0, 0x0, + + /* U+E059 "" */ + 0x1, 0x80, 0x0, 0x7e, 0x0, 0x7, 0xe0, 0x1, + 0xff, 0x0, 0x1f, 0xf0, 0x7, 0xde, 0x0, 0x7f, + 0xe1, 0x8e, 0x78, 0x7e, 0xe7, 0x87, 0xe7, 0xe1, + 0xff, 0x7e, 0x1f, 0xf1, 0x87, 0xfe, 0x0, 0x73, + 0xe0, 0xf, 0x38, 0x0, 0xff, 0x80, 0x7, 0xe0, + 0x0, 0x7e, 0x0, 0x1, 0x80, + + /* U+E05A "" */ + 0x0, 0x30, 0x1, 0x3e, 0x1, 0xfe, 0x5, 0xfe, + 0x7, 0xff, 0x3, 0xff, 0x1f, 0xfc, 0xf, 0xfc, + 0x7c, 0xfe, 0x3e, 0xf0, 0xf3, 0xd8, 0xf3, 0xc0, + 0x7f, 0x40, 0x3f, 0x0, 0x5d, 0x0, 0xc, 0x0, + + /* U+E05B "" */ + 0x3f, 0x80, 0x3f, 0xc0, 0x1f, 0xc0, 0x1f, 0xf8, + 0x1f, 0xfc, 0x1f, 0xf8, 0x1f, 0xf8, 0x4f, 0xfa, + 0xcf, 0xf3, 0xc0, 0x3, 0xe0, 0x7, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + + /* U+E05C "" */ + 0x0, 0xc0, 0x0, 0x78, 0x0, 0x3f, 0x0, 0x1f, + 0xe0, 0x7, 0xf8, 0x0, 0xfc, 0x0, 0x1e, 0x0, + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xc, 0x7f, 0xcf, 0xff, 0x7, 0xbf, 0xff, 0xcf, + 0xff, 0xc3, 0xff, 0xe0, + + /* U+E05D "" */ + 0x0, 0x60, 0x0, 0x36, 0xc0, 0x23, 0x6c, 0x2, + 0x36, 0xd8, 0xfb, 0x6d, 0x82, 0x36, 0xd8, 0x23, + 0x6d, 0x80, 0x36, 0xd8, 0x3, 0xff, 0x83, 0xbf, + 0xf8, 0x3f, 0xbf, 0x1, 0xf1, 0xf4, 0xf, 0xbc, + 0x40, 0x7f, 0xdf, 0x3, 0xfc, 0x40, 0xf, 0xc4, + + /* U+E05E "" */ + 0x2, 0x98, 0x6, 0x98, 0x7, 0x80, 0xd, 0x60, + 0xc8, 0x13, 0xf9, 0xb3, 0xf7, 0x80, 0xef, 0x0, + 0xcf, 0xfe, 0x5f, 0xc0, 0x1f, 0xff, 0x1f, 0xc0, + 0xf, 0xfe, 0x37, 0xfe, 0x77, 0xf8, 0x33, 0xfc, + + /* U+E05F "" */ + 0xc0, 0x0, 0x38, 0x0, 0x7, 0x0, 0x4, 0xf9, + 0xf7, 0x9c, 0xff, 0xf3, 0xff, 0xfe, 0x7f, 0xff, + 0xce, 0xff, 0xf9, 0xdf, 0xff, 0x39, 0xff, 0xe7, + 0x3d, 0xfc, 0xe6, 0x3f, 0x9c, 0x7, 0xf3, 0x80, + 0xfe, 0x70, 0x1c, 0xce, 0x0, 0x1, 0xc0, 0x0, + 0x30, + + /* U+E060 "" */ + 0xc0, 0x0, 0x38, 0x0, 0x7, 0x0, 0x4, 0xf9, + 0xf7, 0x9c, 0xff, 0xf3, 0xff, 0xfe, 0x7f, 0xff, + 0xce, 0xff, 0xf9, 0xdf, 0xff, 0x39, 0xff, 0xe7, + 0x3d, 0xfc, 0xe6, 0x3f, 0x9c, 0x7, 0xf3, 0x80, + 0xfe, 0x70, 0x1c, 0xce, 0x0, 0x1, 0xc0, 0x0, + 0x30, + + /* U+E061 "" */ + 0xf0, 0x0, 0xfc, 0x0, 0xfe, 0x0, 0xff, 0x0, + 0xff, 0x0, 0xf7, 0x80, 0xf7, 0x80, 0xff, 0xc0, + 0xff, 0xe3, 0xff, 0xc3, 0xff, 0xc, 0xff, 0x33, + 0xf3, 0x33, 0xff, 0xc, 0xff, 0x3, 0xfe, 0x3, + + /* U+E062 "" */ + 0x0, 0x0, 0x5e, 0x0, 0x37, 0xe0, 0x19, 0xfc, + 0xc, 0x7f, 0x86, 0x1f, 0xe3, 0x7, 0x9d, 0x81, + 0xe7, 0xc0, 0x7f, 0xe0, 0x1f, 0xf0, 0x67, 0xf8, + 0x19, 0xfc, 0x18, 0x7e, 0x59, 0x9f, 0x36, 0x67, + 0x98, 0x61, 0xce, 0x6, 0xe7, 0x1, 0xb0, 0x0, + 0x0, + + /* U+E063 "" */ + 0xf, 0xc0, 0x1f, 0xe0, 0x3f, 0xf0, 0x7f, 0xf8, + 0x3f, 0xfc, 0x8f, 0x9c, 0xc7, 0x9c, 0xf1, 0xfe, + 0xfc, 0xff, 0xfe, 0x2, 0x7f, 0x3e, 0x3f, 0x6, + 0x3f, 0x3e, 0x3f, 0x6, 0x3f, 0xc, 0x3f, 0xf8, + + /* U+E064 "" */ + 0x7, 0xc0, 0x1f, 0xf0, 0x3e, 0xf8, 0x70, 0x18, + 0xf0, 0x1c, 0xf6, 0x1c, 0xe0, 0xe, 0xf0, 0x9f, + 0xf0, 0x1f, 0x70, 0x1f, 0x7e, 0xfc, 0x3f, 0xfc, + 0x3f, 0xfc, 0x3f, 0xf8, 0x3f, 0xe0, 0x1f, 0xc0, + + /* U+E065 "" */ + 0x0, 0x80, 0x0, 0xe2, 0x0, 0xff, 0x81, 0xff, + 0xc1, 0xff, 0xe1, 0xff, 0xf1, 0xf8, 0xfd, 0xfc, + 0x7e, 0x7e, 0x3f, 0x1f, 0x1f, 0xf, 0xff, 0x87, + 0x83, 0xc3, 0x80, 0xe1, 0xc0, 0x70, 0xff, 0xf8, + 0x3f, 0xf8, + + /* U+E066 "" */ + 0x1, 0x80, 0x0, 0x3c, 0x0, 0x7, 0xe0, 0x0, + 0xff, 0x0, 0x1f, 0xf8, 0x7, 0xff, 0xe0, 0x7e, + 0x7e, 0x7, 0xe7, 0xe0, 0x3e, 0x0, 0x3, 0xf7, + 0xfc, 0x3f, 0x7f, 0xc3, 0xf6, 0xc, 0x3f, 0x60, + 0xc1, 0xf6, 0xc, 0x0, 0x60, 0xc0, 0xf, 0xff, + 0x0, 0xff, 0xe0, + + /* U+E067 "" */ + 0x0, 0xc0, 0x1, 0xb6, 0x0, 0xed, 0xc0, 0x7b, + 0x78, 0x3e, 0xde, 0xf, 0x87, 0xc7, 0xe1, 0xf9, + 0xc3, 0xe, 0xf6, 0xdb, 0xbd, 0xfe, 0xfe, 0x3f, + 0x1f, 0xbf, 0xf7, 0xef, 0xfd, 0xf8, 0xfc, 0x7f, + 0x7f, 0xbd, 0xdb, 0x6e, 0x0, 0xc0, 0x0, + + /* U+E068 "" */ + 0x30, 0xc, 0x78, 0x1e, 0x78, 0x1e, 0x30, 0xc, + 0x0, 0x0, 0x60, 0xe, 0xee, 0x67, 0xdf, 0xf3, + 0xdf, 0xf3, 0xee, 0x67, 0x70, 0xe, 0x70, 0x1e, + 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x70, 0x1e, + + /* U+E069 "" */ + 0xc0, 0x0, 0x39, 0x80, 0x7, 0x70, 0x0, 0xfe, + 0x0, 0x1f, 0xc0, 0x33, 0xf8, 0xe, 0x7f, 0x1, + 0xcf, 0xfe, 0x79, 0xff, 0xdf, 0x3f, 0xf7, 0xe7, + 0xfb, 0x8c, 0xe0, 0xc3, 0x9c, 0x1, 0xf3, 0x80, + 0x78, 0x70, 0x1c, 0xe, 0x6, 0x1, 0xc0, 0x0, + 0x30, + + /* U+E06A "" */ + 0x1e, 0x7, 0xf1, 0xe0, 0x0, 0x0, 0x1f, 0xef, + 0xff, 0xff, 0xf3, 0xfc, 0xfc, 0xf, 0x3, 0xf3, + 0xfc, 0xff, 0xff, 0xff, 0x7f, 0x80, + + /* U+E06B "" */ + 0x1e, 0x7, 0xf1, 0xe0, 0x0, 0x0, 0x1f, 0xef, + 0xff, 0xff, 0xf3, 0xfc, 0xfe, 0x1f, 0x87, 0xe1, + 0xfc, 0xff, 0xff, 0xff, 0x7f, 0x80, + + /* U+E06C "" */ + 0x3, 0x80, 0x1f, 0xc1, 0xff, 0xf7, 0xff, 0xff, + 0xef, 0xfe, 0x3, 0xfc, 0x7, 0xfb, 0xf, 0x60, + 0xc, 0xe1, 0x39, 0xc0, 0x71, 0x80, 0xc1, 0xef, + 0x3, 0xfc, 0x1, 0xf0, 0x1, 0xc0, + + /* U+E06D "" */ + 0x0, 0xf0, 0x1, 0xf8, 0x1, 0x98, 0x1, 0x98, + 0x1, 0x80, 0x1, 0x80, 0x71, 0x9e, 0x19, 0x98, + 0x19, 0x98, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfc, + + /* U+E06E "" */ + 0x6, 0x18, 0xf, 0x18, 0x6, 0x0, 0x0, 0x0, + 0x0, 0xe0, 0x0, 0xe0, 0x7c, 0xe6, 0xfc, 0xe7, + 0xe0, 0xf, 0xc0, 0x7, 0xdf, 0xf3, 0xdf, 0xf3, + 0xdf, 0xf3, 0xe0, 0x7, 0xff, 0xff, 0x7f, 0xfe, + + /* U+E06F "" */ + 0xf, 0x80, 0x10, 0x7, 0xe0, 0x7f, 0xf7, 0xff, + 0xbb, 0xbb, 0x88, 0xfd, 0x57, 0xf2, 0xbf, 0xb5, + 0xf9, 0xae, 0xc4, 0x67, 0xff, 0x1f, 0xf0, 0x3e, + 0x0, + + /* U+E070 "" */ + 0x40, 0x0, 0xc, 0x0, 0x0, 0xff, 0xfc, 0xf, + 0xff, 0x80, 0xff, 0xf8, 0x4f, 0xff, 0x1c, 0xff, + 0xf3, 0xcf, 0xfe, 0x7c, 0xff, 0xc3, 0xe, 0x30, + 0x60, 0xc6, 0xc, 0xc, 0xc1, 0x80, 0xd8, 0x3f, + 0xcf, 0x7, 0xfc, 0xe0, 0xff, 0x8c, 0x0, 0x0, + 0xc0, 0x0, 0x8, + + /* U+E071 "" */ + 0xc0, 0x0, 0x38, 0x0, 0x7, 0xff, 0xf0, 0xff, + 0xfc, 0x1f, 0xff, 0x1b, 0xff, 0xe7, 0x7f, 0xf8, + 0xef, 0xdc, 0x1, 0xc0, 0x0, 0x38, 0x3, 0x7, + 0x30, 0xc0, 0xec, 0x3f, 0x9f, 0xf, 0xf3, 0xc3, + 0xfe, 0x70, 0xff, 0xce, 0x0, 0x1, 0xc0, 0x0, + 0x30, + + /* U+E072 "" */ + 0xc0, 0x0, 0x1c, 0x0, 0x1, 0xff, 0x98, 0x1f, + 0xf7, 0x80, 0xfc, 0xf0, 0x8f, 0xbf, 0x18, 0xf6, + 0x63, 0xce, 0xcc, 0x7c, 0xd9, 0x8f, 0xcf, 0x31, + 0xfc, 0xfe, 0x3f, 0xcf, 0x87, 0xfc, 0xf0, 0xff, + 0x8c, 0x1f, 0xf0, 0xc3, 0xfe, 0xc, 0x7f, 0xc0, + 0xc7, 0xf0, 0x8, + + /* U+E073 "" */ + 0x60, 0x0, 0x7, 0x0, 0x0, 0x38, 0xf0, 0x1, + 0xdf, 0x80, 0x6f, 0xf9, 0xe7, 0x7f, 0x9e, 0x7b, + 0xf9, 0xe3, 0x1e, 0xc, 0x0, 0xe0, 0x0, 0x7, + 0x0, 0x39, 0x39, 0xc7, 0x39, 0xce, 0xf7, 0xce, + 0x7f, 0x7e, 0x73, 0xf7, 0xf3, 0x9f, 0x7f, 0x9c, + 0x0, 0x0, 0x60, 0x0, 0x2, + + /* U+E074 "" */ + 0x3, 0x80, 0x3, 0x80, 0x37, 0xdc, 0x3f, 0xfc, + 0x1f, 0xf8, 0x1f, 0xf8, 0x39, 0xfc, 0xf9, 0xff, + 0xff, 0x9f, 0x3f, 0x9c, 0x1f, 0xf8, 0x1f, 0xf8, + 0x3f, 0xfc, 0x37, 0xdc, 0x3, 0x80, 0x3, 0x80, + + /* U+E075 "" */ + 0xc0, 0x0, 0x38, 0x30, 0x7, 0xc, 0x0, 0xe7, + 0x98, 0x1f, 0xfe, 0x3, 0xff, 0x0, 0x7f, 0xc0, + 0x4f, 0xf8, 0x79, 0xff, 0x9f, 0x3f, 0xe1, 0xe7, + 0xe0, 0x3c, 0xf0, 0xf, 0x9c, 0x7, 0xf3, 0x81, + 0x9e, 0x70, 0x3, 0xe, 0x0, 0xc1, 0xc0, 0x0, + 0x30, + + /* U+E076 "" */ + 0x6, 0x0, 0x2, 0x64, 0x0, 0x7f, 0xe0, 0x3, + 0xfc, 0x0, 0x37, 0xc0, 0xf, 0xff, 0x0, 0xff, + 0xf0, 0x3, 0xec, 0x0, 0x3f, 0xc3, 0x7, 0xfe, + 0xbe, 0x26, 0x4f, 0xc0, 0x60, 0xdc, 0x0, 0x1d, + 0xf0, 0x0, 0xfe, 0x0, 0xf, 0xc0, 0x0, 0xfe, + 0x0, 0x3, 0x0, + + /* U+E085 "" */ + 0x38, 0x70, 0xff, 0xc3, 0x7b, 0xe, 0x1c, 0x38, + 0x70, 0xe1, 0xc7, 0x87, 0xbf, 0x3f, 0xfc, 0xff, + 0xf3, 0xff, 0xcf, 0xff, 0x3f, 0xfc, 0xff, 0xf3, + 0xff, 0xcf, 0xff, 0x3f, + + /* U+E086 "" */ + 0x18, 0x70, 0xff, 0xc3, 0x7b, 0xe, 0xc, 0x38, + 0x70, 0xe1, 0xc7, 0x87, 0xbf, 0x3f, 0xcc, 0xdf, + 0x33, 0x3f, 0xcc, 0xff, 0x3f, 0xcc, 0xff, 0x33, + 0xff, 0xcf, 0xff, 0x3f, + + /* U+E097 "" */ + 0xc0, 0x0, 0x38, 0x18, 0x7, 0xf, 0x0, 0xe7, + 0xe3, 0x1f, 0x9c, 0xc3, 0xc3, 0xb0, 0x60, 0x7c, + 0x0, 0xf, 0x0, 0x1f, 0xc0, 0x7, 0xf0, + + /* U+E098 "" */ + 0x0, 0x1f, 0xc0, 0x7, 0xf0, 0x0, 0x3c, 0x18, + 0x1f, 0xf, 0xe, 0xc7, 0xe7, 0x33, 0x9f, 0x8d, + 0xc3, 0xc0, 0xe0, 0x60, 0x30, 0x0, 0x0, + + /* U+E09A "" */ + 0x3, 0x0, 0x1e, 0x0, 0xfc, 0x7, 0xf8, 0x3b, + 0x70, 0xcc, 0xc0, 0x30, 0x0, 0xc0, 0x3, 0x0, + 0xc, 0xc, 0x30, 0xf0, 0x3, 0xc0, 0xf, 0x0, + 0x3f, 0xff, 0xdf, 0xfe, + + /* U+E0A9 "" */ + 0x0, 0x0, 0xc, 0x0, 0x78, 0x1, 0xe0, 0xf, + 0xc0, 0x33, 0x0, 0xcc, 0x3f, 0xff, 0x18, 0x60, + 0xe1, 0xcf, 0xff, 0xdc, 0xe, 0x60, 0x19, 0x80, + 0x60, + + /* U+E0AC "" */ + 0x18, 0x6, 0xf, 0xe3, 0xfc, 0xd9, 0xb6, 0x6d, + 0x9b, 0xfc, 0xff, 0xb6, 0x3d, 0x8f, 0x63, 0xff, + 0xbf, 0xc1, 0x80, 0x60, + + /* U+E0B4 "" */ + 0x2c, 0xb, 0xf, 0xe3, 0xfc, 0xc1, 0xb0, 0x6c, + 0x1b, 0xfc, 0xff, 0xb0, 0x3c, 0xf, 0x3, 0xff, + 0xbf, 0xc2, 0xc0, 0xb0, + + /* U+E0B7 "" */ + 0x7f, 0x7, 0xf0, 0x7e, 0x7, 0xe0, 0xfe, 0xf, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xe0, 0x7c, 0x7, + 0x80, 0x78, 0x7, 0x0, 0xe0, 0xe, 0x0, 0xc0, + + /* U+E0BB "" */ + 0x7c, 0x1f, 0xf0, 0x7f, 0xc1, 0xff, 0x7, 0xfc, + 0x9f, 0xf7, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1b, 0x0, + 0x6f, 0xff, 0xdf, 0xff, + + /* U+E0CF "" */ + 0x0, 0xc0, 0x6, 0xc0, 0x6, 0x1f, 0x0, 0xf8, + 0xf, 0xc0, 0x7d, 0x80, 0xc1, 0x80, 0x1, 0x80, + 0x3f, 0xfc, 0x7f, 0xfe, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, + 0x3f, 0xfc, + + /* U+E0D8 "" */ + 0x7, 0xe0, 0xf, 0xf0, 0x7f, 0xfe, 0xff, 0xff, + 0xfc, 0x7f, 0xf8, 0x7f, 0xf9, 0xcf, 0xf3, 0x87, + 0xe1, 0xcf, 0xe1, 0xdf, 0xf2, 0x1f, 0xfe, 0x3f, + 0xff, 0xff, 0x7f, 0xfe, + + /* U+E0DF "" */ + 0x6, 0x0, 0xc0, 0x7f, 0x3f, 0xf6, 0x67, 0xcc, + 0x31, 0x86, 0x30, 0xc6, 0x18, 0xc1, 0x99, 0xbf, + 0xf1, 0xfc, 0xc, 0x1, 0x80, + + /* U+E0E3 "" */ + 0xc0, 0x0, 0xc0, 0x3, 0xc0, 0x3, 0xc1, 0x83, + 0xc1, 0x83, 0xc1, 0xb3, 0xd9, 0xb3, 0xd9, 0xb3, + 0xd9, 0xb3, 0xd9, 0xb3, 0xc0, 0x0, 0xc0, 0x0, + 0xff, 0xff, 0x7f, 0xff, + + /* U+E0E4 "" */ + 0xc0, 0x0, 0xcf, 0x80, 0xcf, 0x80, 0xc0, 0x0, + 0xc0, 0x0, 0xc3, 0xf0, 0xc3, 0xf0, 0xc0, 0x0, + 0xc0, 0x1e, 0xc0, 0x1e, 0xc0, 0x0, 0xc0, 0x0, + 0xff, 0xff, 0x7f, 0xff, + + /* U+E131 "" */ + 0x73, 0x9c, 0xe7, 0x39, 0xce, 0x73, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+E139 "" */ + 0xe, 0xe0, 0x1f, 0xc0, 0x3f, 0x80, 0x7f, 0xf, + 0x7d, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xdf, 0x78, 0x7f, 0x0, 0xfe, + 0x1, 0xfc, 0x3, 0xb0, 0x0, + + /* U+E13A "" */ + 0x0, 0x8, 0xc, 0x78, 0x7c, 0xd9, 0xf9, 0xf2, + 0x61, 0xc4, 0x1, 0x8, 0x2, 0x10, 0x4, 0x20, + 0x8, 0x40, 0x10, 0x80, 0x21, 0x0, 0x47, 0xc, + 0x9b, 0x7e, 0x3e, 0x70, 0x38, 0x60, + + /* U+E13B "" */ + 0x70, 0x3b, 0xe1, 0xfd, 0x86, 0xfe, 0x1f, 0x70, + 0x38, 0x80, 0x43, 0x3, 0xf, 0xfc, 0x1f, 0xe0, + 0xc, 0x0, 0x30, 0x1, 0xe0, 0x7, 0x80, 0x33, + 0x0, 0x78, 0x1, 0xe0, + + /* U+E13C "" */ + 0x70, 0x41, 0xf1, 0x83, 0x67, 0xc6, 0xcf, 0xc7, + 0xd, 0x84, 0x9, 0x8, 0x2, 0x10, 0x4, 0x20, + 0x8, 0x40, 0x10, 0x80, 0x21, 0x0, 0x4f, 0x83, + 0xfb, 0x6, 0xfe, 0xf, 0xb8, 0xe, + + /* U+E140 "" */ + 0x0, 0x0, 0xd8, 0x3e, 0x1f, 0xe7, 0xde, 0xdb, + 0x32, 0x46, 0x48, 0xdb, 0x1b, 0x63, 0xc8, 0x39, + 0x33, 0xfe, 0x7f, 0x89, 0x1, 0x20, + + /* U+E152 "" */ + 0xf, 0xc1, 0xfe, 0x38, 0x76, 0x1, 0xe0, 0xc, + 0x0, 0xc6, 0xc, 0x7c, 0xc6, 0xe, 0x60, 0x66, + 0x3, 0x67, 0x1f, 0xe0, 0xfc, + + /* U+E163 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xc0, 0x3, 0xc0, 0x3, + 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, + 0xc0, 0x3, 0xc0, 0x3, 0xff, 0xff, 0x7f, 0xfe, + 0x3, 0xc0, 0x3, 0xc0, 0x1f, 0xf8, + + /* U+E169 "" */ + 0x0, 0xc0, 0xc, 0xf, 0xf0, 0xc, 0x0, 0xc1, + 0xfc, 0x3f, 0xc7, 0x1c, 0x60, 0xc6, 0xc, 0x60, + 0xc7, 0x1c, 0x3f, 0xc1, 0xfc, 0x0, 0xf, 0xff, + + /* U+E16D "" */ + 0x8, 0x7c, 0x1c, 0x38, 0x3e, 0x10, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xf1, 0xcf, 0xf1, 0xcf, 0xf1, 0xcf, 0xff, 0xff, + 0xe0, 0x87, 0xe0, 0x87, 0xe0, 0x87, 0xff, 0xff, + 0x7f, 0xfe, + + /* U+E17B "" */ + 0xff, 0xff, 0x3f, 0xff, 0xc7, 0xff, 0xe0, 0xff, + 0xf0, 0x1f, 0xf8, 0x3, 0xf8, 0x0, 0x7d, 0xf0, + 0xe, 0xfe, 0x3, 0x6e, 0xc0, 0xdd, 0x70, 0x37, + 0xbc, 0xd, 0xd7, 0x1, 0x6e, 0xc0, 0xf, 0xe0, + 0x1, 0xf0, + + /* U+E184 "" */ + 0x0, 0xf0, 0x1f, 0x1, 0x80, 0x38, 0x3, 0x0, + 0x30, 0x7f, 0xe7, 0xfe, 0xc, 0x0, 0xc0, 0x1c, + 0x1, 0x80, 0xf8, 0xf, 0x0, + + /* U+E185 "" */ + 0x3c, 0x0, 0xff, 0x0, 0xff, 0xfe, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, + + /* U+E18F "" */ + 0x3f, 0xc7, 0xf8, 0xc0, 0x18, 0x3, 0x0, 0x7f, + 0xf, 0xe1, 0x80, 0x30, 0x1f, 0xe0, 0xc0, 0x18, + 0x3, 0x0, 0x60, 0x0, + + /* U+E19A "" */ + 0x6, 0x0, 0x60, 0x1f, 0x83, 0xfc, 0x76, 0xee, + 0x60, 0xc6, 0xc, 0x7f, 0xc7, 0xfc, 0x63, 0x66, + 0x77, 0x6e, 0x3f, 0xc1, 0xf8, 0x6, 0x0, 0x60, + + /* U+E19B "" */ + 0x0, 0x1, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x0, + 0x7, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xf1, 0x0, + 0xf8, 0x40, 0x3e, 0x30, 0xf, 0xf8, 0x7, 0xe0, + 0x1, 0xf0, 0x0, 0x7c, 0x0, 0xe, 0x0, 0x0, + + /* U+E1A8 "" */ + 0x2, 0x64, 0x3, 0x6c, 0x1, 0x68, 0x0, 0x0, + 0xc, 0x0, 0x36, 0x33, 0x3b, 0x33, 0x5d, 0xb3, + 0x6f, 0xf7, 0x37, 0xf7, 0xdf, 0xf7, 0xef, 0xf7, + 0x7f, 0xf7, 0x3f, 0xe6, 0x1f, 0xee, 0x7, 0x88, + + /* U+E1B0 "" */ + 0x0, 0x80, 0x0, 0xe0, 0x0, 0xf8, 0x1, 0xff, + 0x1, 0xff, 0xc1, 0xff, 0xf1, 0xf8, 0xfc, 0xfc, + 0x7e, 0x7e, 0x3f, 0x1f, 0x1f, 0xf, 0xff, 0x87, + 0x83, 0xc3, 0x80, 0xe1, 0xc0, 0x70, 0xff, 0xf8, + 0x3f, 0xf8, + + /* U+E1BC "" */ + 0xff, 0xdf, 0x80, 0x70, 0xc, 0xff, 0xc0, 0xc0, + 0xe3, 0xf8, 0xf8, 0xe, 0x1, 0xe0, 0x3c, 0x3, + 0x80, 0x60, + + /* U+E1C4 "" */ + 0x30, 0x63, 0xe, 0x31, 0xc3, 0x78, 0x3e, 0x3, + 0xc0, 0xff, 0xff, 0xff, 0x3c, 0x3, 0xe0, 0x37, + 0x83, 0x1c, 0x30, 0xe3, 0x6, + + /* U+E1C8 "" */ + 0x9, 0x0, 0x90, 0xf, 0x3, 0xfc, 0x79, 0xe6, + 0x96, 0xc9, 0x3c, 0x93, 0xc0, 0xc, 0x0, 0x60, + 0x7, 0x0, 0xff, 0xff, 0xff, + + /* U+E1D3 "" */ + 0x30, 0x3, 0x0, 0x30, 0x3, 0x0, 0x31, 0x83, + 0xf8, 0x7c, 0xf, 0x0, 0x30, 0x3, 0x0, 0x30, + 0x3, 0x0, 0x3f, 0xf3, 0xff, + + /* U+E1D5 "" */ + 0x6, 0x0, 0x60, 0x1f, 0x3, 0xfc, 0x76, 0xee, + 0x66, 0xc6, 0x3c, 0x63, 0xc6, 0x3c, 0x63, 0xc6, + 0x3c, 0x63, 0xc6, 0x3c, 0x63, + + /* U+E1D7 "" */ + 0x0, 0xf0, 0x0, 0x3f, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xdc, 0x3, 0xbd, 0xc0, 0x3b, 0xdf, + 0xff, 0xbd, 0xe0, 0x7b, 0x7e, 0x7, 0x67, 0xff, + 0xfe, 0xf, 0xff, 0x0, 0x1f, 0x80, + + /* U+E1ED "" */ + 0x0, 0xc0, 0x8, 0x1, 0x8f, 0x9c, 0xff, 0xec, + 0x73, 0xc6, 0x3c, 0x63, 0xc6, 0x3c, 0x63, 0xce, + 0x3c, 0xe3, 0xde, 0x3d, 0xe3, 0x30, 0x3, 0x0, + 0x20, 0x0, + + /* U+E1F3 "" */ + 0xf, 0xff, 0x87, 0xff, 0xf1, 0x9f, 0xcc, 0x6e, + 0x3b, 0xdf, 0x7, 0xf7, 0xc1, 0xfd, 0xf0, 0x7f, + 0x6e, 0x3b, 0xd9, 0xfc, 0xf7, 0xff, 0xfc, 0xff, + 0xfb, 0x0, 0x0, 0xc0, 0x0, 0x1f, 0xff, 0xc0, + + /* U+E1F6 "" */ + 0x30, 0x30, 0xc0, 0xc3, 0x83, 0xf, 0xc, 0x3e, + 0x30, 0xd8, 0xc3, 0x73, 0x3f, 0xff, 0x31, 0xf0, + 0xc3, 0xc3, 0x7, 0xc, 0x1c, 0x30, 0x30, 0x0, + 0x0, + + /* U+E1FE "" */ + 0xff, 0xff, 0xff, 0xf0, 0xff, 0xf, 0xf9, 0xfd, + 0xfb, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xdf, + 0xbf, 0x9f, 0xf0, 0xff, 0xf, 0xff, 0xff, 0xff, + + /* U+E209 "" */ + 0xe0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0x7f, 0xcf, 0x8f, 0xff, 0xc3, 0xff, 0x0, 0x7f, + 0xc0, 0xf, 0xe0, 0x1, 0xf8, 0x0, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x1, 0xc0, + + /* U+E221 "" */ + 0x3f, 0x83, 0xfe, 0x1c, 0x38, 0xe0, 0xcf, 0xff, + 0xb8, 0x31, 0xc1, 0x8e, 0x1c, 0x7f, 0xc3, 0xf8, + 0x1c, 0x0, 0xe0, 0x7, 0x0, 0x10, 0x0, + + /* U+E222 "" */ + 0x3f, 0x83, 0xfe, 0x1c, 0x39, 0xff, 0xf7, 0x6, + 0x38, 0x33, 0xff, 0xee, 0x1c, 0x7f, 0xc3, 0xfc, + 0x1c, 0x0, 0xe0, 0x7, 0x0, 0x10, 0x0, + + /* U+E22D "" */ + 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, + 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, 0xf, 0xf0, + 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0xff, 0xff, + 0xf3, 0xcf, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, + 0xf, 0xf0, 0xc, 0x30, + + /* U+E23D "" */ + 0xfc, 0x0, 0xfe, 0x0, 0xc7, 0x0, 0xc3, 0x0, + 0xc3, 0x0, 0xc3, 0x0, 0xc7, 0x7c, 0xfe, 0x7e, + 0xfc, 0x63, 0xcc, 0x63, 0xcc, 0x63, 0xce, 0x7e, + 0xc6, 0x7c, 0xc6, 0x60, 0x0, 0x60, 0x0, 0x60, + + /* U+E289 "" */ + 0x0, 0xf, 0xc0, 0x3, 0xf0, 0x0, 0xc0, 0x0, + 0x30, 0x0, 0xfc, 0x0, 0x3f, 0x0, 0xc, 0x0, + 0x3, 0x0, 0xf, 0xc0, 0x3, 0xf0, 0x0, 0xc0, + 0x0, 0x30, 0x0, 0xfc, 0x0, 0x3f, 0x0, 0x0, + + /* U+E29C "" */ + 0x0, 0x0, 0xf, 0x3, 0xc3, 0xc0, 0xf0, 0xf0, + 0x3c, 0x3c, 0xf, 0x6, 0x1, 0x81, 0x80, 0x63, + 0xff, 0xff, 0xff, 0xff, 0xc0, 0x30, 0x0, 0xc, + 0x0, 0x7, 0x80, 0x1, 0xe0, 0x0, 0x78, 0x0, + 0x1e, 0x0, 0x0, 0x0, + + /* U+E2B7 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x1f, 0x80, 0x7e, 0x1, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x3c, 0xfc, 0xff, 0xff, 0x7f, 0xf9, 0xc0, + 0xe7, 0x3, 0x80, + + /* U+E2BB "" */ + 0x30, 0x6, 0x20, 0xfc, 0x3e, 0x7, 0x10, 0x7f, + 0x1f, 0x3, 0x80, 0x30, 0x66, 0xc, 0xc1, 0x98, + 0x63, 0xfc, 0x7e, 0x0, + + /* U+E2C5 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, + 0xe0, 0x63, 0xc6, 0x23, 0xcf, 0x23, 0xcf, 0x37, + 0xc6, 0x37, 0xe0, 0x77, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x30, 0xc, + + /* U+E2C7 "" */ + 0x60, 0x6, 0xff, 0xff, 0xff, 0xff, 0x60, 0xe, + 0x60, 0x1c, 0x60, 0x18, 0x60, 0x70, 0x60, 0xf0, + 0x60, 0xf0, 0x60, 0x70, 0x60, 0x18, 0x60, 0x1c, + 0x60, 0xe, 0xff, 0xff, 0xff, 0xff, 0x60, 0x6, + + /* U+E2CA "" */ + 0x0, 0x0, 0x0, 0x80, 0xc, 0xe3, 0xc6, 0x23, + 0xef, 0xc1, 0xf7, 0xe2, 0x70, 0xc3, 0x90, 0x63, + 0xc0, 0x3, 0xf0, 0x3, 0xf0, 0x3, 0xf0, 0x3, + 0xf8, 0xc1, 0xf8, 0x61, 0xf8, 0xfd, 0xf8, 0x7e, + 0xf8, 0xc, 0x38, 0x6, 0x8, 0x0, 0x0, + + /* U+E2CD "" */ + 0x0, 0xd, 0x80, 0x6d, 0x80, 0x3d, 0x80, 0x1f, + 0xb0, 0x6f, 0xb0, 0x3b, 0xf0, 0x1e, 0xfc, 0x6f, + 0x3e, 0x7b, 0xe6, 0x3c, 0xf8, 0xe, 0x3e, 0x7, + 0xee, 0x1, 0xf8, 0x1, 0xfe, 0x1, 0x9e, 0x1, + 0x80, 0x0, + + /* U+E2CE "" */ + 0x0, 0x10, 0x0, 0xe0, 0x63, 0x83, 0xe4, 0x19, + 0xc0, 0xf, 0x81, 0xfc, 0xf, 0xf0, 0x61, 0xfb, + 0x3, 0xfc, 0xd, 0xb0, 0x36, 0xc0, 0xd9, 0x86, + 0x67, 0xf9, 0x87, 0x80, + + /* U+E2E6 "" */ + 0xe0, 0xf, 0x0, 0x30, 0x3, 0x0, 0xfc, 0xe7, + 0x8f, 0x30, 0x33, 0x3, 0x30, 0x33, 0x3, 0x30, + 0x63, 0xe, 0x3f, 0xc1, 0xf0, + + /* U+E2EB "" */ + 0x7, 0xe0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, + 0x6d, 0xb6, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfc, + 0x1f, 0xf8, 0x1f, 0xf0, + + /* U+E307 "" */ + 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, + 0x0, 0x0, 0x0, 0x0, 0xf3, 0xcf, 0xf3, 0xcf, + 0xf3, 0xcf, 0xf3, 0xcf, + + /* U+E31E "" */ + 0xe, 0x3, 0x80, 0xe0, 0x0, 0x0, 0x7, 0x3, + 0xe0, 0xfc, 0x7f, 0xbf, 0xff, 0xfc, 0xff, 0x3f, + 0x8f, 0xc1, 0xb0, 0x6c, 0x1b, 0x6, 0xc0, + + /* U+E3AF "" */ + 0x1, 0x80, 0x1, 0xe0, 0x1, 0xfb, 0x81, 0xff, + 0xc1, 0xff, 0xe1, 0xff, 0xf1, 0xff, 0xfd, 0xff, + 0xfe, 0x7f, 0xff, 0x1f, 0xff, 0xf, 0x8f, 0x87, + 0xc7, 0xc3, 0xe3, 0xe1, 0xf1, 0xf0, 0xf8, 0xf8, + 0x3f, 0xf8, + + /* U+E3B1 "" */ + 0x1, 0x80, 0x1, 0xe0, 0x1, 0xfc, 0x1, 0xff, + 0x1, 0xff, 0xc1, 0xff, 0xf1, 0xff, 0xfd, 0xff, + 0xff, 0x7d, 0xff, 0x1f, 0x3f, 0xf, 0xcf, 0x87, + 0xe3, 0xc3, 0xe3, 0xe1, 0xe3, 0xf0, 0xf1, 0xf8, + 0x78, 0xf8, + + /* U+E3B2 "" */ + 0x0, 0x80, 0x0, 0xe0, 0x1, 0xfc, 0x1, 0xff, + 0x1, 0xff, 0xc1, 0xff, 0xf1, 0xff, 0xfd, 0xfe, + 0xff, 0x3f, 0x7e, 0x1e, 0xf, 0xf, 0x7, 0x87, + 0xef, 0xc3, 0xf7, 0xe1, 0xff, 0xf0, 0xff, 0xf8, + 0x3f, 0xf8, + + /* U+E3F5 "" */ + 0x6, 0x0, 0xc0, 0x3e, 0x1f, 0xe7, 0xe, 0xc0, + 0x30, 0x6, 0x0, 0xc0, 0x18, 0x1, 0x80, 0x38, + 0x73, 0xfc, 0x1f, 0x1, 0x80, 0x30, + + /* U+E43C "" */ + 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, 0xf, + 0xff, 0xff, 0xf0, 0x60, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + + /* U+E445 "" */ + 0x0, 0x0, 0x1, 0x80, 0x1, 0xc0, 0x1, 0xc0, + 0x5, 0xe0, 0xd, 0xf0, 0x1d, 0xf0, 0x1d, 0xf8, + 0x3d, 0xfc, 0x3d, 0xfc, 0x3d, 0xfc, 0x1, 0x80, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfc, + + /* U+E447 "" */ + 0x3e, 0x7e, 0xc0, 0xc0, 0xe0, 0x7c, 0xfe, 0xc7, + 0xe3, 0x7f, 0x3e, 0x7, 0x3, 0x3, 0x7e, 0x7c, + + /* U+E448 "" */ + 0x7f, 0xff, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xb8, + 0x3d, 0xbc, 0x3d, 0xbe, 0x1f, 0xbf, 0xf, 0xbc, + 0x7, 0xbb, 0x0, 0x7, 0x0, 0xf, 0x1, 0xc2, + 0x1, 0xdc, 0x1, 0xd8, + + /* U+E46C "" */ + 0x0, 0x8, 0xfc, 0x1c, 0xfe, 0x1e, 0xc7, 0x3e, + 0xc3, 0x60, 0xc3, 0x60, 0xc3, 0x60, 0xc7, 0x3c, + 0xfe, 0x1e, 0xfc, 0x3, 0xcc, 0x3, 0xcc, 0x3, + 0xce, 0x3e, 0xc6, 0x3c, 0xc6, 0x1c, 0x0, 0x8, + + /* U+E473 "" */ + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xcf, 0x3, 0xcf, + 0x3, 0xcf, 0x3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, + 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, + 0xf3, 0xcf, 0xf3, 0xcf, + + /* U+E476 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfd, 0xff, 0xe0, 0x30, 0x0, 0xc0, 0x67, 0x9b, + 0x9e, 0x7f, 0x33, 0xfe, 0x1f, 0xfc, 0xfd, 0xff, + 0xe0, + + /* U+E477 "" */ + 0x7f, 0xe3, 0xf8, 0xcf, 0xe3, 0x3f, 0xbf, 0xfe, + 0x78, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfb, + 0xff, 0xfc, 0x0, 0xf0, 0x3, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+E47A "" */ + 0x7f, 0xe3, 0xf8, 0xcc, 0x63, 0x31, 0xbf, 0xfe, + 0x79, 0xf0, 0xc0, 0x0, 0x0, 0x0, 0x7f, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+E47B "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7c, 0x7e, 0xfe, 0x7f, 0xff, 0xff, 0xfa, 0xff, + 0xf0, 0x7b, 0xe0, 0x3b, 0xe0, 0x3f, 0x7e, 0x36, + 0x7f, 0xee, 0x3e, 0x7c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+E490 "" */ + 0xc0, 0x0, 0x38, 0x78, 0x7, 0x3f, 0x0, 0xe7, + 0xc0, 0x1c, 0xf1, 0x83, 0x80, 0xe0, 0x7e, 0xf0, + 0xf, 0xf0, 0x9, 0xfc, 0x3f, 0x3f, 0xff, 0xe7, + 0xfc, 0x3c, 0xf0, 0xf, 0x1c, 0xf, 0xd3, 0x87, + 0x72, 0x71, 0x9c, 0xce, 0x1, 0x21, 0xc0, 0x0, + 0x30, + + /* U+E494 "" */ + 0x7f, 0x0, 0x7f, 0xc0, 0x3f, 0xb0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xff, + 0x0, 0xff, 0x3e, 0x7f, 0xbf, 0xbf, 0xbd, 0xff, + 0xde, 0xff, 0xec, 0x1f, 0xf7, 0xbf, 0xfb, 0xde, + 0xfe, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E4A5 "" */ + 0x1f, 0xfe, 0x3, 0xff, 0xf0, 0x3f, 0xff, 0x7, + 0xff, 0xf8, 0x7f, 0xff, 0x87, 0xff, 0xc0, 0x3f, + 0xf9, 0xc3, 0x6, 0x36, 0x30, 0x63, 0x63, 0x6, + 0x36, 0x30, 0x67, 0xf3, 0xfe, 0x7f, 0x3f, 0xe7, + 0xf3, 0xfe, 0x7f, 0x0, 0x7, 0xf0, 0x0, 0x7f, + + /* U+E4A8 "" */ + 0x3, 0xc0, 0x19, 0x98, 0x3b, 0xdc, 0x3f, 0xfc, + 0xf, 0xf0, 0x1f, 0xf8, 0xdf, 0xfb, 0xff, 0xff, + 0xff, 0xff, 0xdf, 0xfb, 0x1f, 0xf8, 0xf, 0xf0, + 0x3f, 0xfc, 0x3b, 0xdc, 0x19, 0x98, 0x3, 0xc0, + + /* U+E4A9 "" */ + 0xc0, 0x0, 0x38, 0x78, 0x7, 0xcc, 0xc0, 0xe7, + 0x98, 0x1f, 0xfe, 0x3, 0xfe, 0x0, 0x7f, 0xc1, + 0xaf, 0xf6, 0x7d, 0xff, 0x9f, 0x3f, 0xe6, 0xe7, + 0xd8, 0x3c, 0xf0, 0x7, 0x98, 0x7, 0xf3, 0x81, + 0x9e, 0x60, 0x33, 0xc, 0x1, 0xe1, 0x80, 0x0, + 0x30, + + /* U+E4AA "" */ + 0x3, 0xc0, 0x0, 0xfc, 0x0, 0x19, 0x80, 0x3, + 0x30, 0x0, 0x7e, 0x0, 0x7, 0x80, 0x0, 0x60, + 0x1, 0x8c, 0x0, 0x79, 0x8f, 0x9f, 0xb3, 0xf8, + 0xc6, 0xff, 0x98, 0xdf, 0x71, 0x9b, 0x5e, 0x3b, + 0x73, 0xc3, 0xef, 0xf8, 0x1c, 0xfe, 0x0, 0xf, + 0x80, + + /* U+E4AB "" */ + 0x3, 0xc0, 0x0, 0xfc, 0x0, 0x19, 0x80, 0x3, + 0x30, 0x0, 0x7e, 0x0, 0x7, 0x80, 0x0, 0x60, + 0x1, 0x8c, 0x0, 0x79, 0x8f, 0x9f, 0xb3, 0xb8, + 0xc6, 0xf7, 0x98, 0xde, 0xf1, 0x9b, 0xde, 0x3b, + 0x7f, 0xc3, 0xef, 0x78, 0x1c, 0xfe, 0x0, 0xf, + 0x80, + + /* U+E4AC "" */ + 0x3, 0xc0, 0x0, 0xfc, 0x0, 0x19, 0x80, 0x3, + 0x30, 0x0, 0x7e, 0x0, 0x7, 0x80, 0x0, 0x60, + 0x1, 0x8c, 0x0, 0x79, 0x8f, 0x9f, 0xb3, 0xf8, + 0xc6, 0xed, 0x98, 0xdc, 0x71, 0x9b, 0xce, 0x3b, + 0x71, 0xc3, 0xee, 0xd8, 0x3c, 0xfe, 0x0, 0xf, + 0x80, + + /* U+E4AD "" */ + 0x3, 0xc0, 0x0, 0xfc, 0x0, 0x19, 0x80, 0x3, + 0x30, 0x0, 0x7e, 0x0, 0x7, 0x80, 0x0, 0x60, + 0x1, 0x8c, 0x1c, 0x79, 0x86, 0xdf, 0xb0, 0xd8, + 0xc6, 0x1b, 0x18, 0xc7, 0xf1, 0x98, 0xfe, 0x3b, + 0x5f, 0xc3, 0xfb, 0xf8, 0x1f, 0x7f, 0x0, 0xf, + 0xe0, + + /* U+E4AF "" */ + 0x18, 0x18, 0x18, 0x3c, 0x18, 0x7e, 0x18, 0xff, + 0x18, 0x18, 0x0, 0x18, 0x0, 0x18, 0xff, 0xff, + 0xff, 0xff, 0x18, 0x0, 0x18, 0x0, 0x18, 0x18, + 0xff, 0x18, 0x7e, 0x18, 0x3c, 0x18, 0x18, 0x18, + + /* U+E4B0 "" */ + 0xc, 0x30, 0x3, 0x1e, 0x0, 0xcf, 0xc0, 0x33, + 0xf0, 0xc, 0x30, 0x0, 0xc, 0x0, 0x3, 0x1, + 0xff, 0x9c, 0x7f, 0xef, 0x83, 0x3, 0x60, 0xc0, + 0xd8, 0xb4, 0x7f, 0x7f, 0x9f, 0xcf, 0xc7, 0xf1, + 0xe1, 0xfc, 0x30, 0x7f, 0x0, 0x1f, 0xc0, + + /* U+E4B3 "" */ + 0x0, 0xfc, 0x0, 0x1f, 0x90, 0x3, 0xf6, 0x0, + 0x66, 0xc0, 0xc, 0xfe, 0x21, 0xff, 0xc7, 0x33, + 0xff, 0xf6, 0x73, 0xfe, 0xfe, 0x63, 0x99, 0xfc, + 0x43, 0x39, 0x80, 0x7f, 0x30, 0xf, 0xfe, 0x1, + 0xff, 0xc0, 0x3f, 0xf8, 0x7, 0xff, + + /* U+E4B5 "" */ + 0x0, 0x60, 0x0, 0xf, 0x0, 0x1, 0xf8, 0x0, + 0x36, 0xc0, 0x0, 0x60, 0x0, 0x6, 0x0, 0x3f, + 0x6f, 0xc3, 0xf6, 0xfc, 0x3f, 0x6f, 0xc3, 0xf6, + 0xfc, 0x3f, 0x6f, 0xc3, 0x86, 0xc, 0x0, 0x0, + 0x0, 0x60, 0xe0, 0xf, 0x9f, 0xf, 0x8f, 0x1f, + 0x0, 0x0, 0x0, + + /* U+E4B6 "" */ + 0x1f, 0xc3, 0x1, 0xfc, 0x78, 0x1f, 0xcf, 0xc1, + 0xfd, 0xb4, 0x1f, 0xc3, 0x1, 0xfc, 0x30, 0x1f, + 0xc3, 0x7, 0xff, 0xfe, 0x7f, 0xff, 0xe7, 0xff, + 0xfe, 0x70, 0x70, 0xe0, 0x0, 0x0, 0x7, 0xe, + 0x0, 0xf9, 0xf0, 0xf8, 0xf1, 0xf0, 0x0, 0x0, + + /* U+E4B7 "" */ + 0x3e, 0x6, 0x7c, 0xc, 0x78, 0x1, 0xf0, 0x7, + 0x66, 0x7c, 0xc, 0xf0, 0x0, 0x0, 0x0, 0x6, + 0x66, 0xc, 0xcc, 0x0, 0x0, 0x0, 0x6, 0x66, + 0x6c, 0xcc, 0xc0, + + /* U+E4B8 "" */ + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x7e, 0x7e, 0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x18, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + + /* U+E4B9 "" */ + 0x10, 0xc, 0x10, 0xc, 0x10, 0xc, 0xfc, 0x3f, + 0x78, 0x1e, 0x30, 0xc, 0x0, 0x0, 0x1, 0x80, + 0x23, 0xc4, 0x71, 0x8e, 0x70, 0xe, 0x0, 0x0, + 0x3, 0xc4, 0x77, 0xee, 0xf7, 0xef, 0xf7, 0xef, + 0xf7, 0xef, + + /* U+E4BA "" */ + 0xc0, 0x0, 0xf0, 0x0, 0x3c, 0x21, 0x8f, 0x18, + 0x73, 0xcf, 0xfe, 0xf3, 0xff, 0xbc, 0x61, 0xcf, + 0x8, 0x63, 0xc0, 0x0, 0xf0, 0x0, 0x30, + + /* U+E4BB "" */ + 0x7c, 0xf0, 0x1e, 0x7c, 0x8f, 0x7, 0xef, 0x81, + 0xf6, 0x40, 0xff, 0x0, 0x7f, 0x0, 0x1, 0x80, + 0x0, 0xc0, 0x1, 0x0, 0x1, 0xbe, 0x0, 0xdf, + 0x2, 0x6f, 0x3, 0xe7, 0xe1, 0xe3, 0x7e, 0xf8, + 0xf, 0x3c, + + /* U+E4BC "" */ + 0x0, 0x60, 0x1, 0xe0, 0x7, 0xe0, 0x1f, 0xe0, + 0x36, 0xc0, 0xc, 0x6, 0x18, 0x1c, 0x30, 0x70, + 0x61, 0xff, 0xc3, 0xff, 0x83, 0x87, 0x3, 0x86, + 0x3, 0xc, 0x0, 0x1c, 0x0, 0x1f, 0x0, 0x1e, + + /* U+E4BD "" */ + 0xc0, 0x3, 0xec, 0x37, 0x7c, 0x3e, 0x3c, 0x3c, + 0x7c, 0x3e, 0x7c, 0x3e, 0x1, 0x80, 0x3, 0xc0, + 0x3, 0xc0, 0x1, 0x80, 0x7c, 0x3e, 0x7c, 0x3e, + 0x3c, 0x3c, 0x7c, 0x3e, 0xec, 0x37, 0xc0, 0x3, + + /* U+E4BE "" */ + 0x1, 0x80, 0x1, 0x80, 0x7, 0xe0, 0x7, 0xe0, + 0x3, 0xc0, 0x31, 0x8c, 0x38, 0x1c, 0xfd, 0xbf, + 0xfd, 0xbf, 0x38, 0x1c, 0x31, 0x8c, 0x3, 0xc0, + 0x7, 0xe0, 0x7, 0xe0, 0x1, 0x80, 0x1, 0x80, + + /* U+E4BF "" */ + 0x98, 0x6, 0x76, 0x1, 0xb7, 0x80, 0x7b, 0xe7, + 0x9f, 0x73, 0xf3, 0x81, 0xce, 0x0, 0xe1, 0xc0, + 0x38, 0x70, 0x7, 0x38, 0x3e, 0xfc, 0xff, 0x9e, + 0x7d, 0xe0, 0x1e, 0xd8, 0x6, 0xe6, 0x1, 0x90, + + /* U+E4C0 "" */ + 0x0, 0x20, 0x1, 0xc0, 0x3, 0x8f, 0xff, 0x7f, + 0xff, 0x80, 0xec, 0x7, 0x30, 0x8, 0xc1, 0x0, + 0xe, 0x0, 0x1c, 0x1f, 0xf8, 0xff, 0xe3, 0x7, + 0xc, 0x38, 0x30, 0x40, + + /* U+E4C1 "" */ + 0x0, 0x0, 0x3, 0x6, 0x18, 0x3c, 0xfe, 0xf3, + 0xfd, 0x8e, 0x30, 0x1c, 0xc0, 0x3, 0x0, 0x0, + 0x20, 0x0, 0xe0, 0x1, 0xc6, 0x7f, 0x3f, 0xfc, + 0xfc, 0x61, 0xb3, 0x0, 0xc0, 0x0, + + /* U+E4C2 "" */ + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x30, + 0x31, 0xe1, 0xef, 0xcf, 0xff, 0x3f, 0x30, 0x30, + 0xc0, 0xc3, 0x3, 0xc, 0xc, 0x30, 0x30, 0xc0, + 0xc3, 0x3, 0xc, 0xc, + + /* U+E4C3 "" */ + 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, + 0x21, 0x84, 0xf9, 0x9f, 0xf9, 0x9f, 0xf9, 0x9f, + 0xf9, 0x9f, 0xfb, 0xdf, 0xfb, 0xdf, 0xf9, 0x9f, + 0xfc, 0x3f, 0xfc, 0x7f, 0xff, 0xff, 0x7f, 0xfe, + + /* U+E4C4 "" */ + 0x1e, 0x7, 0x81, 0xe0, 0x78, 0x1e, 0x7, 0x87, + 0xf9, 0xfe, 0xff, 0xfc, 0xff, 0x3f, 0x87, 0xe1, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xe0, + + /* U+E4C5 "" */ + 0x3e, 0x1f, 0x0, 0x0, 0x7, 0xf7, 0xff, 0xfe, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, + 0xfd, 0xff, 0xff, 0xbf, 0x80, + + /* U+E4C6 "" */ + 0x1, 0x80, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfc, + 0x1f, 0xf8, 0x1f, 0xf0, + + /* U+E4C7 "" */ + 0x3, 0x8e, 0x7, 0x8f, 0xf, 0x8f, 0xf, 0xff, + 0xf, 0xff, 0x0, 0x1f, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0x0, 0xf, 0x0, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xdf, + + /* U+E4C8 "" */ + 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, 0x66, 0x66, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7c, 0x3e, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, + 0x38, 0x1c, 0x38, 0x1c, + + /* U+E4C9 "" */ + 0xff, 0xff, 0x3f, 0xff, 0xc6, 0x66, 0x61, 0x99, + 0x98, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xfc, 0x3, + 0xfe, 0x7c, 0x7c, 0x3f, 0x8e, 0x1f, 0xf3, 0x87, + 0xdc, 0xe1, 0xaf, 0x38, 0x73, 0xce, 0x1f, 0xf0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E4CA "" */ + 0xff, 0xff, 0x3f, 0xff, 0xc6, 0x66, 0x61, 0x99, + 0x98, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xfc, 0x3, + 0xfe, 0x7c, 0x3c, 0x3b, 0x8e, 0x1e, 0xf3, 0x87, + 0xbc, 0xe1, 0xef, 0x38, 0x7f, 0xce, 0x1e, 0xf0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E4CB "" */ + 0xff, 0xff, 0x3f, 0xff, 0xc6, 0x66, 0x61, 0x99, + 0x98, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xfc, 0x3, + 0xfe, 0x7c, 0x7c, 0x3f, 0x8e, 0x1d, 0x73, 0x87, + 0x5c, 0xe1, 0xef, 0x38, 0x75, 0xce, 0x1d, 0x70, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E4CC "" */ + 0xff, 0xff, 0x3f, 0xff, 0xc6, 0x66, 0x61, 0x99, + 0xbc, 0xff, 0xff, 0x3f, 0xfc, 0xf, 0xfe, 0x73, + 0xff, 0xbe, 0x7c, 0x2d, 0x8e, 0x3, 0x63, 0x81, + 0xfc, 0xe0, 0x7f, 0x38, 0x1f, 0xce, 0x7, 0xf0, + 0x1, 0xfc, 0x0, 0x7f, + + /* U+E4CE "" */ + 0x3f, 0xff, 0xc3, 0xff, 0xfc, 0x3f, 0xff, 0xc3, + 0xff, 0xfc, 0x1f, 0xf, 0x80, 0xe0, 0x70, 0xe, + 0x7, 0x0, 0xe0, 0x70, 0x8, 0x0, 0x0, 0x0, + 0x0, 0x6, 0x6, 0x0, 0xf9, 0xf0, 0x78, 0xf1, + 0xf0, 0x0, 0x0, + + /* U+E4CF "" */ + 0x7, 0x80, 0x21, 0x1, 0x6, 0x4, 0x8, 0x30, + 0x30, 0x0, 0x0, 0x0, 0x3f, 0xff, 0x7f, 0xf9, + 0xff, 0xe7, 0xff, 0x8f, 0xfe, 0x3f, 0xf0, 0xff, + 0xc3, 0xff, 0xf, 0xfc, + + /* U+E4D0 "" */ + 0x36, 0x0, 0xe, 0x0, 0x7, 0x0, 0x7, 0xc0, + 0xf, 0xf8, 0x7, 0xfc, 0x1, 0xfc, 0x91, 0xff, + 0x78, 0x3e, 0x3c, 0x1f, 0x3f, 0x7, 0x3f, 0xc0, + 0x1f, 0xe0, 0x7, 0xe0, 0x7, 0xf8, 0x1, 0xf8, + 0x0, 0xfc, 0x0, 0x3c, 0x0, + + /* U+E4D1 "" */ + 0x7f, 0xe0, 0x7f, 0xf8, 0x3f, 0xfc, 0x1c, 0xce, + 0xe, 0x67, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xcc, + 0x0, 0xe6, 0x3e, 0x7f, 0x3f, 0xbf, 0xbd, 0xff, + 0x1f, 0x7f, 0x8c, 0x1f, 0xc7, 0xdf, 0xe3, 0xde, + 0xfc, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E4D2 "" */ + 0x7f, 0xe0, 0x7f, 0xf8, 0x3f, 0xfc, 0x1c, 0xce, + 0xe, 0x67, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xcc, + 0x0, 0xe6, 0x3c, 0x7f, 0xbf, 0xbf, 0xbf, 0xdf, + 0x1f, 0x7f, 0x8d, 0x3f, 0xc7, 0x3f, 0xe3, 0xbc, + 0xfc, 0xfe, 0x0, 0x3c, 0x0, + + /* U+E4D3 "" */ + 0x7f, 0xe0, 0x7f, 0xf8, 0x3f, 0xfc, 0x1c, 0xce, + 0xe, 0x67, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xcc, + 0x0, 0xe6, 0x3e, 0x7f, 0x3b, 0xbf, 0xbd, 0xff, + 0x1e, 0xff, 0x8f, 0x7f, 0xc7, 0xff, 0xfb, 0xde, + 0xfc, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E4D4 "" */ + 0x7f, 0xe0, 0x7f, 0xf8, 0x3f, 0xfc, 0x1c, 0xce, + 0xe, 0x67, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xcc, + 0x0, 0xe6, 0x3e, 0x7f, 0x3f, 0xbf, 0xb7, 0x7f, + 0x1d, 0x7f, 0x8e, 0x3f, 0xc7, 0x1f, 0xe3, 0x76, + 0xfc, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E4D5 "" */ + 0x7f, 0xe6, 0xf, 0xff, 0x7e, 0xff, 0xf7, 0xfe, + 0x67, 0x7f, 0xe6, 0x77, 0xff, 0xff, 0x7e, 0xff, + 0xf6, 0xe, 0x67, 0x60, 0xe6, 0x76, 0xf, 0xff, + 0x60, 0xff, 0xf6, 0xf, 0x9f, 0x60, 0xf9, 0xf6, + 0xf, 0x9f, 0x60, 0xf9, 0xf6, 0x7, 0xfe, 0x60, + + /* U+E4D6 "" */ + 0x7f, 0xe0, 0x7f, 0xf8, 0x3f, 0xfc, 0x1c, 0xce, + 0xe, 0x67, 0x7, 0xff, 0x83, 0xff, 0x81, 0xcd, + 0x9c, 0xe6, 0xdb, 0x7f, 0xe9, 0xbf, 0xe4, 0xdf, + 0x37, 0xff, 0x9b, 0xff, 0xcd, 0xff, 0xfe, 0xfe, + 0xff, 0x7f, 0x0, 0x3f, 0x80, + + /* U+E4D7 "" */ + 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0xf0, 0xe6, 0x70, + 0xe6, 0x70, 0xff, 0xf0, 0xff, 0xf0, 0xe6, 0x70, + 0xe6, 0x70, 0xff, 0xf0, 0xf0, 0x0, 0xf0, 0x0, + 0xf5, 0x77, 0xf7, 0x45, 0xf7, 0x55, 0x37, 0x55, + 0x5, 0x77, + + /* U+E4D8 "" */ + 0x7f, 0xf0, 0x7f, 0xf8, 0x3f, 0xfc, 0x1c, 0xce, + 0xe, 0x67, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xcc, + 0x0, 0xe6, 0x1c, 0x7f, 0x7f, 0xff, 0xbe, 0x7f, + 0x1f, 0x3f, 0x8f, 0x9f, 0xc7, 0xcf, 0xf9, 0xec, + 0xfe, 0x7c, 0x0, 0x1c, 0x0, + + /* U+E4D9 "" */ + 0x7f, 0xe1, 0xff, 0xe3, 0xff, 0xc7, 0x33, 0x8e, + 0x67, 0x1f, 0xfe, 0x3f, 0xfc, 0x73, 0x38, 0xe6, + 0x71, 0xff, 0xe3, 0xf8, 0x7, 0xc0, 0xf, 0x8a, + 0xbf, 0x15, 0xfe, 0x2b, 0xbf, 0x57, 0x0, 0xea, + + /* U+E4DA "" */ + 0x7f, 0xe0, 0x3f, 0xfc, 0xf, 0xff, 0x3, 0x99, + 0xc0, 0xe6, 0x70, 0x3f, 0xfc, 0xf, 0xfe, 0x3, + 0x9b, 0x38, 0xe6, 0xdf, 0x3f, 0xf7, 0xcf, 0xfd, + 0xf3, 0xe7, 0x38, 0xf9, 0x80, 0x3e, 0xcf, 0xef, + 0xf7, 0xfd, 0xfd, 0xff, 0x0, 0x7f, 0xc0, + + /* U+E4DB "" */ + 0x7f, 0xe0, 0x1f, 0xfe, 0x3, 0xff, 0x8c, 0x73, + 0x35, 0xae, 0x66, 0xb5, 0xff, 0xd6, 0xbf, 0xf0, + 0xc7, 0x32, 0xc3, 0xe6, 0x5c, 0xff, 0xf9, 0x9b, + 0xff, 0x0, 0xfc, 0xee, 0x7f, 0x9c, 0xcf, 0xf3, + 0x89, 0x3f, 0xf6, 0x1b, 0xfe, 0xe7, 0x0, 0xc, + 0xc0, + + /* U+E4DC "" */ + 0xc1, 0x80, 0xe1, 0x80, 0x79, 0x80, 0x3f, 0xd8, + 0x3f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, + 0x3f, 0xfc, 0x31, 0x8c, 0x1, 0x80, 0x1, 0x80, + + /* U+E4DD "" */ + 0x3, 0x3, 0xc, 0x3e, 0x31, 0xd8, 0x6, 0x0, + 0x0, 0x0, 0x1, 0xfe, 0xf, 0xfc, 0x30, 0x31, + 0x80, 0x67, 0xff, 0xbf, 0xff, 0xcf, 0xcf, 0xff, + 0xff, 0xff, 0xf8, 0x7, 0xc0, 0xc, + + /* U+E4DE "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, + 0xf0, 0xf, 0xf7, 0xcf, 0xe7, 0xc7, 0xe0, 0x7, + 0xec, 0x67, 0xe0, 0x7, 0xe0, 0x7, 0x6f, 0xe6, + + /* U+E4E0 "" */ + 0xe, 0xc, 0x7, 0x2, 0x3, 0x81, 0x1, 0xc0, + 0x80, 0x0, 0xe0, 0xf8, 0x70, 0xfe, 0x7e, 0xff, + 0xbf, 0x7f, 0xdf, 0xbf, 0xef, 0x87, 0xc7, 0x83, + 0xe3, 0xf1, 0xb0, 0x60, 0xd8, 0x30, 0x6c, 0x1c, + 0x36, 0xe, + + /* U+E4E1 "" */ + 0xe, 0x3, 0x81, 0xe0, 0x78, 0x1e, 0x7, 0x80, + 0xe0, 0x38, 0x0, 0x0, 0x1, 0xe0, 0x78, 0x3f, + 0xf, 0xc7, 0xf8, 0xfe, 0x7f, 0xdf, 0xed, 0xfd, + 0xff, 0x3f, 0x7, 0xc3, 0xf8, 0x7c, 0x1e, 0x7, + 0xc1, 0xe0, 0x7c, 0x1e, 0x7, 0xc0, 0x20, 0x8, + + /* U+E4E2 "" */ + 0x0, 0x1c, 0x0, 0x7c, 0x0, 0xf8, 0xf, 0xf7, + 0x7d, 0xdf, 0xe3, 0x3e, 0x6, 0x7c, 0xc, 0x7c, + 0x30, 0x1c, 0x60, 0xe, 0xc0, 0xf, 0x80, 0xf, + 0x80, 0x1f, 0x0, 0x3e, 0x0, 0x38, + + /* U+E4E3 "" */ + 0x1f, 0x87, 0xfe, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf9, 0xff, 0x2f, 0xf6, 0xff, 0x4f, 0xfd, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, + + /* U+E4E4 "" */ + 0xf, 0x0, 0x1f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, + 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0x26, 0x44, 0x66, 0xcc, 0x44, 0xc8, + 0x0, 0x0, 0x8, 0x10, 0x3e, 0x7c, 0xe3, 0xc7, + + /* U+E4E5 "" */ + 0x7f, 0xef, 0xff, 0xfb, 0xfc, 0x0, 0xcf, 0x0, + 0x33, 0xc0, 0xf, 0xf0, 0x3, 0x3c, 0x0, 0xff, + 0x0, 0x3f, 0xc0, 0xf, 0xff, 0xfb, 0xf7, 0xfe, + 0xfc, 0x0, 0x3f, 0x0, 0xf, 0xc7, 0xfb, 0xf0, + + /* U+E4E6 "" */ + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0xc, 0x30, 0x1e, 0x78, + 0x1e, 0x78, 0x1e, 0x78, 0xc, 0x0, 0x0, 0x0, + 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, + + /* U+E4E8 "" */ + 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xff, 0xf0, 0xff, + 0x80, 0x9f, 0xc0, 0x33, 0xe7, 0xce, 0x33, 0xfb, + 0xe5, 0xff, 0xfc, 0x7d, 0xff, 0xda, 0xff, 0xf7, + 0x3c, 0xfd, 0xff, 0x0, 0x3f, 0x80, 0x7, 0xc0, + + /* U+E4E9 "" */ + 0x1, 0x80, 0x1, 0x83, 0x1, 0x83, 0x0, 0x6, + 0x0, 0x6, 0x1, 0x8c, 0x1, 0x9c, 0x31, 0x98, + 0x19, 0xb8, 0x1d, 0xf8, 0xf, 0xf3, 0xef, 0xff, + 0x7c, 0x3e, 0x38, 0x1c, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, + + /* U+E4EA "" */ + 0x1, 0xf8, 0x0, 0x1f, 0x80, 0xf, 0xff, 0x1, + 0xff, 0xf8, 0x18, 0x1, 0x81, 0x80, 0x18, 0x18, + 0x1, 0x81, 0x80, 0x18, 0x1f, 0xff, 0x81, 0xff, + 0xf8, 0xf, 0xff, 0x0, 0xf, 0x0, 0x0, 0x0, + 0x0, 0xf0, 0xf0, 0x1f, 0x9f, 0xa7, 0x8f, 0x1f, + 0x0, 0x0, 0x0, + + /* U+E4EB "" */ + 0x7f, 0x0, 0x7f, 0xc0, 0x3f, 0xb0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xff, + 0x0, 0xff, 0x3e, 0x7f, 0xbb, 0xbf, 0xbd, 0xff, + 0xde, 0xff, 0xef, 0x7f, 0xf7, 0xff, 0xfb, 0xde, + 0xfe, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E4ED "" */ + 0x7f, 0x0, 0x7f, 0xc0, 0x3f, 0xb0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xff, 0xc3, 0xff, 0xe1, 0xff, + 0x80, 0xff, 0xbe, 0x7f, 0xbf, 0xbf, 0xbf, 0xff, + 0xdf, 0xff, 0xec, 0x1f, 0xf7, 0xff, 0xfb, 0xfe, + 0xfe, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E4EE "" */ + 0x7f, 0x0, 0x7f, 0xc0, 0x3f, 0xb0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xff, + 0x0, 0xff, 0x3e, 0x7f, 0xbf, 0xbf, 0xbd, 0xff, + 0xde, 0xff, 0xec, 0x1f, 0xf7, 0xbf, 0xfb, 0xde, + 0xfe, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E4EF "" */ + 0x7f, 0x0, 0x7f, 0xc0, 0x3f, 0xb0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xff, 0x83, 0xff, 0xc1, 0xff, + 0x80, 0xff, 0x3e, 0x7f, 0xbf, 0xbf, 0xba, 0xff, + 0xdf, 0x7f, 0xef, 0x7f, 0xf7, 0xff, 0xfb, 0xde, + 0xfe, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E4F0 "" */ + 0x7f, 0x0, 0x7f, 0xc0, 0x3f, 0xb0, 0x1f, 0xcc, + 0xf, 0xe3, 0x7, 0xff, 0xc3, 0xff, 0xe1, 0xff, + 0x80, 0xff, 0x1c, 0x7f, 0x7f, 0xff, 0xbe, 0x7f, + 0xdf, 0x3f, 0xef, 0x9f, 0xf7, 0xcf, 0xfd, 0xec, + 0xfe, 0x7c, 0x0, 0x1c, 0x0, + + /* U+E4F1 "" */ + 0x3, 0x0, 0x7, 0xe0, 0xf, 0xf0, 0xf, 0xf0, + 0x1f, 0xf8, 0x1e, 0x78, 0x1c, 0x38, 0x1c, 0x38, + 0xc, 0x38, 0xf, 0xf0, 0xe3, 0xe7, 0xf8, 0x1f, + 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, + + /* U+E4F2 "" */ + 0x1, 0x80, 0x0, 0x70, 0x0, 0x1f, 0x83, 0xf, + 0xf8, 0xf7, 0xff, 0x1f, 0xff, 0xe7, 0xff, 0x3d, + 0xff, 0xcf, 0x7f, 0xff, 0xbd, 0xff, 0xcc, 0x3f, + 0xe0, 0x7, 0xe0, 0x1, 0xc0, 0x0, 0x60, 0x0, + + /* U+E4F3 "" */ + 0xff, 0x7f, 0x9f, 0xef, 0xf1, 0x98, 0xcc, 0x33, + 0x19, 0x86, 0x63, 0x30, 0xcc, 0x66, 0x1f, 0x8c, + 0xc3, 0xf1, 0x98, 0x7e, 0x61, 0x8f, 0xcc, 0x31, + 0xfb, 0xff, 0x3e, 0x7f, 0xe7, 0xcf, 0xfc, 0x7b, + 0xff, 0xc0, 0x7f, 0xf8, 0x7, 0xfe, + + /* U+E4F4 "" */ + 0xff, 0xff, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x3f, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe7, 0xfe, 0x7f, + 0xe7, 0xfe, 0x7f, 0xe7, 0xfe, 0x7f, 0xe3, 0xfc, + + /* U+E4F5 "" */ + 0xff, 0xff, 0xff, 0xc0, 0x3c, 0x63, 0xc6, 0x3c, + 0xf3, 0xcf, 0x3c, 0x63, 0x60, 0x66, 0x6, 0x7f, + 0xe7, 0xfe, 0x7f, 0xe7, 0xfe, 0x7f, 0xe3, 0xfc, + + /* U+E4F6 "" */ + 0x66, 0x66, 0xfe, 0x7f, 0xfc, 0x3f, 0x70, 0xe, + 0x60, 0x6, 0xe3, 0xe7, 0xc6, 0x63, 0x4, 0x60, + 0x6, 0x0, 0xc6, 0x63, 0xe7, 0xe7, 0x60, 0x6, + 0x70, 0xe, 0xfc, 0x3f, 0xfe, 0x7f, 0x66, 0x66, + + /* U+E4F7 "" */ + 0x7, 0xff, 0xc3, 0xff, 0xf3, 0xff, 0xfd, 0xe0, + 0xff, 0xf3, 0xfe, 0x30, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xf0, 0x7, 0xfc, 0x31, 0xf0, + 0x3f, 0xfc, 0x1e, 0xff, 0xff, 0x3f, 0xff, 0xf, + 0xff, 0x80, + + /* U+E4F8 "" */ + 0x0, 0xc0, 0x0, 0x30, 0x0, 0x61, 0x80, 0x18, + 0x60, 0x0, 0x0, 0x3, 0xcf, 0x0, 0xf1, 0xc0, + 0xff, 0x3c, 0x70, 0xe3, 0x98, 0x18, 0x6c, 0x3, + 0xf, 0x0, 0xc3, 0xc0, 0x30, 0xf0, 0xc, 0x36, + 0x6, 0x19, 0xc3, 0x8e, 0x3f, 0xcf, 0x3, 0xc7, + 0x0, + + /* U+E4F9 "" */ + 0xc0, 0x0, 0xf0, 0x0, 0x3c, 0x0, 0xf, 0x0, + 0x3, 0xcc, 0xc, 0xfb, 0x87, 0x7e, 0x73, 0x9f, + 0xdc, 0xef, 0x7f, 0x3f, 0x8f, 0xcf, 0xc1, 0xf3, + 0xe0, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xff, 0xf0, 0x3c, 0xf0, + + /* U+E4FA "" */ + 0x0, 0x70, 0x0, 0x7, 0x0, 0x0, 0x20, 0xe, + 0x7, 0x7, 0xe1, 0xfc, 0x7e, 0x1f, 0xc7, 0xe0, + 0x70, 0x7e, 0x5, 0x7, 0xe4, 0x53, 0x7e, 0x60, + 0x77, 0xe7, 0x6, 0x7f, 0x38, 0xcf, 0xfb, 0x8d, + 0xf7, 0xf8, 0xfe, 0x3f, 0x8f, 0xc1, 0xf8, 0xf8, + 0xf, 0x8f, 0x0, + + /* U+E4FB "" */ + 0x0, 0xf0, 0x0, 0x1f, 0x80, 0xe3, 0xfc, 0x7e, + 0x3f, 0xc7, 0xe3, 0xfc, 0x7e, 0x3f, 0xc7, 0xe1, + 0xf8, 0x7e, 0xcf, 0x37, 0xee, 0x7, 0x7e, 0x70, + 0xe7, 0xf3, 0x9c, 0xff, 0xb9, 0xdf, 0x7f, 0x9f, + 0xe3, 0xf9, 0xfc, 0x1f, 0x9f, 0x80, 0xf9, 0xf0, + + /* U+E4FC "" */ + 0x3c, 0x3c, 0x1f, 0x9f, 0x8f, 0xff, 0xf3, 0xff, + 0xfc, 0xff, 0xff, 0x3f, 0xf8, 0x7, 0xfc, 0x1, + 0xfe, 0x7c, 0x3f, 0x3f, 0x8f, 0xdf, 0x71, 0xf7, + 0x3c, 0x3d, 0x83, 0x7, 0x79, 0xc0, 0x5c, 0xf0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E4FD "" */ + 0x3c, 0x3c, 0x1f, 0x9f, 0x8f, 0xff, 0xf3, 0xff, + 0xfc, 0xff, 0xff, 0x3f, 0xf8, 0x7, 0xfc, 0x1, + 0xfe, 0x7c, 0x3f, 0x3f, 0x87, 0xdf, 0xf1, 0xf7, + 0xdc, 0x3d, 0xaf, 0x3, 0x73, 0xc0, 0x5f, 0xf0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E4FE "" */ + 0x3c, 0x3c, 0x1f, 0x9f, 0x8f, 0xff, 0xf3, 0xff, + 0xfc, 0xff, 0xff, 0x3f, 0xf8, 0x7, 0xfc, 0x1, + 0xfe, 0x7c, 0x3f, 0x3b, 0x8f, 0xde, 0xf1, 0xf7, + 0xbc, 0x3d, 0xef, 0x7, 0x7f, 0xc0, 0x5e, 0xf0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E4FF "" */ + 0x3c, 0x3c, 0x1f, 0x9f, 0x8f, 0xff, 0xf3, 0xff, + 0xfc, 0xff, 0xff, 0x3f, 0xf8, 0xf, 0xfc, 0x1, + 0xfe, 0x7c, 0x3f, 0x3f, 0x8f, 0xdf, 0xf1, 0xf7, + 0xfc, 0x3d, 0x83, 0x7, 0x7f, 0xc0, 0x5f, 0xf0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E500 "" */ + 0x3c, 0x3c, 0x1f, 0x9f, 0x8f, 0xff, 0xf3, 0xff, + 0xfc, 0xff, 0xff, 0x3f, 0xf8, 0xf, 0xfc, 0x1, + 0xfe, 0x7c, 0x3f, 0x3f, 0x8f, 0xde, 0xf1, 0xf7, + 0xbc, 0x3d, 0x83, 0x7, 0x7b, 0xc0, 0x5e, 0xf0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E501 "" */ + 0x3c, 0x3c, 0x1f, 0x9f, 0x8f, 0xff, 0xf3, 0xff, + 0xfc, 0xff, 0xff, 0x3f, 0xf8, 0xf, 0xfc, 0x1, + 0xfe, 0x7c, 0x7f, 0x3f, 0x8f, 0xdd, 0x71, 0xf7, + 0x5c, 0x3d, 0xef, 0x7, 0x75, 0xc0, 0xdd, 0x70, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E502 "" */ + 0x6, 0xc0, 0x3d, 0xe0, 0xe0, 0xe3, 0x80, 0xee, + 0xc6, 0xf9, 0x8c, 0xf3, 0x19, 0x87, 0xf0, 0xf, + 0xe1, 0x98, 0xcf, 0x31, 0x9f, 0x63, 0x77, 0x1, + 0xc7, 0x7, 0x7, 0xbc, 0x3, 0x60, + + /* U+E503 "" */ + 0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xfc, 0x75, 0x5c, + 0x75, 0x1e, 0xf5, 0x1e, 0xf1, 0x5e, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x30, 0xff, 0x30, 0x7f, 0x30, + 0x1, 0xb0, 0x0, 0xf0, 0x0, 0x30, 0x0, 0x1e, + + /* U+E507 "" */ + 0xe, 0xc6, 0x13, 0xf9, 0x8e, 0x7f, 0x3, 0xcf, + 0xcc, 0xf9, 0xfb, 0x3f, 0x3e, 0xf, 0xe7, 0x83, + 0xfc, 0xce, 0xff, 0x98, 0xff, 0xf3, 0x3f, 0xfe, + 0x7f, 0xff, 0xce, 0xff, 0xf8, 0x3f, 0xff, 0x7, + 0xff, 0x80, + + /* U+E508 "" */ + 0xc, 0x60, 0x13, 0x3c, 0xe, 0xf, 0x3, 0xc1, + 0x80, 0xf8, 0x0, 0x3f, 0x0, 0xf, 0xe0, 0x3, + 0xfc, 0x60, 0xff, 0x81, 0xbf, 0xf0, 0xff, 0xfe, + 0x3f, 0xff, 0xc6, 0xff, 0xf8, 0x3f, 0xff, 0x7, + 0xff, 0x80, + + /* U+E509 "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0xff, 0x80, 0x1f, 0xfc, 0x3, 0xff, 0xe0, 0x7f, + 0xff, 0xf, 0xff, 0x0, 0x7f, 0xe7, 0x83, 0xfc, + 0xfe, 0x3e, 0x1f, 0xe3, 0xe1, 0xf7, 0x3e, 0x1a, + 0x73, 0xe1, 0xcf, 0x3e, 0x1d, 0xe1, 0xfc, 0xfe, + 0x0, 0x7, 0x80, + + /* U+E50A "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0xff, 0x80, 0x1f, 0xfc, 0x3, 0xff, 0xe0, 0x7f, + 0xff, 0xf, 0xff, 0x0, 0x7f, 0xe7, 0xc3, 0xfc, + 0xfe, 0x3e, 0x1e, 0xf3, 0xe1, 0xef, 0x3e, 0x1e, + 0xf3, 0xe1, 0xff, 0x3f, 0xde, 0xf1, 0xfc, 0xfe, + 0x0, 0x7, 0xc0, + + /* U+E50B "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0xff, 0x80, 0x1f, 0xfc, 0x3, 0xff, 0xe0, 0x7f, + 0xff, 0x8f, 0xff, 0x0, 0x3f, 0xe7, 0xc3, 0xfc, + 0xfe, 0x3e, 0x1b, 0xb3, 0xe1, 0xd7, 0x3e, 0x1e, + 0xf3, 0xe1, 0xd7, 0x3e, 0x1b, 0xb1, 0xfc, 0xfe, + 0x0, 0x7, 0xc0, + + /* U+E50C "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0x7f, 0x80, 0xf, 0xfc, 0x3, 0xff, 0x0, 0x7f, + 0xe0, 0x7, 0xfc, 0x68, 0x7f, 0xcf, 0xc3, 0xf9, + 0xfe, 0x3e, 0x3f, 0xf3, 0xe3, 0xcf, 0x3e, 0x38, + 0x73, 0xe3, 0x87, 0x3e, 0x18, 0x63, 0xf9, 0xce, + 0x0, 0x7, 0x80, + + /* U+E50D "" */ + 0x0, 0x3, 0x0, 0x0, 0x3f, 0x3, 0xc3, 0xf0, + 0x7e, 0x3f, 0xf, 0xf3, 0xf1, 0xff, 0x3f, 0x3f, + 0xf3, 0x7, 0xff, 0x30, 0x7e, 0x73, 0x7, 0xe7, + 0x30, 0x3e, 0x73, 0x3, 0xff, 0x30, 0x3f, 0xf3, + 0x3, 0xff, 0x30, 0x3f, 0xf3, 0x1, 0xff, 0x30, + + /* U+E50E "" */ + 0x0, 0xe0, 0x0, 0x1f, 0x0, 0x3, 0xf8, 0x0, + 0x7f, 0xc0, 0xf, 0xfe, 0x1, 0xf1, 0xf0, 0xf, + 0x1e, 0x0, 0xf1, 0xe0, 0xf, 0x1e, 0x0, 0xff, + 0xe0, 0x0, 0x60, 0x0, 0x0, 0x0, 0xf, 0x9f, + 0xf, 0x8f, 0x1f, 0x7, 0xe, 0x0, 0xf9, 0xf0, + 0xf8, 0xf1, 0xf0, 0x0, 0x0, + + /* U+E50F "" */ + 0x3e, 0x0, 0x7, 0xf1, 0xc0, 0xf7, 0xbe, 0xf, + 0xbb, 0xf0, 0xc1, 0xbf, 0x8f, 0xbb, 0xfe, 0x7f, + 0x33, 0xe3, 0xe7, 0x3c, 0x8, 0xf3, 0xc0, 0x1f, + 0xfc, 0x0, 0xf1, 0xc0, 0x4, 0x4, 0x6, 0x6, + 0x0, 0xf9, 0xf0, 0xf8, 0xf1, 0xf0, 0x70, 0xe0, + 0xf, 0x9f, 0xf, 0x8f, 0x1f, 0x0, 0x0, 0x0, + + /* U+E510 "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0x7f, 0x80, 0x1f, 0xfc, 0x3, 0xff, 0xe0, 0x7f, + 0xfc, 0xf, 0xff, 0x9c, 0x7f, 0xfb, 0xe3, 0xff, + 0xb6, 0x3e, 0x33, 0x63, 0xe6, 0x7f, 0x3e, 0x67, + 0xf3, 0xe6, 0x7f, 0x3f, 0xe7, 0xf1, 0xfe, 0x7f, + 0x0, 0x7, 0xf0, + + /* U+E511 "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x7, 0xf0, 0x0, + 0xff, 0x80, 0x1f, 0xfc, 0x3, 0xff, 0xe0, 0x7f, + 0xff, 0x7, 0xf3, 0x0, 0x7f, 0x27, 0x83, 0xc0, + 0xfe, 0x3c, 0x1f, 0xe3, 0xf1, 0xf7, 0x3f, 0x1a, + 0xf3, 0xf9, 0xdf, 0x3f, 0xdf, 0xe1, 0xfc, 0xfe, + 0x0, 0x7, 0x80, + + /* U+E512 "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x7, 0xf0, 0x0, + 0xff, 0x80, 0x1f, 0xfc, 0x3, 0xff, 0xe0, 0x7f, + 0xff, 0x7, 0xf3, 0x0, 0x3f, 0x27, 0xc3, 0xc0, + 0xee, 0x3c, 0x1e, 0xf3, 0xf1, 0xef, 0x3f, 0x1e, + 0xf3, 0xf9, 0xff, 0x3f, 0xde, 0xf1, 0xfc, 0xfe, + 0x0, 0x7, 0xc0, + + /* U+E513 "" */ + 0x0, 0x80, 0x0, 0x7c, 0x0, 0x1f, 0xc0, 0x7, + 0xfc, 0x1, 0xff, 0xc0, 0x7f, 0xfc, 0x1f, 0xff, + 0xc7, 0xf9, 0x80, 0x3f, 0x27, 0x87, 0x81, 0xf8, + 0xf0, 0x6d, 0x9f, 0x8c, 0x73, 0xf1, 0xce, 0x7f, + 0x39, 0xcf, 0xf6, 0xd8, 0xfe, 0x7e, 0x0, 0x7, + 0x80, + + /* U+E514 "" */ + 0x0, 0x3, 0x0, 0x0, 0x3f, 0x3, 0x83, 0xf0, + 0x7c, 0x3f, 0xf, 0xe3, 0xf1, 0xff, 0x3f, 0x3f, + 0xf3, 0x7, 0xcf, 0x30, 0xfc, 0xf3, 0x7, 0x83, + 0x30, 0x70, 0x33, 0x7, 0x83, 0x30, 0x7c, 0xf3, + 0x7, 0xcf, 0x30, 0x7f, 0xf3, 0x3, 0xff, 0x30, + + /* U+E515 "" */ + 0x3, 0xc0, 0x0, 0xe0, 0x0, 0x18, 0x0, 0x3, + 0x3c, 0x0, 0x67, 0x86, 0x6, 0xe0, 0xf0, 0xdc, + 0x1f, 0x8d, 0x83, 0xfc, 0xd8, 0x3f, 0xcd, 0x83, + 0xfc, 0xd8, 0x30, 0xcc, 0xc0, 0x4, 0x6c, 0x6, + 0x6, 0x71, 0xf1, 0x31, 0xf1, 0xf1, 0x80, 0xe0, + 0xe, 0x1f, 0x10, 0x3f, 0x1f, 0x0, 0x0, 0x0, + + /* U+E516 "" */ + 0x7f, 0x80, 0x0, 0x1, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0x3, 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x80, + + /* U+E517 "" */ + 0x7f, 0x80, 0x0, 0x1, 0xfe, 0xff, 0xff, 0xfc, + 0xf, 0x87, 0xff, 0xf0, 0x3e, 0x1f, 0xff, 0xc0, + 0xf0, 0x3f, 0xff, 0xff, 0x7f, 0x80, + + /* U+E518 "" */ + 0x1, 0x80, 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, + 0xcf, 0xf3, 0xdf, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xc3, 0xc3, 0x3, 0xc0, 0x7, 0xe0, + 0xe, 0x70, 0xe, 0x70, + + /* U+E519 "" */ + 0xc, 0x1, 0xe0, 0x3f, 0x0, 0x0, 0x3f, 0xc7, + 0xfe, 0xff, 0xff, 0xf3, 0xff, 0x3f, 0xf3, 0xff, + 0x3f, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, + + /* U+E51A "" */ + 0x3c, 0x0, 0x31, 0x80, 0x30, 0x40, 0x19, 0xb1, + 0xed, 0xdf, 0xfe, 0xef, 0xff, 0x76, 0x3c, 0xc6, + 0x0, 0x3e, 0x8, 0x0, 0x7f, 0xdf, 0x80, 0xf, + 0x4f, 0xe7, 0xe7, 0xf3, 0xc3, 0xf9, 0xf1, 0xfd, + 0xfc, 0xfe, + + /* U+E51B "" */ + 0x0, 0xc0, 0x0, 0x30, 0x0, 0xc, 0x1, 0x3, + 0x3, 0xe0, 0xc1, 0xcc, 0x1, 0xc1, 0x80, 0x60, + 0x0, 0x0, 0x7, 0xf8, 0x1, 0xfe, 0x7, 0xff, + 0xf9, 0xff, 0xfe, 0x7f, 0xff, 0x9f, 0xff, 0xe7, + 0xff, 0xf9, 0xff, 0xfe, + + /* U+E51C "" */ + 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0x80, + 0x1, 0x80, 0x7f, 0xfe, 0x7f, 0xfe, 0x36, 0x6c, + 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, + 0x36, 0x6c, 0x36, 0x6c, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, + + /* U+E51D "" */ + 0x1f, 0xfc, 0x1f, 0xff, 0xc, 0x1, 0x86, 0x0, + 0xc3, 0x0, 0x1, 0x83, 0xe0, 0xc1, 0xf8, 0x60, + 0xf6, 0xff, 0x79, 0xff, 0xbf, 0xdf, 0xdf, 0xe0, + 0xf, 0xf0, 0x7, 0xf8, 0x3, 0xfc, 0x1, 0xfe, + 0x0, 0xff, + + /* U+E51E "" */ + 0xd, 0xb0, 0xdb, 0x1d, 0xb1, 0x9b, 0x1b, 0x33, + 0xb3, 0x33, 0x33, 0x33, 0x73, 0x36, 0x33, 0x66, + 0x3e, 0x63, 0xc6, 0x3c, 0x63, + + /* U+E51F "" */ + 0xf, 0x0, 0x3f, 0xc0, 0x7f, 0xe0, 0xff, 0xf0, + 0xf9, 0xf0, 0xf0, 0xf0, 0xf0, 0xc0, 0xf9, 0x9c, + 0xff, 0xb6, 0x7f, 0xb6, 0x7f, 0x36, 0x3f, 0x7f, + 0x1f, 0x7f, 0x1f, 0x7f, 0xf, 0x7f, 0x6, 0x7f, + 0x0, 0x7f, + + /* U+E520 "" */ + 0x0, 0x78, 0x0, 0x1, 0x80, 0x0, 0x30, 0x0, + 0x6, 0x1, 0x98, 0x80, 0xfe, 0x30, 0x36, 0xcc, + 0x9f, 0xff, 0x6f, 0xff, 0xd7, 0xff, 0xb3, 0xff, + 0xfc, 0xdf, 0xfe, 0x66, 0x63, 0x33, 0x30, 0x40, + 0x80, 0x10, + + /* U+E521 "" */ + 0xf, 0x80, 0x3f, 0xe0, 0x7f, 0xf0, 0x7d, 0xf0, + 0xfc, 0xf8, 0xe2, 0x78, 0xe0, 0x38, 0xe0, 0x78, + 0xfe, 0xf8, 0x7d, 0xf0, 0x7f, 0xf0, 0x3f, 0xf8, + 0xf, 0x9c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, + + /* U+E522 "" */ + 0xf, 0x80, 0x3f, 0xe0, 0x7f, 0xf0, 0x7d, 0xf0, + 0xfd, 0xf8, 0xfd, 0x38, 0xe5, 0x38, 0xe5, 0x38, + 0xe5, 0x38, 0x65, 0x30, 0x7f, 0xf0, 0x3f, 0xf8, + 0xf, 0x9c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, + + /* U+E523 "" */ + 0x0, 0x1, 0xf0, 0x40, 0x1f, 0x6, 0x0, 0xf7, + 0x67, 0xdf, 0x3c, 0xff, 0xb3, 0xdc, 0x70, 0x7b, + 0x83, 0x8f, 0xb0, 0x18, 0x1b, 0x1, 0x81, 0xb0, + 0x18, 0x1b, 0x83, 0x80, 0x1c, 0x70, 0x0, 0xfe, + 0x0, 0x7, 0xc0, 0x0, 0x38, 0x0, 0x7, 0xc0, + 0x0, 0x7c, 0x0, 0x3, 0x80, 0x0, 0x10, 0x0, + + /* U+E524 "" */ + 0x0, 0xf0, 0x0, 0x1f, 0x80, 0x3, 0xfc, 0x7, + 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x79, 0xe3, 0xcf, + 0xf, 0x3c, 0xe0, 0x73, 0xce, 0x67, 0x37, 0xe6, + 0x7e, 0x7e, 0x67, 0xe1, 0xf6, 0xf8, 0x3, 0x6c, + 0x0, 0x16, 0x80, 0x0, 0x60, 0x0, + + /* U+E525 "" */ + 0x7f, 0x7f, 0xbf, 0xdf, 0xfc, 0x37, 0xff, 0xd, + 0xff, 0xc3, 0x7f, 0xf0, 0xdf, 0xfc, 0x37, 0xff, + 0xd, 0xff, 0xc3, 0x7f, 0xf0, 0xdf, 0xff, 0xf7, + 0xfd, 0xfd, 0xfe, + + /* U+E527 "" */ + 0x7f, 0xde, 0x3f, 0xc7, 0xff, 0xfe, 0xf, 0xc1, + 0xf8, 0x3f, 0x7, 0xff, 0xf9, 0x4f, 0x29, 0xff, + 0xfc, 0xa7, 0x94, 0xff, 0xfb, 0xfe, + + /* U+E528 "" */ + 0x20, 0x0, 0x18, 0x0, 0xf, 0xff, 0xf1, 0x9f, + 0xfe, 0x27, 0xf9, 0x81, 0x87, 0xe0, 0x40, 0xf9, + 0x30, 0x3e, 0x7c, 0xc, 0x9f, 0x2, 0x7, 0xe1, + 0x81, 0x9f, 0xec, 0x7f, 0xf9, 0x8f, 0xff, 0xf0, + 0x0, 0x18, 0x0, 0xc, + + /* U+E529 "" */ + 0x0, 0x3e, 0x0, 0xe, 0x4, 0x1e, 0xf, 0x36, + 0x19, 0xe0, 0x30, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0xdf, 0xfb, 0xfe, 0x3f, 0xfe, 0x3f, + 0xfe, 0x3f, 0xde, 0x3f, 0xdf, 0xfb, 0xff, 0xff, + + /* U+E52A "" */ + 0x4, 0x88, 0x76, 0xcc, 0x7, 0xee, 0xf8, 0x22, + 0x0, 0x0, 0x3, 0x66, 0x76, 0xee, 0x0, 0x88, + 0x0, 0x0, 0xff, 0xff, 0xdf, 0xfb, 0xfc, 0x3f, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xdf, 0xfb, + 0xff, 0xff, + + /* U+E52B "" */ + 0xc, 0x18, 0x3, 0x36, 0x0, 0x6f, 0x0, 0x33, + 0x60, 0x6, 0xf8, 0x0, 0xf8, 0x7, 0xff, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xef, + 0xf8, 0x1b, 0xc0, 0x6, 0xf0, 0x3, 0x6, 0x0, + 0x80, 0x80, + + /* U+E52C "" */ + 0x8, 0x8, 0x1, 0x81, 0x80, 0x1b, 0x60, 0x2, + 0x6c, 0x0, 0xed, 0x80, 0xf, 0xe0, 0x3, 0xff, + 0x3, 0xff, 0xfc, 0xff, 0xff, 0xdf, 0xff, 0xfb, + 0xff, 0xc0, 0x3b, 0x63, 0x60, 0x6c, 0xfe, 0xd, + 0x9f, 0xc3, 0x1, 0xb0, 0x40, 0x7f, 0x0, 0xf, + 0xe0, 0x0, 0xd8, + + /* U+E52D "" */ + 0x3, 0xc0, 0xf, 0xf0, 0xf, 0xf0, 0x1f, 0xf8, + 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, + 0xff, 0xff, 0xff, 0xff, + + /* U+E52E "" */ + 0x0, 0xfd, 0x80, 0x1f, 0xb0, 0x3, 0xf6, 0x0, + 0x67, 0xf0, 0x4, 0xfe, 0x6, 0x7f, 0xc0, 0xc3, + 0x98, 0x3c, 0x73, 0xc, 0xdf, 0xe1, 0x99, 0xcc, + 0x67, 0xb9, 0x8f, 0xf3, 0xf3, 0xff, 0x7e, 0xff, + 0xf7, 0xdf, 0xfe, 0x7b, 0xff, 0xcf, + + /* U+E52F "" */ + 0x1, 0x83, 0x80, 0xf1, 0xf0, 0x3c, 0x7c, 0x1f, + 0x9f, 0x6, 0x63, 0x83, 0x9c, 0x0, 0xc3, 0x0, + 0x73, 0xe0, 0x1d, 0xf8, 0xf, 0xff, 0x3, 0xff, + 0xc1, 0xff, 0xf8, 0x7f, 0xfe, 0x3f, 0xff, 0xcf, + 0xff, 0xf0, + + /* U+E532 "" */ + 0x0, 0x6, 0x0, 0x3, 0xc0, 0x0, 0x78, 0x0, + 0x1e, 0x0, 0x8f, 0x88, 0x7f, 0xe6, 0x7f, 0xbd, + 0xfe, 0xf, 0x78, 0x3, 0xd8, 0x58, 0xe6, 0x36, + 0x1, 0x9f, 0xc0, 0x66, 0x30, 0x1b, 0x8e, 0xf, + 0xff, 0xff, 0xff, 0xff, + + /* U+E533 "" */ + 0x1, 0x80, 0x33, 0xcc, 0x7b, 0xde, 0x30, 0xc, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xc0, 0x77, 0xee, + 0xf7, 0xef, 0xf7, 0xef, 0xf7, 0xef, 0x73, 0xce, + 0x7b, 0xde, 0x7b, 0xde, 0x7b, 0xde, 0x3, 0xc0, + + /* U+E534 "" */ + 0x0, 0xc0, 0x6, 0x79, 0x83, 0xde, 0xf0, 0x60, + 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x0, + 0xef, 0xdc, 0x7b, 0xf7, 0x9e, 0xfd, 0xe7, 0xbf, + 0x78, 0xe7, 0x9c, 0x3d, 0xef, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xff, 0xff, + + /* U+E535 "" */ + 0x70, 0x7, 0x1c, 0x1, 0xc7, 0x0, 0x70, 0x0, + 0x0, 0x78, 0x1e, 0x3f, 0xdf, 0xcf, 0xfe, 0xf3, + 0xf7, 0xbe, 0xfc, 0x5d, 0xff, 0x3, 0xf, 0xc0, + 0xe0, 0xf8, 0x5c, 0x36, 0x33, 0xd, 0x9c, 0xc3, + 0x6e, 0x18, 0x5b, 0x6, + + /* U+E536 "" */ + 0x61, 0x99, 0xb8, 0xce, 0xd8, 0x36, 0x60, 0x1c, + 0x67, 0x87, 0xf7, 0xc1, 0xf3, 0xf0, 0xf9, 0xfe, + 0x7c, 0xff, 0x3e, 0x7c, 0x1f, 0x3e, 0xf, 0x9f, + 0x7, 0xcf, 0x83, 0xe7, 0xc1, 0xf3, 0xe0, 0xf9, + 0xa0, 0x68, + + /* U+E537 "" */ + 0x0, 0x0, 0x0, 0x78, 0x0, 0x7f, 0x80, 0x78, + 0x78, 0x78, 0x7, 0xb8, 0x0, 0x70, 0xc, 0x0, + 0x47, 0x88, 0x38, 0xc7, 0xe, 0x1, 0xc0, 0x0, + 0x0, 0x7, 0x88, 0x3b, 0xf7, 0x1e, 0xfd, 0xe7, + 0xbf, 0x79, 0xef, 0xde, + + /* U+E538 "" */ + 0x6, 0x2, 0x3, 0xc1, 0xc0, 0x60, 0x70, 0x0, + 0x1c, 0x0, 0x7, 0x3, 0xc7, 0xf1, 0xf9, 0xfc, + 0xff, 0x3e, 0x7f, 0xe7, 0x1f, 0xf8, 0x8d, 0xfb, + 0x0, 0x7e, 0x0, 0x1f, 0x80, 0x7, 0xe0, 0x1, + 0xf8, 0x0, 0x7e, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xf0, + + /* U+E539 "" */ + 0x6, 0x2, 0x3, 0xc1, 0xc0, 0x60, 0xf8, 0x0, + 0x7f, 0x0, 0x1f, 0xc3, 0xc1, 0xc1, 0xf8, 0x70, + 0xff, 0x1c, 0x7f, 0xe2, 0x1f, 0xf8, 0x8d, 0xfb, + 0x0, 0x7e, 0x0, 0x1f, 0x80, 0x7, 0xe0, 0x1, + 0xf8, 0x0, 0x7e, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xf0, + + /* U+E53A "" */ + 0x3, 0x80, 0x1f, 0x0, 0x7c, 0x1, 0xf0, 0x3, + 0x80, 0x0, 0x0, 0x7e, 0x7, 0xfc, 0x1f, 0xf8, + 0xec, 0xe7, 0xb3, 0xde, 0x5f, 0x7c, 0xf8, 0xfc, + 0xe0, 0xf3, 0x0, 0xc0, + + /* U+E53B "" */ + 0x6, 0x0, 0x6, 0x70, 0x66, 0x70, 0x30, 0x70, + 0x0, 0x0, 0x0, 0x0, 0xe0, 0xf8, 0x61, 0xfc, + 0x3, 0xfe, 0x33, 0xfe, 0x66, 0xfb, 0x6, 0xfb, + 0x0, 0xf8, 0x0, 0xd8, 0x0, 0xd8, 0x0, 0xd8, + 0x0, 0xd8, 0x0, 0xd8, 0x0, 0xd8, 0x0, 0x0, + + /* U+E53C "" */ + 0xe, 0x0, 0x78, 0x3, 0x80, 0x0, 0x0, 0xe0, + 0xf, 0x80, 0xfe, 0xf, 0xf8, 0xff, 0xe6, 0xfb, + 0x37, 0xc8, 0x3e, 0x1, 0xb7, 0xd, 0xbc, 0x6c, + 0x63, 0x63, 0x1b, 0x18, 0xd8, 0x40, + + /* U+E53D "" */ + 0xe, 0x0, 0x1, 0xcf, 0xfc, 0x39, 0xff, 0x82, + 0x30, 0x30, 0x6, 0x6, 0x3f, 0xe0, 0xcf, 0xfc, + 0x1b, 0xf8, 0x3, 0xff, 0x60, 0x7b, 0xef, 0xfe, + 0x7d, 0xff, 0x8f, 0x80, 0x1, 0xb0, 0x0, 0x36, + 0x0, 0x6, 0xc0, 0x0, 0xd8, 0x0, 0x1b, 0x0, + 0x3, 0x60, 0x0, 0x0, 0x0, 0x0, + + /* U+E53E "" */ + 0xe, 0x0, 0x1, 0xc0, 0x0, 0x38, 0x0, 0x0, + 0x0, 0x0, 0xe0, 0x0, 0x7f, 0x0, 0xf, 0xf0, + 0x3, 0xfe, 0x0, 0xff, 0xe0, 0x1b, 0xe9, 0xe2, + 0x7c, 0x7f, 0xf, 0x9f, 0xe1, 0xb3, 0xee, 0x36, + 0x6b, 0xc6, 0xce, 0xf8, 0xd9, 0xfe, 0x1b, 0x1f, + 0xc3, 0x61, 0xe0, + + /* U+E53F "" */ + 0xe, 0x0, 0x3, 0x80, 0x0, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0x80, 0x3, 0xf0, 0x0, + 0xfe, 0x0, 0x7f, 0xc0, 0x3f, 0xf1, 0xd, 0xf1, + 0xf0, 0x7c, 0xee, 0x1b, 0x7b, 0xc6, 0xde, 0xf1, + 0xb7, 0xfc, 0x6d, 0xef, 0x1b, 0x3f, 0x86, 0xc7, + 0xc0, + + /* U+E540 "" */ + 0xe, 0x0, 0x3, 0x80, 0x0, 0xe0, 0x0, 0x0, + 0x0, 0xe, 0x0, 0xf, 0xc0, 0x3, 0xf8, 0x1, + 0xfe, 0x0, 0xff, 0xc0, 0x37, 0xc7, 0xc9, 0xf3, + 0xf8, 0x7d, 0xff, 0x1b, 0x7f, 0xc6, 0xd8, 0x31, + 0xb7, 0xfc, 0x6d, 0xff, 0x1b, 0x3f, 0x86, 0xc7, + 0xc0, + + /* U+E541 "" */ + 0xe, 0x0, 0x3, 0x80, 0x0, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0x80, 0x3, 0xf0, 0x0, + 0xfe, 0x0, 0x7f, 0xc0, 0x3f, 0xf1, 0xd, 0xf1, + 0xf0, 0x7c, 0xfe, 0x1b, 0x7b, 0xc6, 0xd8, 0x31, + 0xb7, 0xbc, 0x6d, 0xef, 0x1b, 0x3f, 0x86, 0xc7, + 0xc0, + + /* U+E542 "" */ + 0xe, 0x0, 0x1, 0xc0, 0x0, 0x38, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3c, 0x0, 0xf, 0xc0, + 0x1, 0xfc, 0x0, 0x7f, 0xc0, 0x1f, 0xf8, 0x3, + 0x7c, 0x7e, 0xf, 0x9e, 0xe1, 0xb7, 0xce, 0x36, + 0xf3, 0xc6, 0xdf, 0xf8, 0xdb, 0xcf, 0x1b, 0x3f, + 0xc3, 0x61, 0xe0, + + /* U+E543 "" */ + 0xe, 0x0, 0x3, 0x80, 0x0, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3, 0xc0, 0x3, 0xf8, 0x0, + 0xff, 0x0, 0x7f, 0xc0, 0x3f, 0xd0, 0xd, 0xf1, + 0xf8, 0x7c, 0x7e, 0x1b, 0x36, 0xc6, 0xce, 0x71, + 0xb3, 0x9c, 0x6c, 0xdb, 0x1b, 0x1f, 0x86, 0xc3, + 0xc0, + + /* U+E544 "" */ + 0x6, 0x0, 0x6, 0x70, 0x66, 0x70, 0x30, 0x70, + 0x0, 0x0, 0x0, 0x0, 0xe0, 0xf8, 0xc1, 0xfc, + 0x3, 0xfe, 0x33, 0xfe, 0x66, 0xfb, 0x7, 0xff, + 0x1, 0xfc, 0x1, 0xfc, 0x0, 0xd8, 0x0, 0xd8, + 0x0, 0xd8, 0x0, 0xd8, 0x0, 0xd8, + + /* U+E545 "" */ + 0x0, 0x60, 0x0, 0xf, 0x0, 0x18, 0x60, 0x0, + 0xc0, 0x0, 0xe, 0x7, 0x80, 0x7f, 0xf0, 0x3, + 0xf8, 0x0, 0x1f, 0x0, 0x1, 0xf0, 0x0, 0x6, + 0x0, 0x6, 0xe, 0x1, 0xf9, 0xf2, 0xf0, 0xf1, + 0xe0, 0x0, 0x0, + + /* U+E546 "" */ + 0x1, 0x80, 0xc3, 0x3, 0xc6, 0x3, 0x18, 0x0, + 0x70, 0x3, 0xc0, 0x7, 0xc0, 0x1f, 0xc0, 0x3f, + 0xf8, 0x6f, 0xf8, 0xce, 0x31, 0x8c, 0x20, 0xc, + 0x0, 0x1c, 0x0, 0x1c, 0x0, 0x18, + + /* U+E547 "" */ + 0x1, 0xb0, 0x30, 0xd8, 0x3c, 0x6c, 0xcc, 0x60, + 0xc0, 0x70, 0x0, 0xf0, 0x18, 0x7c, 0xe, 0x7f, + 0x0, 0x3f, 0xf0, 0x1b, 0xfc, 0xc, 0xe7, 0x6, + 0x31, 0x80, 0xc, 0x0, 0x7, 0x0, 0x1, 0xc0, + 0x0, 0x60, + + /* U+E548 "" */ + 0xe, 0x1, 0xc0, 0x38, 0x0, 0x0, 0xa0, 0x77, + 0xe, 0xe3, 0xde, 0xfb, 0xff, 0x6c, 0xec, 0x1d, + 0x83, 0xb0, 0x36, 0x6, 0xc0, 0xd8, 0x1b, 0x0, + 0x0, + + /* U+E549 "" */ + 0x6, 0x0, 0x1, 0xdc, 0x0, 0x60, 0x0, 0x3, + 0x0, 0x1e, 0x20, 0xf, 0xc0, 0x3, 0xf8, 0xc1, + 0xff, 0x38, 0xfe, 0xec, 0x37, 0x80, 0x61, 0xe0, + 0x3c, 0x78, 0x2f, 0x1e, 0x1f, 0xc7, 0x87, 0xf1, + 0xe3, 0x3c, 0x68, 0xc6, + + /* U+E54A "" */ + 0x1, 0xf0, 0x3, 0xf0, 0x0, 0x0, 0x3, 0xf0, + 0x1, 0xe0, 0x1, 0xe0, 0x0, 0x0, 0xff, 0xe8, + 0xff, 0xd8, 0x3, 0xbc, 0x2, 0x7e, 0x0, 0xfe, + 0x1, 0xf7, 0x0, 0x7, 0x3, 0xf0, 0x3, 0xf0, + + /* U+E54B "" */ + 0x7, 0xc0, 0x3f, 0x20, 0x0, 0xc3, 0xf6, 0x7, + 0x98, 0x1e, 0xc0, 0x3, 0x1, 0xfc, 0x17, 0x60, + 0xed, 0xc3, 0xdf, 0x1f, 0x7e, 0x6e, 0xdb, 0xbd, + 0x7c, 0xf0, 0xc3, 0xe0, + + /* U+E54C "" */ + 0x3c, 0x0, 0x0, 0x18, 0x3c, 0x3c, 0x3c, 0x3c, + 0x18, 0x18, 0x0, 0x0, 0x1c, 0x3c, 0x66, 0x7e, + 0x72, 0x7e, 0x7c, 0x7e, 0x0, 0x0, 0x8, 0x10, + 0x1c, 0x38, 0xfe, 0x7f, 0x1c, 0x38, 0x8, 0x10, + + /* U+E54D "" */ + 0x1, 0xc0, 0x41, 0xc1, 0x61, 0xc3, 0x30, 0x86, + 0x10, 0xc, 0x3, 0xe0, 0x7, 0xf0, 0xf, 0xf8, + 0x1f, 0xf8, 0x1b, 0xec, 0x13, 0xe4, 0x3, 0xe0, + 0x3, 0x60, 0x13, 0x6c, 0x33, 0x66, 0x63, 0x63, + 0x43, 0x61, 0x3, 0x60, + + /* U+E54E "" */ + 0x0, 0x10, 0x1c, 0x60, 0x7c, 0x40, 0xf8, 0x80, + 0xe3, 0x80, 0x7, 0x0, 0xe, 0x87, 0xbf, 0x3f, + 0x7e, 0xfe, 0xff, 0xfd, 0xe6, 0xfb, 0xfd, 0xf3, + 0xfb, 0xe3, 0x37, 0xc7, 0xf, 0x8e, + + /* U+E54F "" */ + 0x1, 0x80, 0x7, 0xe0, 0x1f, 0x78, 0x7c, 0x3e, + 0xf1, 0x8f, 0xc1, 0x83, 0xc0, 0x3, 0xc3, 0xc3, + 0xc7, 0xe3, 0xcf, 0xf3, 0xcb, 0xf3, 0xcb, 0xd3, + 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x0, 0x0, + + /* U+E551 "" */ + 0xe, 0x0, 0x1, 0xe0, 0x0, 0xe, 0x0, 0x0, + 0x0, 0x0, 0x1c, 0x0, 0x3, 0xf0, 0x0, 0x7f, + 0x83, 0xef, 0xfe, 0x7, 0xde, 0xe0, 0x3d, 0xe0, + 0x63, 0xde, 0xe, 0x30, 0xf0, 0xfe, 0x17, 0x8e, + 0x3, 0x98, 0x60, 0x71, 0x80, 0xe, 0x18, 0x0, + 0xc1, 0x80, 0x0, 0x8, 0x0, + + /* U+E552 "" */ + 0xe, 0x0, 0x3, 0xc0, 0x0, 0x38, 0x0, 0x0, + 0x0, 0x1, 0xe0, 0x0, 0x7e, 0x0, 0x1f, 0xe0, + 0x67, 0xff, 0x6, 0xde, 0x6f, 0xfb, 0xc0, 0x18, + 0x38, 0x6, 0x3, 0x80, 0x1, 0x38, 0x0, 0x73, + 0x0, 0x1c, 0x60, 0x7, 0xc, 0x0, 0xc0, 0x80, + 0x0, + + /* U+E553 "" */ + 0xe, 0x0, 0x1, 0xe0, 0xc0, 0xe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xe0, 0xc0, 0x3f, + 0xc, 0xcf, 0xfe, 0x6, 0xde, 0x67, 0xfd, 0xe0, + 0x6, 0xde, 0x0, 0xc0, 0xe0, 0xc0, 0x17, 0x8c, + 0x3, 0x98, 0x0, 0x79, 0x80, 0xf, 0x18, 0xc0, + 0xe1, 0x8c, 0x0, 0x8, 0x0, + + /* U+E554 "" */ + 0x0, 0x70, 0x0, 0x78, 0x0, 0x1c, 0x0, 0x0, + 0x0, 0xe, 0x0, 0xf, 0xc0, 0xf, 0xf0, 0xf, + 0xfe, 0x6, 0xf7, 0x3, 0x78, 0x1, 0xbc, 0x0, + 0x8e, 0x7, 0xc3, 0x83, 0xc4, 0xe3, 0xe7, 0x31, + 0xe7, 0x18, 0xf7, 0xc, 0x33, 0x2, 0x0, + + /* U+E555 "" */ + 0x1, 0x80, 0x0, 0x78, 0x0, 0xf, 0x0, 0x1, + 0xe0, 0x0, 0x3c, 0x0, 0x7, 0x80, 0x1, 0xf8, + 0x0, 0x7f, 0x80, 0x1f, 0xe0, 0x7, 0xf8, 0xf1, + 0xfe, 0x7f, 0x7f, 0xcf, 0xfe, 0x3b, 0xee, 0x7, + 0x61, 0xc0, 0xee, 0x78, 0x3c, 0xff, 0xf, 0xdf, + 0xc1, 0x80, 0xf0, + + /* U+E556 "" */ + 0x1, 0x80, 0x0, 0x78, 0x0, 0xf, 0x0, 0x1, + 0xe0, 0x0, 0x3c, 0x0, 0x7, 0x80, 0x1, 0xf8, + 0x0, 0x7f, 0x80, 0x1f, 0xe0, 0x7, 0xf8, 0xf3, + 0xfe, 0x77, 0x7d, 0xce, 0xfc, 0x3b, 0xde, 0x7, + 0x7b, 0xc0, 0xef, 0xf8, 0x3c, 0xef, 0xf, 0xdf, + 0xc1, 0x80, 0xf0, + + /* U+E557 "" */ + 0x1, 0x80, 0x0, 0x78, 0x0, 0xf, 0x0, 0x1, + 0xe0, 0x0, 0x3c, 0x0, 0x7, 0x80, 0x1, 0xf8, + 0x0, 0x7f, 0x80, 0x1f, 0xf0, 0x7, 0xf8, 0xf3, + 0xfe, 0x7f, 0x7d, 0xcd, 0xbc, 0x3b, 0x8e, 0x7, + 0x79, 0xc0, 0xee, 0x38, 0x3c, 0xdb, 0xf, 0x9f, + 0xc1, 0xc8, 0xf0, + + /* U+E558 "" */ + 0x1, 0xc0, 0x0, 0x78, 0x0, 0xf, 0x0, 0x1, + 0xe0, 0x0, 0x3c, 0x0, 0x7, 0x80, 0x0, 0xf8, + 0x0, 0x7f, 0x80, 0x1f, 0xf3, 0x87, 0xfe, 0xd9, + 0xff, 0xdb, 0x7f, 0xf3, 0x6e, 0x3c, 0xfe, 0x7, + 0x9f, 0xc0, 0xf3, 0xf8, 0x3f, 0x7f, 0xf, 0xef, + 0xe1, 0x85, 0xfc, + + /* U+E55A "" */ + 0x6, 0xcc, 0x76, 0xee, 0x7, 0xee, 0xf8, 0x22, + 0x0, 0x0, 0x3, 0x66, 0x76, 0xee, 0x6, 0xcc, + 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x3f, 0xfc, 0x1f, 0xf8, + + /* U+E55B "" */ + 0x18, 0x60, 0x6, 0x18, 0x1, 0x86, 0x0, 0x61, + 0x80, 0xff, 0xfc, 0x3f, 0xff, 0x7, 0xff, 0x81, + 0xff, 0xe0, 0x7f, 0xc0, 0x1f, 0xe7, 0xc3, 0xf3, + 0xf8, 0xfd, 0xf7, 0x1f, 0x73, 0xc1, 0xd8, 0x30, + 0x37, 0x9c, 0xd, 0xcf, 0x3, 0x3f, 0x80, 0x7, + 0xc0, + + /* U+E55C "" */ + 0x18, 0x60, 0x6, 0x18, 0x1, 0x86, 0x0, 0x61, + 0x80, 0xff, 0xfc, 0x3f, 0xff, 0x7, 0xff, 0x81, + 0xff, 0xe0, 0x7f, 0xc0, 0x1f, 0xe7, 0xc3, 0xf3, + 0xf8, 0xfd, 0xff, 0x1f, 0x7d, 0xc1, 0xda, 0xf0, + 0x37, 0x3c, 0xd, 0xff, 0x3, 0x3f, 0x80, 0x7, + 0xc0, + + /* U+E55D "" */ + 0x18, 0x60, 0x6, 0x18, 0x1, 0x86, 0x0, 0x61, + 0x80, 0xff, 0xfc, 0x3f, 0xff, 0x7, 0xff, 0x81, + 0xff, 0xe0, 0x7f, 0xc0, 0x1f, 0xe7, 0xc3, 0xf3, + 0xb8, 0xfd, 0xef, 0x1f, 0x7b, 0xc1, 0xde, 0xf0, + 0x37, 0xfc, 0xd, 0xef, 0x3, 0x3f, 0x80, 0x7, + 0xc0, + + /* U+E55E "" */ + 0x18, 0x60, 0x6, 0x18, 0x1, 0x86, 0x0, 0x61, + 0x80, 0xff, 0xfc, 0x3f, 0xff, 0x7, 0xff, 0x81, + 0xff, 0xe0, 0x7f, 0xc0, 0x1f, 0xe7, 0xc3, 0xf3, + 0xf8, 0xfd, 0xff, 0x1f, 0x7f, 0xc1, 0xd8, 0x30, + 0x37, 0xfc, 0xd, 0xff, 0x3, 0x3f, 0x80, 0x7, + 0xc0, + + /* U+E55F "" */ + 0x18, 0x60, 0x6, 0x18, 0x1, 0x86, 0x0, 0x61, + 0x80, 0xff, 0xfc, 0x3f, 0xff, 0x7, 0xff, 0x81, + 0xff, 0xe0, 0x7f, 0xc0, 0x1f, 0xe7, 0xc3, 0xf3, + 0xf8, 0xfd, 0xef, 0x1f, 0x7b, 0xc1, 0xd8, 0x30, + 0x37, 0xbc, 0xd, 0xef, 0x3, 0x3f, 0x80, 0x7, + 0xc0, + + /* U+E560 "" */ + 0x18, 0x60, 0x6, 0x18, 0x1, 0x86, 0x0, 0x61, + 0x80, 0xff, 0xfc, 0x3f, 0xff, 0x7, 0xff, 0x81, + 0xff, 0xe0, 0x7f, 0xc0, 0x1f, 0xe7, 0xc7, 0xf3, + 0xf8, 0xfd, 0xdb, 0x1f, 0x75, 0xc3, 0xde, 0xf0, + 0x37, 0x5c, 0xd, 0xdb, 0x3, 0x3f, 0x80, 0x7, + 0xc0, + + /* U+E561 "" */ + 0x0, 0x80, 0x0, 0x40, 0x0, 0xf8, 0x0, 0x38, + 0x0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xe0, 0x1, 0xf0, 0x3e, 0xf8, 0x1f, + 0x7c, 0xf, 0xbe, 0xff, 0xdf, 0x7f, 0xef, 0xbf, + 0xf7, 0xdf, + + /* U+E562 "" */ + 0xc0, 0x0, 0x3c, 0x0, 0x3, 0xf3, 0x33, 0x3f, + 0x33, 0x33, 0xe6, 0x66, 0x7e, 0x66, 0x67, 0xcc, + 0xcc, 0xfc, 0xcc, 0xcf, 0xc0, 0x0, 0x3c, 0x0, + 0x3, 0xc0, 0x0, 0x3c, 0x0, 0x3, 0xc0, 0x0, + 0x3c, 0x0, 0x3, + + /* U+E563 "" */ + 0xff, 0x7b, 0xff, 0xde, 0xf6, 0x27, 0xbd, 0x89, + 0xff, 0xff, 0x7f, 0xff, 0xde, 0xff, 0xf7, 0xbf, + 0xfd, 0xef, 0x3e, 0x7b, 0xcf, 0x1f, 0xf3, 0x87, + 0xfc, 0xe1, 0xef, 0x38, 0x7b, 0xce, 0x1e, 0xf0, + + /* U+E564 "" */ + 0x1e, 0x78, 0x7, 0x9e, 0x3, 0xe7, 0x80, 0xff, + 0xf0, 0x3f, 0xfc, 0xf, 0x98, 0x7, 0xe4, 0x1, + 0xf8, 0x78, 0x7e, 0x3f, 0x9f, 0xdf, 0xef, 0xf7, + 0xdf, 0xfd, 0xaf, 0xff, 0x77, 0xdf, 0xdf, 0xe0, + 0x3, 0xf8, 0x0, 0x78, + + /* U+E565 "" */ + 0x1e, 0x78, 0x7, 0x9e, 0x3, 0xe7, 0xc0, 0xff, + 0xf0, 0x3f, 0xfc, 0xf, 0x98, 0x7, 0xe4, 0x1, + 0xf8, 0x7c, 0x7f, 0x3b, 0x9f, 0xde, 0xff, 0xf7, + 0xbf, 0xfd, 0xef, 0xff, 0x7f, 0xdf, 0xde, 0xf0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E566 "" */ + 0x1e, 0x78, 0x7, 0x9e, 0x3, 0xe7, 0xc0, 0xff, + 0xf0, 0x3f, 0xfc, 0xf, 0x98, 0x7, 0xe4, 0x1, + 0xf8, 0x7c, 0x7f, 0x3f, 0x9f, 0xdb, 0xb7, 0xf7, + 0x5f, 0xfd, 0xef, 0xff, 0x75, 0xff, 0xdb, 0xb0, + 0x3, 0xf8, 0x0, 0x7c, + + /* U+E567 "" */ + 0x1e, 0x70, 0xf, 0x3c, 0xf, 0x9e, 0x7, 0xff, + 0x83, 0xff, 0xc1, 0xf3, 0x1, 0xf9, 0x38, 0xfc, + 0xb6, 0x7e, 0x5b, 0x3f, 0xed, 0xbf, 0xe7, 0xff, + 0xc7, 0xff, 0xe3, 0xff, 0xf1, 0xfc, 0x0, 0xfe, + 0x0, 0x3f, + + /* U+E568 "" */ + 0x22, 0x22, 0x3, 0x33, 0x30, 0x33, 0x33, 0x3, + 0xbb, 0xb8, 0x3f, 0xff, 0xc3, 0xff, 0xfc, 0x3f, + 0xff, 0xe3, 0xff, 0xfe, 0x0, 0x0, 0xf, 0xff, + 0xff, 0xff, 0xff, 0xf0, + + /* U+E569 "" */ + 0xef, 0xfd, 0xdb, 0xff, 0x6e, 0xff, 0xdf, 0xbf, + 0xf7, 0x6f, 0xfd, 0xbb, 0xff, 0x76, 0xff, 0xd9, + 0xbf, 0xf6, 0xef, 0xfd, 0xdb, 0xff, 0x66, 0xff, + 0xdb, 0xbf, 0xf7, + + /* U+E56A "" */ + 0xf, 0xe0, 0x1f, 0xc0, 0x1f, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xfc, 0x7, 0xfc, 0x1f, 0xfc, 0x79, + 0x3c, 0xf2, 0x7b, 0xf1, 0xff, 0xe3, 0xff, 0x93, + 0xff, 0x27, 0xff, 0xff, 0xbf, 0xfe, + + /* U+E56B "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0x7f, 0x80, 0x7f, 0x3f, 0x8f, 0xe1, 0xfc, 0xce, + 0x18, 0xc, 0xf3, 0x0, 0xff, 0xe7, 0xcf, 0xfc, + 0xfe, 0xce, 0x1f, 0xfc, 0xe1, 0xf7, 0xfe, 0x1b, + 0x7f, 0xe1, 0xcf, 0xfe, 0x1f, 0xf7, 0xfc, 0xfe, + 0x0, 0x7, 0xc0, + + /* U+E56C "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0x7f, 0x80, 0x7f, 0x3f, 0x8f, 0xe1, 0xfc, 0xce, + 0x18, 0xc, 0xf3, 0x0, 0xff, 0xe7, 0xcf, 0xfc, + 0xee, 0xce, 0x1e, 0xfc, 0xe1, 0xef, 0xfe, 0x1e, + 0xff, 0xe1, 0xff, 0xff, 0xde, 0xf7, 0xfc, 0xfe, + 0x0, 0x7, 0xc0, + + /* U+E56D "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0x7f, 0x80, 0x7f, 0x3f, 0x8f, 0xe1, 0xfc, 0xce, + 0x18, 0xc, 0xf3, 0x0, 0xff, 0xe7, 0xcf, 0xfc, + 0xfe, 0xce, 0x1d, 0x7c, 0xe1, 0xd7, 0xfe, 0x1e, + 0xff, 0xe1, 0xd7, 0xfe, 0x1d, 0x77, 0xfc, 0xfe, + 0x0, 0x7, 0xc0, + + /* U+E56E "" */ + 0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3, + 0x0, 0x1, 0xe0, 0x1, 0xfe, 0x7, 0xff, 0xfb, + 0xfc, 0xff, 0xcf, 0x3c, 0xf3, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0xff, 0xcf, 0x3c, 0xf3, 0xcf, 0x3f, + 0xf3, 0xff, 0xfc, 0xff, 0x7f, 0xff, 0x80, + + /* U+E56F "" */ + 0x0, 0xc0, 0x0, 0x1e, 0x0, 0x3, 0xf0, 0x0, + 0x7f, 0x80, 0x7f, 0x1f, 0x8f, 0xe1, 0xfc, 0xce, + 0x1c, 0xc, 0xf3, 0x9c, 0xff, 0xfb, 0x6f, 0xff, + 0xb6, 0xcf, 0x33, 0x6c, 0xe3, 0x7f, 0xfe, 0x37, + 0xff, 0xe3, 0x7f, 0xff, 0xf7, 0xf7, 0xff, 0x7f, + 0x0, 0x7, 0xf0, + + /* U+E571 "" */ + 0x7f, 0xef, 0xff, 0xe7, 0xfc, 0x4f, 0xc8, 0xff, + 0x1f, 0xe3, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xe7, 0xfe, 0xef, 0xfc, 0xff, 0x87, 0xf0, + + /* U+E572 "" */ + 0x3, 0x80, 0x1f, 0xc1, 0xff, 0xf7, 0xff, 0xff, + 0xbb, 0xff, 0x77, 0xfe, 0xf, 0xfc, 0x1f, 0x7a, + 0x7c, 0xf0, 0x79, 0xe0, 0xf1, 0xe3, 0xc1, 0xff, + 0x3, 0xfc, 0x1, 0xf0, 0x1, 0xc0, + + /* U+E573 "" */ + 0x3, 0x80, 0x1f, 0xc1, 0xff, 0xf7, 0xff, 0xff, + 0xff, 0xfe, 0x47, 0xfc, 0xa3, 0xf9, 0x7, 0x7c, + 0xc, 0xe0, 0x39, 0xc3, 0xf1, 0xf7, 0xc1, 0xff, + 0x3, 0xfc, 0x1, 0xf0, 0x1, 0xc0, + + /* U+E574 "" */ + 0x3, 0x80, 0x1f, 0xc0, 0xff, 0xe7, 0xff, 0xff, + 0xff, 0xff, 0x27, 0xfc, 0x7, 0xf8, 0xf, 0x70, + 0x3c, 0xf0, 0x79, 0xfb, 0xf1, 0xff, 0xc1, 0xff, + 0x3, 0xfc, 0x1, 0xf0, 0x1, 0xc0, + + /* U+E576 "" */ + 0x7f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0xa1, 0x79, 0x5e, 0xf0, 0x8d, 0xe1, 0x1b, 0xd2, + 0xf7, 0xb5, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xff, 0x80, + + /* U+E577 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0x8f, 0xfe, 0x3f, 0xf8, + 0xff, 0xfc, 0xff, 0xf1, 0xfe, 0xc7, 0xf1, 0x1f, + 0xc0, 0x7e, 0x61, 0xf9, 0xcf, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+E578 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xfc, 0xf, 0xf0, + 0x3f, 0xd8, 0xfe, 0x1, 0xf8, 0x47, 0xf0, 0x3f, + 0xc0, 0xff, 0x3, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+E579 "" */ + 0x3, 0x0, 0x18, 0x3f, 0xfd, 0xff, 0xfe, 0x31, + 0x81, 0x8c, 0x6d, 0xe7, 0x6e, 0x33, 0x1, 0x98, + 0xf, 0xf8, 0x3f, 0xe0, 0x33, 0x1, 0x98, 0x3d, + 0xc1, 0xec, 0x3, 0x0, 0x18, 0x0, + + /* U+E57A "" */ + 0xc, 0x0, 0x4, 0xc8, 0x0, 0x3f, 0x0, 0x3, + 0x30, 0x1c, 0xed, 0xc3, 0xee, 0xdc, 0x32, 0x33, + 0xf, 0x23, 0xf1, 0xf7, 0x4c, 0x93, 0x70, 0xc3, + 0xb7, 0x0, 0x3b, 0x20, 0x3, 0xb0, 0x0, 0x13, + 0x0, 0x0, 0x30, 0xff, 0xff, 0xff, 0xff, 0xff, + + /* U+E57B "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xcf, 0xff, 0xcf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, + 0xff, 0xee, 0xff, 0xfc, 0xff, 0xf8, 0x7f, 0xf0, + + /* U+E57C "" */ + 0x1, 0x80, 0x1, 0x80, 0x7b, 0xde, 0xfb, 0xdf, + 0xc9, 0x9f, 0xcc, 0x3f, 0xfe, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe7, 0xff, 0xee, 0xff, 0xfc, + 0xff, 0xf8, 0x7f, 0xf0, + + /* U+E57D "" */ + 0x1, 0x80, 0x7, 0xe0, 0xf, 0xf0, 0x3f, 0xfc, + 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0x7f, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x1f, + 0xff, 0x1f, 0xff, 0xf, + + /* U+E57E "" */ + 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, 0x3, 0xf0, + 0x0, 0x78, 0x30, 0xc, 0x3e, 0x0, 0x1f, 0xe0, + 0x1f, 0xfe, 0x7, 0xff, 0x81, 0xfb, 0xe0, 0x7e, + 0xf8, 0x3f, 0x9f, 0xf, 0xe7, 0xc3, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, + + /* U+E57F "" */ + 0x30, 0x6, 0x30, 0x1, 0xbf, 0xff, 0xec, 0x0, + 0x63, 0x0, 0x60, 0xe, 0x0, 0xf, 0x80, 0x1f, + 0xf0, 0x3f, 0xfe, 0x1f, 0xff, 0xf, 0xff, 0x87, + 0xef, 0xc3, 0xf3, 0xe1, 0xf9, 0xf0, 0xfc, 0x78, + + /* U+E580 "" */ + 0x30, 0x0, 0x30, 0x0, 0x3f, 0xff, 0xcc, 0x0, + 0x33, 0x0, 0x18, 0xe, 0xc, 0xf, 0x80, 0x1f, + 0xf0, 0x3f, 0xfe, 0x1f, 0xff, 0xf, 0xff, 0x87, + 0xef, 0xc3, 0xf3, 0xe1, 0xf9, 0xf0, 0xfc, 0x78, + + /* U+E581 "" */ + 0x30, 0xc, 0x30, 0xc, 0x30, 0xc, 0xb4, 0x2d, + 0xfc, 0x3f, 0x78, 0x1e, 0x33, 0xcc, 0xf, 0xe0, + 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0x7c, + 0x7f, 0x7c, 0x7f, 0x3e, 0x7f, 0x3e, 0x7f, 0x1e, + + /* U+E582 "" */ + 0x0, 0x10, 0x0, 0x1f, 0x0, 0x1f, 0xf0, 0xf, + 0xfe, 0x0, 0x7f, 0x80, 0x8f, 0xe0, 0xf8, 0xf8, + 0x7f, 0x1f, 0x7f, 0xf3, 0xdf, 0xfc, 0xf7, 0xff, + 0x3d, 0xff, 0xc0, 0xfe, 0xf8, 0x3f, 0xbe, 0xf, + 0xe7, 0x83, 0xf1, 0xe0, + + /* U+E583 "" */ + 0x7f, 0xbf, 0xf0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xff, 0xfb, 0xfe, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0x1, + + /* U+E584 "" */ + 0x7c, 0x3e, 0xfe, 0x7f, 0x0, 0x0, 0x0, 0x0, + 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xf6, 0x7b, + 0xf6, 0x7b, 0xf6, 0x7b, 0xfe, 0x7f, 0xfe, 0x7f, + 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0x82, 0x41, + + /* U+E585 "" */ + 0x40, 0x0, 0xb2, 0x1, 0x3d, 0x80, 0x6f, 0x67, + 0x9b, 0xd9, 0xe6, 0xf6, 0x79, 0xbc, 0x9e, 0x4d, + 0xf, 0xc2, 0x3, 0x30, 0x0, 0xcc, 0x0, 0x7f, + 0x80, 0x18, 0x60, 0xc, 0xc, 0x3, 0xff, 0x1, + 0x80, 0x60, 0x60, 0x18, + + /* U+E586 "" */ + 0x3, 0x0, 0x3f, 0x3, 0xff, 0x1f, 0xfe, 0x70, + 0x38, 0xc0, 0xc3, 0xff, 0xf, 0xfc, 0x18, 0x60, + 0x73, 0x81, 0xfe, 0x5, 0xe8, 0x1c, 0xe0, 0xe1, + 0xcf, 0xff, 0xff, 0xff, + + /* U+E587 "" */ + 0x0, 0x7e, 0x40, 0x7, 0xec, 0x3c, 0x7e, 0xc7, + 0xe6, 0x7f, 0x7e, 0x67, 0xf7, 0xe7, 0xff, 0xfe, + 0x67, 0x3f, 0xe6, 0x73, 0xfe, 0x7f, 0xf7, 0xc6, + 0x73, 0x18, 0x67, 0x31, 0x87, 0xff, 0x18, 0x7f, + 0xf1, 0x87, 0xff, 0x18, 0x7f, 0xf1, 0x87, 0xff, + + /* U+E589 "" */ + 0x0, 0x7, 0x0, 0x7, 0xc0, 0x7, 0xe0, 0x7, + 0xf0, 0x3, 0xf0, 0x1, 0xf0, 0x1, 0xf0, 0x21, + 0xc0, 0x39, 0xc0, 0x1f, 0xc0, 0xf, 0xc0, 0xf, + 0xe0, 0x7, 0xf8, 0x3, 0xfe, 0x3, 0xfe, 0x1, + 0xf8, 0x0, 0xe0, 0x0, 0x0, + + /* U+E58A "" */ + 0x6, 0x0, 0x1e, 0x0, 0x3e, 0x0, 0xff, 0xff, + 0xff, 0xff, 0x3e, 0x0, 0x1e, 0x0, 0x6, 0x7f, + 0x0, 0x7f, 0x0, 0x7f, 0x0, 0x7f, 0x0, 0x0, + 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, 0xfb, 0xff, + + /* U+E58B "" */ + 0x7f, 0xf0, 0x3f, 0xfe, 0xf, 0xff, 0x83, 0xf3, + 0xfc, 0xfe, 0x7f, 0xb8, 0xe, 0x7f, 0xe7, 0x8f, + 0xf3, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xcf, 0xcf, 0x63, 0xf3, 0x8c, 0x84, 0xc1, + 0xc0, 0xe0, + + /* U+E58C "" */ + 0x7f, 0xf0, 0x3f, 0xfe, 0xf, 0xff, 0x83, 0xf3, + 0xfc, 0xf8, 0xff, 0xbe, 0x1e, 0x7f, 0x87, 0x8f, + 0xe3, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xcf, 0xcf, 0x73, 0xf3, 0x84, 0x84, 0xc1, + 0xc0, 0xe0, + + /* U+E58D "" */ + 0x3f, 0xe0, 0x7, 0xff, 0xe0, 0x7f, 0xfe, 0xf, + 0xff, 0x30, 0xff, 0xf3, 0xf, 0xff, 0x38, 0xff, + 0xff, 0xef, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, + 0xff, 0x73, 0xfc, 0xe3, 0x20, 0xcc, 0x32, 0xc, + 0xc1, 0xc0, 0x78, + + /* U+E58E "" */ + 0x3f, 0xe0, 0xf, 0xff, 0xc1, 0xff, 0xf8, 0x75, + 0x59, 0x8e, 0xa3, 0x31, 0xd4, 0x67, 0x38, 0xaf, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xef, 0xff, 0xfd, + 0xcf, 0xf3, 0x99, 0x86, 0x63, 0x20, 0xcc, 0x38, + 0xf, 0x0, + + /* U+E58F "" */ + 0x6, 0x0, 0x0, 0x70, 0x0, 0x7, 0x0, 0x0, + 0x70, 0x0, 0x7, 0x3f, 0xe0, 0xf3, 0xff, 0x1f, + 0x7f, 0xf3, 0xf7, 0x7, 0x7f, 0x70, 0x77, 0xf7, + 0x7, 0xff, 0x7f, 0xfe, 0x76, 0xfb, 0x8f, 0x7f, + 0xf1, 0xf3, 0xfe, 0x3f, 0xb0, 0x63, 0x8b, 0x6, + + /* U+E591 "" */ + 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0x0, 0x19, 0xe6, 0xf, 0x7b, 0xc1, 0x8c, 0x60, + 0x0, 0x0, 0x39, 0xe7, 0x1c, 0xfc, 0xe7, 0x3f, + 0x39, 0xcf, 0xce, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xff, 0xfc, + + /* U+E592 "" */ + 0x0, 0xc0, 0x6, 0x79, 0x83, 0xde, 0xf0, 0x63, + 0x18, 0x0, 0x0, 0x6, 0x79, 0x3, 0x3f, 0x31, + 0xcf, 0xce, 0x73, 0xf3, 0x80, 0x0, 0x0, 0x0, + 0x3, 0xff, 0xff, + + /* U+E593 "" */ + 0xc0, 0x0, 0x7c, 0x0, 0x18, 0x80, 0x2, 0x0, + 0x0, 0x0, 0x8e, 0x20, 0x3b, 0xee, 0x7, 0x39, + 0xc0, 0xc2, 0x10, 0x0, 0x0, 0x3, 0x3e, 0x60, + 0xef, 0xee, 0x39, 0xfc, 0xe7, 0x3f, 0x9c, 0x0, + 0x0, 0x0, 0x0, 0x1, 0x0, 0x4, 0x60, 0x0, + 0xf8, 0x0, 0xc, + + /* U+E594 "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xf3, 0xff, 0xd8, + 0x6f, 0xf2, 0x13, 0xfc, 0xcc, 0xff, 0x3f, 0x3f, + 0xf8, 0x7f, 0xfe, 0x1b, 0xfb, 0x2, 0x7e, 0xc0, + 0x9f, 0xb0, 0x27, 0xff, 0xff, 0xdf, 0xff, 0xe0, + + /* U+E595 "" */ + 0x7c, 0xf, 0xb0, 0x0, 0x3c, 0x0, 0xf, 0x0, + 0x3, 0x8, 0xc4, 0x7, 0x7b, 0x81, 0xcc, 0xe0, + 0x20, 0x10, 0x9, 0xe0, 0x6, 0xfd, 0x81, 0xbf, + 0x60, 0x6f, 0xd8, 0xc0, 0x0, 0xf0, 0x0, 0x3c, + 0x0, 0xd, 0xf0, 0x3e, + + /* U+E596 "" */ + 0xff, 0x81, 0xff, 0x1, 0x8c, 0x3, 0x18, 0x6, + 0x30, 0xc, 0x60, 0x1f, 0xc0, 0x3f, 0x0, 0x7c, + 0xf8, 0xf3, 0xf9, 0xef, 0xfb, 0xdf, 0x77, 0xb5, + 0xef, 0x73, 0xce, 0xff, 0x8c, 0xfe, 0x0, 0xf8, + + /* U+E597 "" */ + 0xff, 0x80, 0xff, 0x80, 0x63, 0x0, 0x63, 0x0, + 0x63, 0x0, 0x63, 0x0, 0x7f, 0x0, 0x7c, 0x30, + 0x7d, 0x32, 0x7d, 0xfe, 0x78, 0xbc, 0x7b, 0xbf, + 0x7b, 0xf7, 0x78, 0xe6, 0x3d, 0xfe, 0x1d, 0x32, + 0x0, 0x30, + + /* U+E598 "" */ + 0x0, 0xd, 0x80, 0xf, 0x60, 0x3, 0xd8, 0x0, + 0x7e, 0xc0, 0x67, 0xb0, 0xe, 0xfc, 0x1, 0xef, + 0xc1, 0xbc, 0x80, 0x7b, 0xe0, 0xf, 0xb8, 0xf0, + 0xf3, 0x77, 0x1f, 0x8e, 0xf1, 0xfb, 0xde, 0x7f, + 0x7b, 0xdd, 0xef, 0xff, 0x1c, 0xef, 0x40, 0x1f, + 0xc0, 0x0, 0xf0, + + /* U+E599 "" */ + 0x0, 0xf8, 0x7, 0xf0, 0x1d, 0xc0, 0x7f, 0x1, + 0xfc, 0xf3, 0xf7, 0xe3, 0xff, 0xcf, 0xe7, 0x3f, + 0x9c, 0xfe, 0x73, 0xf9, 0xcf, 0xe7, 0x3f, 0x9f, + 0xfe, 0x3f, 0xb8, 0x7c, + + /* U+E59A "" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xcd, 0x8b, 0x3f, 0xdf, 0xbf, 0x78, + 0xf1, 0xe7, 0x8f, 0x1e, 0xfd, 0xfb, 0xfc, 0xd1, + 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0xff, 0xff, 0xff, + + /* U+E59C "" */ + 0xe, 0x7, 0x81, 0xe0, 0x38, 0x0, 0x7, 0x83, + 0xf1, 0xfe, 0x7f, 0xf7, 0xf3, 0xf0, 0xfe, 0x1f, + 0x7, 0xc1, 0xf0, 0x8, + + /* U+E59D "" */ + 0xe, 0x1, 0xc0, 0x38, 0x67, 0x3e, 0xe, 0xe3, + 0x8f, 0xe0, 0xf8, 0x1f, 0x3, 0xe0, 0x7c, 0xf, + 0x81, 0xb0, 0x36, 0x6, 0xc0, 0xd8, + + /* U+E5A0 "" */ + 0x7f, 0x0, 0x7f, 0xc0, 0x3f, 0xb0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xff, 0xc3, 0xff, 0xe1, 0xff, + 0x80, 0xff, 0xbc, 0x7f, 0xbf, 0xbf, 0xbf, 0x5f, + 0xdf, 0x3f, 0xec, 0xbf, 0xf7, 0x3f, 0xfb, 0xfc, + 0xfe, 0xfe, 0x0, 0x3c, 0x0, + + /* U+E5A1 "" */ + 0x7f, 0x0, 0x7f, 0xc0, 0x3f, 0xf0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xff, 0xc3, 0xff, 0xe1, 0xff, + 0x80, 0xff, 0xbe, 0x7f, 0xbf, 0xbf, 0xb3, 0x7f, + 0xdc, 0x7f, 0xef, 0x3f, 0xf7, 0x1f, 0xfb, 0x36, + 0xfc, 0xfe, 0x0, 0x3e, 0x0, + + /* U+E5A9 "" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x60, 0x3d, + 0xc6, 0x3, 0xdc, 0xe0, 0x3d, 0xfc, 0x3, 0xc7, + 0x80, 0x3c, 0xf8, 0x3, 0xcf, 0xc0, 0x3c, 0xff, + 0x83, 0xcd, 0xfc, 0x3c, 0xcc, 0x63, 0xff, 0xe7, + 0xff, 0xff, 0x7f, 0x0, 0x30, 0x0, 0x1, 0x0, + + /* U+E5AA "" */ + 0x0, 0x78, 0x0, 0xfc, 0x1, 0xcc, 0x1, 0x8c, + 0x1f, 0x8e, 0x3f, 0x9f, 0x33, 0x9f, 0x71, 0x9f, + 0x71, 0x8e, 0x71, 0x84, 0xf9, 0x80, 0xf9, 0x80, + 0xf9, 0x80, 0x71, 0x80, 0x21, 0x80, 0x1, 0x80, + 0x1, 0x80, 0x1, 0x80, + + /* U+E5AF "" */ + 0x0, 0x0, 0x1, 0xf8, 0x0, 0x3f, 0xe0, 0x7, + 0xff, 0x80, 0xff, 0xfe, 0xf, 0xff, 0xf8, 0x3f, + 0xff, 0xe3, 0xf, 0xff, 0x30, 0x3, 0xf3, 0xff, + 0xff, 0x3f, 0xff, 0xf0, 0x0, 0x3f, 0x7f, 0xff, + 0xf7, 0xff, 0xff, + + /* U+E5B4 "" */ + 0xff, 0xfc, 0x63, 0x6, 0x3, 0xfc, 0x7f, 0xe6, + 0x6, 0x60, 0x66, 0x6, 0x7f, 0xe7, 0xfe, 0x66, + 0x66, 0x66, 0x7f, 0xe3, 0xfc, 0x60, 0x64, 0x3, + 0xc0, 0x30, + + /* U+E678 "" */ + 0x7f, 0xf8, 0x3f, 0xff, 0xf, 0xff, 0xc3, 0xff, + 0xf0, 0xff, 0xf0, 0x3f, 0xf9, 0xcc, 0xce, 0xdb, + 0x33, 0xb6, 0xcc, 0xed, 0xb3, 0x37, 0xfc, 0xcd, + 0xff, 0x33, 0x7f, 0xff, 0xdf, 0xdf, 0xf7, 0xf0, + 0x1, 0xfc, + + /* U+E67A "" */ + 0x7f, 0xf8, 0x3f, 0xff, 0xf, 0xc0, 0xc3, 0xf0, + 0x30, 0xff, 0xf0, 0x3f, 0xf9, 0xcf, 0xc0, 0xdb, + 0xf0, 0x36, 0xff, 0xcd, 0xbf, 0xf7, 0xff, 0xc1, + 0xff, 0xf0, 0x7f, 0xff, 0xdf, 0xdf, 0xf7, 0xf0, + 0x1, 0xfc, + + /* U+E682 "" */ + 0x0, 0xe0, 0x0, 0xe, 0x0, 0x0, 0xe0, 0xe, + 0xe, 0x7, 0xe1, 0xf0, 0x7f, 0x3f, 0x8f, 0x3f, + 0xff, 0xc3, 0xff, 0xfc, 0x1f, 0xff, 0x81, 0xff, + 0xf8, 0x1f, 0xff, 0x80, 0xff, 0xf0, 0xf, 0xff, + 0x0, 0x7f, 0xe0, 0x7, 0xfe, 0x0, + + /* U+E68F "" */ + 0xc0, 0x0, 0x39, 0xff, 0x7, 0x3f, 0xc0, 0xef, + 0xc0, 0x1f, 0xf0, 0x3, 0xfc, 0x0, 0x7f, 0x0, + 0xf, 0xe0, 0x9, 0xfc, 0x7, 0x3f, 0x81, 0xe7, + 0xe0, 0x7c, 0xf8, 0x0, 0x1c, 0x0, 0x3, 0x80, + 0xc, 0x70, 0x3, 0xe, 0x0, 0xc1, 0xc0, 0x30, + 0x30, + + /* U+E691 "" */ + 0x7f, 0xf8, 0x3f, 0xff, 0xf, 0xff, 0xc3, 0xff, + 0xf0, 0xff, 0xf0, 0x3f, 0xf9, 0xcc, 0xce, 0xdb, + 0x33, 0xb0, 0xcc, 0xec, 0x33, 0x37, 0xfc, 0xcd, + 0xff, 0x33, 0x7f, 0xff, 0xdf, 0xdf, 0xf7, 0xf0, + 0x1, 0xfc, + + /* U+E695 "" */ + 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x1, 0x80, + 0x1, 0x80, 0x3, 0xc0, 0x3f, 0xfc, 0x63, 0xc6, + 0x61, 0x86, 0x61, 0x86, 0xf3, 0xcf, 0xf3, 0xcf, + 0xf3, 0xcf, 0xf3, 0xcf, + + /* U+E696 "" */ + 0x7, 0xe0, 0x3, 0xff, 0x0, 0xff, 0xf8, 0x3f, + 0xff, 0x7, 0xff, 0xf1, 0xff, 0xfe, 0x3f, 0xfe, + 0x7, 0xff, 0x80, 0xff, 0xe6, 0x1f, 0xfd, 0xe1, + 0xff, 0xbc, 0x3f, 0xe7, 0x7, 0xf0, 0x80, 0xfe, + 0x71, 0xfc, 0x1f, 0xfe, 0x1, 0xc7, 0x0, 0x0, + 0x0, + + /* U+E697 "" */ + 0x3e, 0x7, 0xfc, 0x3f, 0xf1, 0xfd, 0xcf, 0xe7, + 0x7f, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xff, 0xf3, 0xff, 0x9f, 0xfc, 0xff, 0xe7, + 0xdf, 0x3e, + + /* U+E698 "" */ + 0x3e, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, + 0xc, 0x3, 0xc0, 0x30, 0x0, 0xdd, 0xb5, 0xda, + + /* U+E699 "" */ + 0x3, 0x0, 0x1e, 0x0, 0x78, 0x18, 0xc6, 0xf3, + 0x3f, 0xcc, 0xf7, 0xf7, 0x99, 0xe6, 0x67, 0x99, + 0xef, 0xef, 0x33, 0xfc, 0xcf, 0x63, 0x18, 0x1e, + 0x0, 0x78, 0x0, 0xc0, + + /* U+E69A "" */ + 0x3, 0x0, 0x1, 0xe0, 0x0, 0x78, 0x1, 0x8c, + 0x20, 0xf3, 0x1c, 0x3c, 0xcf, 0x7, 0xf2, 0x1, + 0x9e, 0x3c, 0x67, 0xbf, 0x9e, 0xef, 0x7f, 0x37, + 0x9f, 0xcd, 0xc3, 0x63, 0x79, 0xc1, 0xed, 0xf0, + 0x7b, 0xf8, 0xc, 0x3c, + + /* U+E69B "" */ + 0x7f, 0xfb, 0xff, 0xfe, 0x13, 0xfa, 0x6f, 0xe9, + 0xbf, 0x86, 0xff, 0xff, 0xfd, 0xc7, 0xf6, 0x1f, + 0xfb, 0x7f, 0xed, 0xff, 0xc7, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+E790 "" */ + 0x0, 0xc0, 0x0, 0xfc, 0x0, 0x7f, 0x80, 0x3f, + 0xf0, 0x3f, 0xff, 0x1f, 0xff, 0xef, 0xff, 0xfd, + 0xff, 0xfe, 0x7f, 0xff, 0x9f, 0xff, 0xe3, 0xff, + 0xf0, 0xff, 0xfc, 0x3f, 0xff, 0x7, 0xff, 0x81, + 0xff, 0xe0, 0x3f, 0xf0, + + /* U+E807 "" */ + 0xc, 0x3, 0x7, 0xf8, 0xfc, 0x3f, 0x1f, 0xe0, + 0xc0, 0x78, 0x3f, 0x1c, 0xee, 0x1f, 0x3, 0xc0, + 0xf0, 0x3e, 0x1d, 0x86, 0x3f, 0x7, 0x80, + + /* U+E80A "" */ + 0x18, 0x0, 0x38, 0x0, 0x31, 0xf0, 0x67, 0xfc, + 0x6e, 0xe, 0xcc, 0xe6, 0xd9, 0xf3, 0xd9, 0xb3, + 0xd9, 0xb3, 0xd8, 0x33, 0xfc, 0x67, 0x6f, 0xe6, + 0x77, 0xce, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+E816 "" */ + 0x7, 0xf8, 0x3, 0xff, 0x0, 0xff, 0xc0, 0x3f, + 0xf0, 0x6f, 0xfd, 0xb3, 0xff, 0x3c, 0xff, 0xcd, + 0xbf, 0xf6, 0x6f, 0xfd, 0xb3, 0xff, 0x3c, 0xff, + 0xcd, 0xbf, 0xf6, 0xf, 0xfc, 0x3, 0x87, 0x0, + 0xe1, 0xc0, 0x1f, 0xe0, + + /* U+E81B "" */ + 0x39, 0xee, 0x30, 0xfb, 0xff, 0xff, 0xfd, 0xe0, + + /* U+E81C "" */ + 0x7b, 0xff, 0xff, 0xfd, 0xf0, 0xc7, 0x79, 0xc0, + + /* U+E81D "" */ + 0x7f, 0xff, 0x8f, 0xff, 0xfe, 0xc3, 0xc, 0x6c, + 0x30, 0xc3, 0xc3, 0xc, 0x3c, 0x30, 0xc3, 0xc3, + 0xc, 0x3f, 0xff, 0xc3, 0xff, 0xfc, 0x3f, 0xff, + 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, + 0xf7, 0x3f, 0xce, 0x33, 0xc, 0xc1, 0xe0, 0x78, + + /* U+E820 "" */ + 0x0, 0xc0, 0x0, 0xfe, 0x1, 0xff, 0xe0, 0xff, + 0xfc, 0x3f, 0xff, 0x1f, 0xff, 0xe7, 0xff, 0xf9, + 0xff, 0xfe, 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xff, + 0xfd, 0xff, 0xfe, 0x7f, 0xff, 0x8f, 0xff, 0xc1, + 0xff, 0xe0, 0x3f, 0xf0, 0x7, 0xf8, 0x0, + + /* U+F000 "" */ + 0xff, 0xff, 0xff, 0xff, 0x70, 0xe, 0x38, 0x1c, + 0x1c, 0x38, 0xe, 0x70, 0x7, 0xe0, 0x3, 0xc0, + 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, + 0x1, 0x80, 0xf, 0xf0, 0xf, 0xf0, + + /* U+F001 "" */ + 0x0, 0xe, 0x3, 0xfc, 0x3f, 0xf8, 0x7f, 0xf0, + 0xff, 0xe1, 0xf0, 0xc3, 0x1, 0x86, 0x3, 0xc, + 0x3e, 0x18, 0xfd, 0xf1, 0xff, 0xe3, 0xff, 0xc3, + 0xdf, 0x80, 0x1e, 0x0, 0x0, + + /* U+F002 "" */ + 0xf, 0x80, 0x3f, 0xe0, 0x70, 0x70, 0x60, 0x30, + 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, + 0xc0, 0x18, 0x60, 0x30, 0x70, 0x70, 0x3f, 0xf8, + 0xf, 0x9c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, + + /* U+F003 "" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, + 0x1f, 0xf8, 0xcf, 0xf3, 0xe3, 0xc7, 0xf1, 0x8f, + 0xf8, 0x1f, 0xfe, 0x7f, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F004 "" */ + 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, + 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf0, + 0x7, 0xe0, 0x1, 0x80, + + /* U+F005 "" */ + 0x0, 0xc0, 0x0, 0x30, 0x0, 0x1e, 0x0, 0x7, + 0x80, 0x3, 0xf0, 0xf, 0xff, 0xcf, 0xff, 0xfd, + 0xff, 0xfe, 0x3f, 0xff, 0x7, 0xff, 0x80, 0xff, + 0xc0, 0x3f, 0xf0, 0xf, 0xfc, 0x3, 0xff, 0x0, + 0xf3, 0xc0, 0x70, 0x38, + + /* U+F006 "" */ + 0x0, 0xc0, 0x0, 0x30, 0x0, 0x1e, 0x0, 0x7, + 0x80, 0x3, 0xf0, 0xf, 0xff, 0xcf, 0xff, 0xfd, + 0xff, 0xfe, 0x3f, 0xff, 0x7, 0xff, 0x80, 0xff, + 0xc0, 0x3f, 0xf0, 0xf, 0xfc, 0x3, 0xff, 0x0, + 0xf3, 0xc0, 0x70, 0x38, + + /* U+F007 "" */ + 0x7, 0x0, 0xfe, 0x7, 0xf0, 0x3f, 0x81, 0xfc, + 0xf, 0xe0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0xfe, + 0xf, 0xf8, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xe0, + + /* U+F008 "" */ + 0x7f, 0xfb, 0xff, 0xfc, 0xfe, 0xf3, 0xfb, 0xff, + 0xff, 0xff, 0xfc, 0xfe, 0xf3, 0xfb, 0xff, 0xff, + 0xff, 0xfc, 0xfe, 0xf3, 0xfb, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F009 "" */ + 0x7f, 0xfb, 0xff, 0xfc, 0x30, 0xf0, 0xc3, 0xc3, + 0xf, 0xc, 0x3f, 0xff, 0xff, 0xff, 0xc3, 0xf, + 0xc, 0x3c, 0x30, 0xf0, 0xc3, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F00A "" */ + 0x7f, 0xfb, 0xff, 0xfc, 0xcc, 0xf3, 0x33, 0xff, + 0xff, 0xff, 0xfc, 0xcc, 0xf3, 0x33, 0xff, 0xff, + 0xff, 0xfc, 0xcc, 0xf3, 0x33, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F00B "" */ + 0x7f, 0xfb, 0xff, 0xfc, 0xc0, 0xf3, 0x3, 0xff, + 0xff, 0xff, 0xfc, 0xc0, 0xf3, 0x3, 0xff, 0xff, + 0xff, 0xfc, 0xc0, 0xf3, 0x3, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F00C "" */ + 0x0, 0xc, 0x0, 0x70, 0x1, 0x80, 0xc, 0x0, + 0x70, 0x3, 0x80, 0xc, 0x30, 0x70, 0xe3, 0x81, + 0xcc, 0x3, 0xe0, 0x7, 0x80, 0xc, 0x0, + + /* U+F00D "" */ + 0xc0, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, 0x80, + 0xf0, 0xf, 0x1, 0xf8, 0x39, 0xc7, 0xe, 0xe0, + 0x7c, 0x3, + + /* U+F00E "" */ + 0xf, 0x80, 0x3f, 0xe0, 0x7f, 0xf0, 0x7d, 0xf0, + 0xfd, 0xf8, 0xf0, 0x78, 0xf0, 0x78, 0xf0, 0x78, + 0xfd, 0xf8, 0x7d, 0xf0, 0x7f, 0xf0, 0x3f, 0xf0, + 0xf, 0x9c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, + + /* U+F010 "" */ + 0xf, 0x80, 0x3f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf0, + 0xff, 0xf8, 0xff, 0xf8, 0xf0, 0x78, 0xff, 0xf8, + 0xff, 0xf8, 0x7f, 0xf0, 0x7f, 0xf0, 0x3f, 0xf8, + 0xf, 0x9c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, + + /* U+F011 "" */ + 0x1, 0x80, 0x1, 0x80, 0x19, 0x98, 0x39, 0x9c, + 0x71, 0x8e, 0x61, 0x86, 0xe1, 0x87, 0xc1, 0x83, + 0xc1, 0x83, 0xc1, 0x83, 0xc0, 0x3, 0xe0, 0x7, + 0x60, 0x6, 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, + 0x7, 0xe0, + + /* U+F012 "" */ + 0x0, 0x6, 0x0, 0xc, 0x0, 0x18, 0x1, 0xb0, + 0x3, 0x60, 0x6, 0xc0, 0xcd, 0x81, 0x9b, 0x3, + 0x36, 0x36, 0x6c, 0x6c, 0xde, 0xd9, 0xbd, 0xb3, + 0x7b, 0x66, 0xc0, + + /* U+F013 "" */ + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x77, 0xee, + 0x7f, 0xff, 0xff, 0xff, 0x7e, 0x7e, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff, + 0x7f, 0xff, 0x77, 0xee, 0x3, 0xc0, 0x3, 0xc0, + 0x3, 0xc0, + + /* U+F014 "" */ + 0x7, 0x80, 0x3f, 0xf, 0xff, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x9f, 0xfe, 0x6c, 0xd9, + 0xb3, 0x66, 0xcd, 0x9b, 0x36, 0x6c, 0xd9, 0xb3, + 0x66, 0xcd, 0x9f, 0xfe, 0x3f, 0xf0, + + /* U+F015 "" */ + 0x0, 0x80, 0x0, 0xe0, 0x1, 0xfc, 0x1, 0xff, + 0x1, 0xff, 0xc1, 0xff, 0xf1, 0xff, 0xfd, 0xff, + 0xff, 0x7f, 0xff, 0x1f, 0xff, 0xf, 0x8f, 0x87, + 0xc7, 0xc3, 0xe3, 0xe1, 0xf1, 0xf0, 0xf8, 0xf8, + 0x3f, 0xf8, + + /* U+F016 "" */ + 0x3e, 0x7, 0xfc, 0x3f, 0xf1, 0xfd, 0xcf, 0xe7, + 0x7f, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xcf, 0xfe, + + /* U+F017 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7e, 0x7e, + 0x7e, 0x7e, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, + 0xfe, 0x3f, 0xff, 0x8f, 0xff, 0xef, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F018 "" */ + 0x1e, 0x78, 0x1e, 0x78, 0x3e, 0x7c, 0x3f, 0xfc, + 0x3f, 0xfc, 0x3e, 0x7c, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7f, 0xfe, 0xff, 0xff, 0xfe, 0x7f, + 0xfe, 0x7f, 0xfe, 0x7f, + + /* U+F019 "" */ + 0x3, 0x0, 0xc, 0x0, 0x30, 0x0, 0xc0, 0x3, + 0x0, 0xc, 0x1, 0xb6, 0x7, 0xf8, 0xf, 0xc0, + 0x1e, 0x7, 0x33, 0xbe, 0x1f, 0xff, 0xef, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F01A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0x7e, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F01B "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0x7e, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F01C "" */ + 0x3f, 0xfc, 0x7f, 0xfe, 0x60, 0x6, 0x60, 0x6, + 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, + 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, + + /* U+F01D "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7d, 0xfe, 0xfc, 0x7f, 0xfc, 0x3f, 0xfc, 0x1f, + 0xfc, 0x1f, 0xfc, 0x3f, 0xfc, 0x7f, 0x7d, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F01E "" */ + 0x0, 0x0, 0x1, 0xf8, 0xc3, 0xff, 0x63, 0x81, + 0xf3, 0x0, 0x79, 0x80, 0xfd, 0x80, 0x7e, 0xc0, + 0x0, 0x60, 0x0, 0x30, 0x0, 0x18, 0x0, 0xc, + 0x0, 0x7, 0x0, 0x21, 0x80, 0x30, 0x70, 0x38, + 0x1f, 0xf8, 0x7, 0xf0, 0x0, 0x0, 0x0, + + /* U+F021 "" */ + 0x7, 0xe3, 0x1f, 0xfb, 0x3c, 0x3f, 0x70, 0xf, + 0x60, 0x3f, 0xe0, 0x3f, 0xc0, 0x0, 0xc0, 0x0, + 0x0, 0x3, 0x0, 0x3, 0xfc, 0x7, 0xfc, 0x6, + 0xf0, 0xe, 0xfc, 0x3c, 0xdf, 0xf8, 0xc7, 0xe0, + + /* U+F022 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x7, + 0xe6, 0x7, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x7, + 0xe6, 0x7, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F023 "" */ + 0xf, 0x1, 0xf8, 0x39, 0xc3, 0xc, 0x30, 0xc3, + 0xc, 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xe0, + + /* U+F024 "" */ + 0xc0, 0x3, 0x7c, 0x3f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xf0, 0x18, 0xc0, 0x3, 0x0, + 0xc, 0x0, 0x30, 0x0, + + /* U+F025 "" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0x6, 0xe0, + 0x1f, 0x0, 0x3c, 0x0, 0xf0, 0x3, 0xf8, 0x7f, + 0xe1, 0xff, 0x87, 0xfe, 0x1f, 0xf8, 0x7f, 0xe1, + 0xf7, 0x87, 0x80, + + /* U+F026 "" */ + 0x1, 0x81, 0xc1, 0xe1, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xc3, 0xe0, 0xf0, 0x38, 0xc, + + /* U+F027 "" */ + 0x1, 0x80, 0x1c, 0x1, 0xe0, 0x1f, 0xf, 0xf8, + 0x7f, 0xdb, 0xfe, 0x7f, 0xf3, 0xff, 0xbf, 0xfc, + 0x3, 0xe0, 0xf, 0x0, 0x38, 0x0, 0xc0, + + /* U+F028 "" */ + 0x1, 0x83, 0x0, 0x70, 0x30, 0x1e, 0x26, 0x7, + 0xc7, 0x6f, 0xf8, 0x67, 0xff, 0x66, 0xff, 0xe6, + 0xdf, 0xfc, 0xdb, 0xff, 0xb3, 0x7f, 0xf0, 0xcc, + 0x3e, 0x3b, 0x3, 0xc4, 0xe0, 0x38, 0x18, 0x3, + 0x6, 0x0, + + /* U+F029 "" */ + 0xfc, 0xff, 0xf3, 0xfc, 0xcc, 0xf3, 0x33, 0xfc, + 0xff, 0xf3, 0xf0, 0x0, 0x0, 0x0, 0xfc, 0xcf, + 0xf3, 0x3c, 0xc3, 0x33, 0xc, 0xfc, 0xcf, 0xf3, + 0x30, + + /* U+F02A "" */ + 0xdb, 0x6f, 0x6d, 0xbd, 0xb6, 0xf6, 0xdb, 0xdb, + 0x6f, 0x6d, 0xbd, 0xb6, 0xf6, 0xdb, 0xdb, 0x6f, + 0x6d, 0xbd, 0xb6, 0xf6, 0xdb, 0xdb, 0x6f, 0x6d, + 0xb0, + + /* U+F02B "" */ + 0x7f, 0x1, 0xff, 0x3, 0x9f, 0x7, 0x3f, 0xf, + 0xff, 0x9f, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x7f, + 0xfe, 0x7f, 0xf8, 0x7f, 0xe0, 0x7f, 0x80, 0x3e, + 0x0, 0x38, 0x0, + + /* U+F02C "" */ + 0x7f, 0x10, 0x7f, 0xcc, 0x3f, 0xf3, 0x1c, 0xfc, + 0xcf, 0xff, 0x37, 0xff, 0xdf, 0xff, 0xe7, 0xff, + 0xf6, 0x3f, 0xf7, 0xf, 0xf3, 0x3, 0xf3, 0x0, + 0xf3, 0x0, 0x31, 0x0, + + /* U+F02D "" */ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x1f, 0xc0, 0x7f, 0xff, 0xfc, 0x7, 0xf0, 0x1f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1b, 0x0, + 0x6f, 0xff, 0xdf, 0xff, + + /* U+F02E "" */ + 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf0, 0xfc, 0x3, + + /* U+F02F "" */ + 0x1f, 0xf0, 0x3f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf, + 0x30, 0xc, 0x30, 0xc, 0x3f, 0xfc, 0x1f, 0xf8, + + /* U+F030 "" */ + 0x7, 0xe0, 0xf, 0xf0, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, + + /* U+F031 "" */ + 0x1, 0x0, 0x7, 0x0, 0xe, 0x0, 0x3e, 0x0, + 0x6c, 0x0, 0xdc, 0x3, 0x18, 0x6, 0x30, 0x1c, + 0x70, 0x3f, 0xe0, 0xff, 0xe1, 0x80, 0xcf, 0x83, + 0xff, 0x7, 0xc0, + + /* U+F032 "" */ + 0xff, 0x8f, 0xfc, 0x30, 0xe3, 0x6, 0x30, 0x63, + 0xe, 0x3f, 0xc3, 0xfe, 0x30, 0x73, 0x3, 0x30, + 0x33, 0x7, 0xff, 0xef, 0xfc, + + /* U+F033 "" */ + 0xf, 0xf0, 0xff, 0x1, 0x80, 0x38, 0x3, 0x0, + 0x30, 0x6, 0x0, 0x60, 0xc, 0x0, 0xc0, 0x1c, + 0x1, 0x80, 0xff, 0xf, 0xf0, + + /* U+F034 "" */ + 0xff, 0xc3, 0x3f, 0xf1, 0xec, 0xcc, 0xff, 0x33, + 0x3f, 0xc, 0x3, 0x3, 0x0, 0xc0, 0xc0, 0x30, + 0x30, 0xc, 0xc, 0x3, 0x3, 0x0, 0xc0, 0xc0, + 0xfc, 0x30, 0x3f, 0x3f, 0x7, 0x8f, 0xc0, 0xc0, + + /* U+F035 "" */ + 0xff, 0xff, 0xff, 0xfc, 0x30, 0xf0, 0xc3, 0x3, + 0x0, 0xc, 0x0, 0x30, 0x3, 0xf0, 0xf, 0xc0, + 0x0, 0x0, 0x0, 0xc, 0xc, 0x70, 0x3b, 0xff, + 0xff, 0xff, 0xdc, 0xe, 0x30, 0x30, + + /* U+F036 "" */ + 0xff, 0x83, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0x83, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F037 "" */ + 0x1f, 0xe0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0xff, + 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x1f, 0xe0, + 0x7f, 0x80, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F038 "" */ + 0x7, 0xfc, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x7, 0xfc, + 0x1f, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F039 "" */ + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F03A "" */ + 0x40, 0x1, 0xdf, 0xff, 0xbf, 0xfa, 0x0, 0x0, + 0x0, 0x8, 0x0, 0x3b, 0xff, 0xf7, 0xff, 0x40, + 0x0, 0x0, 0x1, 0x0, 0x7, 0x7f, 0xfe, 0xff, + 0xe8, 0x0, 0x0, + + /* U+F03B "" */ + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x13, + 0xfc, 0xcf, 0xff, 0x0, 0x3c, 0x0, 0x33, 0xfc, + 0x4f, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F03C "" */ + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x83, + 0xff, 0x8f, 0xff, 0x0, 0x3c, 0x0, 0xe3, 0xfe, + 0xf, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F03D "" */ + 0x7f, 0xe0, 0x7f, 0xf8, 0x3f, 0xfc, 0xff, 0xfe, + 0xff, 0xff, 0x7f, 0xff, 0xbf, 0xff, 0xdf, 0xff, + 0xef, 0xff, 0xf7, 0xff, 0xf9, 0xff, 0xfc, 0xf, + 0xfc, 0x0, + + /* U+F03E "" */ + 0x7f, 0xfb, 0xff, 0xfe, 0x7f, 0xf9, 0xff, 0xe7, + 0xff, 0x9f, 0xff, 0xf7, 0xff, 0x8f, 0xf4, 0x1f, + 0x80, 0x7c, 0x0, 0xf0, 0x3, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F040 "" */ + 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x9f, + 0x1, 0xcf, 0x3, 0xe6, 0x7, 0xf0, 0xf, 0xf8, + 0x1f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0, 0x7f, 0x80, + 0x4f, 0x0, 0xce, 0x0, 0xfc, 0x0, 0xe0, 0x0, + + /* U+F041 "" */ + 0xf, 0x3, 0xfc, 0x7f, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe7, 0xfe, 0x7f, + 0xe3, 0xfc, 0x1f, 0x81, 0xf0, 0xf, 0x0, 0x60, + + /* U+F042 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0x3c, 0x7f, 0xe, + 0x7f, 0x6, 0xff, 0x7, 0xff, 0x3, 0xff, 0x3, + 0xff, 0x3, 0xff, 0x3, 0xff, 0x7, 0x7f, 0x6, + 0x7f, 0xe, 0x3f, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F043 "" */ + 0x6, 0x0, 0xf0, 0xf, 0x1, 0xf8, 0x3f, 0xc3, + 0xfc, 0x7f, 0xe7, 0xfe, 0xff, 0xff, 0xff, 0xdf, + 0xfc, 0xff, 0xe7, 0xe7, 0x1e, 0x3f, 0xc0, 0xf0, + + /* U+F044 "" */ + 0x0, 0x4, 0x0, 0xf, 0x7e, 0x7, 0xfe, 0x63, + 0xc0, 0xf0, 0xc1, 0xf8, 0xc3, 0xf8, 0xc7, 0xf0, + 0xc7, 0xe0, 0xc7, 0xcc, 0xcf, 0x8c, 0xcc, 0xc, + 0xc0, 0xc, 0xc0, 0xc, 0xff, 0xfc, 0x7f, 0xf8, + + /* U+F045 "" */ + 0x0, 0x18, 0x0, 0xe, 0x0, 0x7, 0x8e, 0x3f, + 0xef, 0x7f, 0xfe, 0x7f, 0xff, 0x3f, 0xfd, 0x9e, + 0x3c, 0xce, 0x1c, 0x63, 0xc, 0x31, 0x80, 0x18, + 0x20, 0xc, 0x1, 0x86, 0x0, 0xc3, 0xff, 0xe0, + 0xff, 0xe0, + + /* U+F046 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x9f, 0xfe, 0xff, 0xf3, 0xf9, 0x9f, 0xe4, 0xff, + 0xc7, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F047 "" */ + 0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, + 0x1, 0x80, 0x31, 0x8c, 0x71, 0x8e, 0xff, 0xff, + 0xff, 0xff, 0x71, 0x8e, 0x31, 0x8c, 0x1, 0x80, + 0x7, 0xe0, 0x7, 0xe0, 0x3, 0xc0, 0x1, 0x80, + + /* U+F048 "" */ + 0xc0, 0x3c, 0xf, 0xc1, 0xfc, 0x7f, 0xcf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xc7, + 0xfc, 0x1f, 0xc0, 0xfc, 0x3, + + /* U+F049 "" */ + 0xc1, 0x83, 0xc3, 0x87, 0xc7, 0x8f, 0xcf, 0x9f, + 0xdf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xdf, 0xbf, 0xcf, 0x9f, 0xc7, 0x8f, + 0xc3, 0x87, 0xc1, 0x83, + + /* U+F04A "" */ + 0x3, 0x3, 0x7, 0x87, 0xf, 0x8f, 0x1f, 0x9f, + 0x3f, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xff, 0x3f, 0xbf, 0x1f, 0x9f, 0xf, 0x8f, + 0x7, 0x87, 0x3, 0x3, + + /* U+F04B "" */ + 0xc0, 0x7, 0x80, 0x3f, 0x1, 0xfe, 0xf, 0xfc, + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, + 0x3f, 0xc1, 0xf8, 0xf, 0x0, 0x60, 0x0, + + /* U+F04C "" */ + 0xf9, 0xff, 0x9f, 0xf9, 0xff, 0x9f, 0xf9, 0xff, + 0x9f, 0xf9, 0xff, 0x9f, 0xf9, 0xff, 0x9f, 0xf9, + 0xff, 0x9f, 0xf9, 0xff, 0x9f, + + /* U+F04D "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F04E "" */ + 0xc0, 0xc0, 0xe1, 0xe0, 0xf1, 0xf0, 0xf9, 0xf8, + 0xfd, 0xfc, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0xfd, 0xfc, 0xf9, 0xf8, 0xf1, 0xf0, + 0xe1, 0xe0, 0xc0, 0xc0, + + /* U+F050 "" */ + 0xc1, 0x83, 0xe1, 0xc3, 0xf1, 0xe3, 0xf9, 0xf3, + 0xfd, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xfb, 0xf9, 0xf3, 0xf1, 0xe3, + 0xe1, 0xc3, 0xc1, 0x83, + + /* U+F051 "" */ + 0xc0, 0x3f, 0x3, 0xf8, 0x3f, 0xe3, 0xff, 0x3f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfe, + 0x3f, 0x83, 0xf0, 0x3c, 0x3, + + /* U+F052 "" */ + 0x3, 0x0, 0x1e, 0x0, 0xfc, 0x7, 0xf8, 0x3f, + 0xf1, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F053 "" */ + 0x3, 0x7, 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xe0, + 0x70, 0x38, 0x1c, 0xe, 0x7, 0x3, + + /* U+F054 "" */ + 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x7, + 0xe, 0x1c, 0x38, 0x70, 0xe0, 0xc0, + + /* U+F055 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F056 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F057 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0x9f, 0xf8, 0x1f, 0xfc, 0x3f, + 0xfc, 0x3f, 0xf8, 0x1f, 0xf9, 0x9f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F058 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xcf, 0xff, 0xdf, 0xff, 0x9f, + 0xf3, 0x3f, 0xf2, 0x7f, 0xf8, 0xff, 0x7c, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F059 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfc, 0x3f, 0xfd, 0xbf, 0xfd, 0xbf, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F05A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfe, 0x7f, 0xff, 0xff, 0xfc, 0x7f, + 0xfc, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x7c, 0x3e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F05B "" */ + 0x0, 0x80, 0x0, 0xe0, 0x1, 0xfc, 0x1, 0xff, + 0x1, 0x89, 0xc1, 0x80, 0x70, 0xc0, 0x18, 0xe3, + 0x8e, 0xf9, 0xcf, 0xb8, 0xe3, 0x8c, 0x1, 0x86, + 0x1, 0xc1, 0xc9, 0xc0, 0x7f, 0xc0, 0x1f, 0xc0, + 0x3, 0x80, 0x0, 0x80, 0x0, + + /* U+F05C "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0x9f, 0xf8, 0x1f, 0xfc, 0x3f, + 0xfc, 0x3f, 0xf8, 0x1f, 0xf9, 0x9f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F05D "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xcf, 0xff, 0xdf, 0xff, 0x9f, + 0xf3, 0x3f, 0xf2, 0x7f, 0xf8, 0xff, 0x7c, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F05E "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x78, 0xe, + 0x7c, 0x6, 0xee, 0x7, 0xc7, 0x3, 0xc3, 0x83, + 0xc1, 0xc3, 0xc0, 0xe3, 0xe0, 0x77, 0x60, 0x3e, + 0x70, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F060 "" */ + 0x6, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x38, 0x0, + 0x70, 0x0, 0xff, 0xff, 0xff, 0xff, 0x70, 0x0, + 0x38, 0x0, 0x1c, 0x0, 0xe, 0x0, 0x6, 0x0, + + /* U+F061 "" */ + 0x0, 0x60, 0x0, 0x70, 0x0, 0x38, 0x0, 0x1c, + 0x0, 0xe, 0xff, 0xff, 0xff, 0xff, 0x0, 0xe, + 0x0, 0x1c, 0x0, 0x38, 0x0, 0x70, 0x0, 0x60, + + /* U+F062 "" */ + 0x6, 0x0, 0xf0, 0x1f, 0x83, 0xfc, 0x76, 0xee, + 0x67, 0xc6, 0x30, 0x60, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, + + /* U+F063 "" */ + 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, + 0x60, 0x6, 0x0, 0x60, 0x6, 0xc, 0x63, 0xe6, + 0x77, 0x6e, 0x3f, 0xc1, 0xf8, 0xf, 0x0, 0x60, + + /* U+F064 "" */ + 0x0, 0x0, 0x0, 0x60, 0x0, 0x70, 0x0, 0x78, + 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff, 0xff, 0xfe, + 0xff, 0xfc, 0xf0, 0x78, 0xe0, 0x70, 0xe0, 0x60, + 0x60, 0x0, 0x60, 0x0, 0x30, 0x0, + + /* U+F065 "" */ + 0xf8, 0x7f, 0xe1, 0xfc, 0x0, 0xf0, 0x3, 0xc0, + 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0x0, 0x3c, 0x0, 0xf0, 0x3, 0xf8, 0x7f, 0xe1, + 0xf0, + + /* U+F066 "" */ + 0x18, 0x60, 0x61, 0x81, 0x86, 0x3e, 0x1f, 0xf8, + 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xe1, 0xff, 0x87, 0xc6, 0x18, 0x18, 0x60, 0x61, + 0x80, + + /* U+F067 "" */ + 0x3, 0x0, 0xc, 0x0, 0x30, 0x0, 0xc0, 0x3, + 0x0, 0xc, 0xf, 0xff, 0xff, 0xff, 0x3, 0x0, + 0xc, 0x0, 0x30, 0x0, 0xc0, 0x3, 0x0, 0xc, + 0x0, + + /* U+F068 "" */ + 0xff, 0xff, 0xff, 0xf0, + + /* U+F069 "" */ + 0x3, 0x0, 0xc, 0x0, 0x30, 0x0, 0xc0, 0xe3, + 0x1d, 0xed, 0xe3, 0xff, 0x3, 0xf0, 0xf, 0xc0, + 0xff, 0xc7, 0xb7, 0xb8, 0xc7, 0x3, 0x0, 0xc, + 0x0, 0x30, 0x0, 0xc0, + + /* U+F06A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, + 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0x7e, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F06B "" */ + 0x1c, 0x38, 0x32, 0x4c, 0x33, 0xcc, 0x31, 0x8c, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x7e, 0x3e, 0x7c, + + /* U+F06C "" */ + 0x0, 0x3, 0x0, 0x7, 0x0, 0xf, 0x1, 0xff, + 0x7, 0xff, 0xf, 0xff, 0x8, 0x3f, 0x0, 0x3f, + 0xf, 0xff, 0x3f, 0xfe, 0x7f, 0xfe, 0x6f, 0xfc, + 0xc7, 0xf8, 0xc3, 0xe0, 0xc0, 0x0, + + /* U+F06D "" */ + 0x6, 0x0, 0x1e, 0x0, 0x7c, 0x81, 0xff, 0x83, + 0xff, 0x8f, 0xff, 0x1f, 0xff, 0x7d, 0xfe, 0xf9, + 0xfd, 0xe1, 0xbb, 0xc0, 0x77, 0x80, 0xef, 0x81, + 0xcf, 0x8f, 0x8f, 0xfe, 0xf, 0xf8, 0x7, 0xc0, + + /* U+F06E "" */ + 0x1, 0xf0, 0x1, 0xff, 0x80, 0x7c, 0x7c, 0x1e, + 0x3, 0xc7, 0xc6, 0x7c, 0xf0, 0xe7, 0xbe, 0x1c, + 0xff, 0xdf, 0x9f, 0x79, 0xf3, 0xcf, 0xbe, 0xf8, + 0xf0, 0x1e, 0xf, 0x8f, 0x80, 0xff, 0xe0, 0x7, + 0xf0, 0x0, + + /* U+F070 "" */ + 0xc0, 0x0, 0xc, 0x0, 0x0, 0xcf, 0xc0, 0xf, + 0xfe, 0x0, 0xf1, 0xf0, 0x4c, 0xf, 0x1c, 0xf9, + 0xf3, 0xcf, 0x9e, 0xf8, 0xf3, 0xff, 0xe, 0x7d, + 0xe0, 0xcf, 0x3e, 0xf, 0xe3, 0xc0, 0xf8, 0x3e, + 0xe, 0x1, 0xf8, 0xc0, 0xf, 0xcc, 0x0, 0x0, + 0xc0, 0x0, 0xc, + + /* U+F071 "" */ + 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x7, 0xe0, + 0x7, 0xe0, 0xe, 0x70, 0xe, 0x70, 0x1e, 0x78, + 0x1e, 0x78, 0x3e, 0x7c, 0x3f, 0xfc, 0x7e, 0x7e, + 0x7e, 0x7e, 0xff, 0xff, 0xff, 0xff, + + /* U+F072 "" */ + 0x6, 0x0, 0x1, 0xc0, 0x0, 0x78, 0x0, 0x1f, + 0x0, 0xc3, 0xe0, 0x38, 0xfc, 0x7, 0xff, 0xf9, + 0xff, 0xff, 0x7f, 0xff, 0xdf, 0xff, 0xee, 0x3f, + 0x3, 0xf, 0x80, 0x7, 0xc0, 0x1, 0xe0, 0x0, + 0x70, 0x0, 0x18, 0x0, + + /* U+F073 "" */ + 0x18, 0x60, 0x61, 0x87, 0xff, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf3, 0x33, 0xcc, 0xcf, + 0xff, 0xff, 0xff, 0xf3, 0x33, 0xcc, 0xcf, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F074 "" */ + 0x0, 0xc, 0x0, 0xe, 0xf8, 0x7f, 0xfc, 0xff, + 0xc, 0xce, 0x6, 0xc, 0x7, 0x0, 0x3, 0x80, + 0x1, 0x8c, 0xc, 0xce, 0xfc, 0xff, 0xf8, 0x7f, + 0x0, 0xe, 0x0, 0xc, + + /* U+F075 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfc, 0x7f, 0xf8, 0xf7, 0xe0, 0xc0, 0x0, + + /* U+F076 "" */ + 0xf0, 0x3f, 0xc0, 0xff, 0x3, 0xc0, 0x0, 0xf0, + 0x3f, 0xc0, 0xff, 0x3, 0xfc, 0xf, 0xf0, 0x3f, + 0xc0, 0xff, 0x87, 0xdf, 0xfe, 0x3f, 0xf0, 0x7f, + 0x80, 0xfc, 0x0, + + /* U+F077 "" */ + 0x3, 0x0, 0x1e, 0x0, 0xfc, 0x7, 0x38, 0x38, + 0x71, 0xc0, 0xee, 0x1, 0xf0, 0x3, + + /* U+F078 "" */ + 0xc0, 0xf, 0x80, 0x77, 0x3, 0x8e, 0x1c, 0x1c, + 0xe0, 0x3f, 0x0, 0x78, 0x0, 0xc0, + + /* U+F079 "" */ + 0x30, 0xfe, 0x1e, 0x3f, 0xcf, 0xc0, 0x33, 0xf0, + 0xc, 0x30, 0x3, 0xc, 0x0, 0xc3, 0x0, 0x30, + 0xc0, 0xc, 0x30, 0x3, 0xc, 0x0, 0xc3, 0x0, + 0xfc, 0xc0, 0x3f, 0x3f, 0xc7, 0x87, 0xf0, 0xc0, + + /* U+F07A "" */ + 0x40, 0x0, 0x3c, 0x0, 0x3, 0xff, 0xfc, 0x7f, + 0xff, 0x1f, 0xff, 0xc7, 0xff, 0xe1, 0xff, 0xf8, + 0x7f, 0xfe, 0xf, 0xff, 0x83, 0xff, 0xc0, 0x80, + 0x0, 0x30, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0, + 0x70, 0xe0, 0x1c, 0x38, 0x7, 0xe, 0x0, + + /* U+F07B "" */ + 0x3c, 0x0, 0xff, 0x0, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, + + /* U+F07C "" */ + 0x3c, 0x0, 0x7f, 0x80, 0x3f, 0xff, 0x1f, 0xff, + 0xcc, 0x0, 0x4, 0x0, 0x2, 0xff, 0xff, 0x7f, + 0xff, 0x3f, 0xff, 0xbf, 0xff, 0x9f, 0xff, 0xcf, + 0xff, 0xe7, 0xff, 0xe0, + + /* U+F07D "" */ + 0x18, 0x3c, 0x7e, 0xff, 0xdb, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xdb, 0xff, 0x7e, + 0x3c, 0x18, + + /* U+F07E "" */ + 0x18, 0x6, 0xe, 0x1, 0xc7, 0x0, 0x3b, 0xff, + 0xff, 0xff, 0xff, 0xdc, 0x0, 0xe3, 0x80, 0x70, + 0x60, 0x18, + + /* U+F080 "" */ + 0xc0, 0x0, 0xcf, 0xf0, 0xcf, 0xf0, 0xc0, 0x0, + 0xc0, 0x0, 0xcf, 0xc0, 0xcf, 0xc0, 0xc0, 0x0, + 0xcf, 0xfc, 0xcf, 0xfc, 0xc0, 0x0, 0xc0, 0x0, + 0xff, 0xff, 0x7f, 0xff, + + /* U+F083 "" */ + 0x39, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7, 0xe0, 0xfc, 0x3f, 0xfc, 0x3f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xfc, 0x3f, 0xfc, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, + + /* U+F084 "" */ + 0x0, 0xf8, 0x1, 0xfc, 0x3, 0xfe, 0x7, 0xe7, + 0x7, 0xe7, 0x7, 0xe7, 0x7, 0xff, 0x7, 0xff, + 0xf, 0xfe, 0x1f, 0xfc, 0x3f, 0xf8, 0x7f, 0x0, + 0xfc, 0x0, 0xfc, 0x0, 0xf0, 0x0, 0xf0, 0x0, + + /* U+F085 "" */ + 0x0, 0x0, 0x0, 0xe0, 0x1, 0xfc, 0x0, 0x3f, + 0xc0, 0x3, 0xfe, 0x0, 0x63, 0xc0, 0x3c, 0x70, + 0x7, 0xfc, 0x0, 0x1f, 0xc0, 0x3, 0xfb, 0x80, + 0x70, 0x7e, 0x0, 0xf, 0xe0, 0xf, 0xf8, 0x1, + 0xe3, 0x0, 0xc, 0x78, 0x1, 0xff, 0x0, 0x7f, + 0x0, 0xf, 0xe0, 0x0, 0x1c, 0x0, 0x0, 0x0, + + /* U+F086 "" */ + 0x1f, 0x80, 0xf, 0xf0, 0x7, 0xfe, 0x3, 0xff, + 0xc0, 0xff, 0xf0, 0x3f, 0xfc, 0xf, 0xff, 0x43, + 0xff, 0xdc, 0x7f, 0xe7, 0x9f, 0xf3, 0xff, 0xf0, + 0xff, 0x0, 0x7f, 0x0, 0x7f, 0xc0, 0xff, 0xf0, + 0x1f, 0xf8, 0x3, 0xfe, 0x0, 0x7f, 0xc0, 0x0, + 0x30, + + /* U+F087 "" */ + 0x0, 0x0, 0x1, 0xc0, 0x1, 0xc0, 0x3, 0xc0, + 0x3, 0x80, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, + 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xfe, 0xf7, 0xfe, + 0xf7, 0xfe, 0xf3, 0xfc, 0xf1, 0xfc, + + /* U+F088 "" */ + 0x1, 0xfc, 0x3, 0xfc, 0xf7, 0xfe, 0xf7, 0xfe, + 0xf7, 0xfe, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, + 0xf7, 0xff, 0xf7, 0xff, 0xf3, 0x80, 0xf3, 0xc0, + 0x1, 0xc0, 0x1, 0xc0, 0x0, 0x0, + + /* U+F089 "" */ + 0x0, 0x0, 0x30, 0x1c, 0x7, 0x3, 0xcf, 0xff, + 0xfd, 0xff, 0x3f, 0xc7, 0xf0, 0xfc, 0x3f, 0xf, + 0xc3, 0xe0, 0xf0, 0x70, + + /* U+F08A "" */ + 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, + 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf0, + 0x7, 0xe0, 0x1, 0x80, + + /* U+F08B "" */ + 0x7c, 0x0, 0xfc, 0x0, 0xc0, 0x30, 0xc0, 0x38, + 0xc0, 0x1c, 0xc0, 0xe, 0xc7, 0xff, 0xc7, 0xff, + 0xc0, 0xe, 0xc0, 0x1c, 0xc0, 0x38, 0xc0, 0x30, + 0xfc, 0x0, 0x7c, 0x0, + + /* U+F08D "" */ + 0x7f, 0xe7, 0xfe, 0x1f, 0x81, 0xf8, 0x1f, 0x81, + 0xf8, 0x3f, 0xc7, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0x0, 0x0, 0x0, 0x60, 0x6, 0x0, 0x60, + 0x6, 0x0, + + /* U+F08E "" */ + 0x0, 0x7f, 0x0, 0x7f, 0x0, 0xf, 0x7c, 0x1f, + 0xfc, 0x3b, 0xc0, 0x73, 0xc0, 0xe3, 0xc1, 0xc0, + 0xc3, 0x80, 0xc3, 0x0, 0xc0, 0x18, 0xc0, 0x18, + 0xc0, 0x18, 0xc0, 0x18, 0xff, 0xf8, 0x7f, 0xf0, + + /* U+F090 "" */ + 0x0, 0x3e, 0x0, 0x3f, 0x6, 0x3, 0x7, 0x3, + 0x3, 0x83, 0x1, 0xc3, 0xff, 0xe3, 0xff, 0xe3, + 0x1, 0xc3, 0x3, 0x83, 0x7, 0x3, 0x6, 0x3, + 0x0, 0x3f, 0x0, 0x3e, + + /* U+F091 "" */ + 0x1f, 0xf8, 0x1f, 0xf8, 0xff, 0xff, 0xdf, 0xf9, + 0xdf, 0xfb, 0xcf, 0xfb, 0x6f, 0xf6, 0x7f, 0xfe, + 0x3f, 0xfc, 0xf, 0xf0, 0x3, 0xc0, 0x1, 0x80, + 0x1, 0x80, 0x1, 0x80, 0xf, 0xf0, 0xf, 0xf0, + + /* U+F093 "" */ + 0x3, 0x0, 0x1e, 0x0, 0xfc, 0x7, 0xf8, 0x1b, + 0x60, 0xc, 0x0, 0x30, 0x0, 0xc0, 0x3, 0x0, + 0xc, 0x7, 0xb7, 0xbf, 0x1f, 0xff, 0xef, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F094 "" */ + 0x3, 0xf8, 0x3f, 0xf3, 0x9f, 0xcc, 0x7f, 0x67, + 0xfd, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xfb, + 0xff, 0xef, 0xff, 0x3f, 0xfc, 0xff, 0xc1, 0xfc, + 0x0, + + /* U+F095 "" */ + 0x38, 0x0, 0x78, 0x0, 0xfc, 0x0, 0xfc, 0x0, + 0xfc, 0x0, 0xfc, 0x0, 0xf8, 0x0, 0x78, 0x0, + 0x7c, 0x0, 0x3e, 0x0, 0x1f, 0x3c, 0x1f, 0xbf, + 0xf, 0xff, 0x3, 0xff, 0x1, 0xfe, 0x0, 0x3c, + + /* U+F096 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F097 "" */ + 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf0, 0xfc, 0x3, + + /* U+F098 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xe3, + 0xff, 0x8f, 0xfe, 0x7f, 0xfc, 0xff, 0xf9, 0x1f, + 0xe0, 0x7f, 0xe3, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F09C "" */ + 0xf, 0x1, 0xf8, 0x39, 0xc3, 0xc, 0x30, 0x3, + 0x0, 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xe0, + + /* U+F09D "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xc6, 0x3f, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F09E "" */ + 0xf8, 0x3, 0xf8, 0x0, 0xf8, 0x0, 0xf0, 0xf0, + 0xe3, 0xf1, 0xc0, 0xe3, 0x1, 0xce, 0x3, 0x98, + 0x6, 0x66, 0xc, 0xfc, 0x33, 0xf0, 0xcd, 0x83, + 0x30, + + /* U+F0A0 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x7f, 0xfb, + 0xff, 0xff, 0xe4, 0xff, 0x93, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F0A1 "" */ + 0x0, 0x0, 0x0, 0x1c, 0x0, 0x78, 0x3, 0xf3, + 0xff, 0x6f, 0xf8, 0xff, 0x81, 0xff, 0x3, 0xfe, + 0x7, 0xfc, 0xd, 0xff, 0x19, 0xff, 0xb0, 0xe3, + 0xe1, 0xc3, 0xc3, 0x81, 0x87, 0x0, + + /* U+F0A2 "" */ + 0x3, 0x0, 0x1e, 0x1, 0xfe, 0x7, 0xf8, 0x3f, + 0xf0, 0xff, 0xc3, 0xff, 0xf, 0xfc, 0x3f, 0xf1, + 0xff, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xfc, 0x0, + 0x0, 0x0, 0x1, 0xe0, + + /* U+F0A3 "" */ + 0x2, 0x10, 0x0, 0xcc, 0x1, 0x3f, 0x20, 0xff, + 0xfc, 0x1f, 0xfe, 0xf, 0xff, 0xcf, 0xff, 0xfd, + 0xff, 0xfe, 0x3f, 0xff, 0x1f, 0xff, 0xef, 0xff, + 0xfc, 0xff, 0xfc, 0x1f, 0xfe, 0xf, 0xff, 0xc1, + 0x3f, 0x20, 0xc, 0xc0, 0x2, 0x10, 0x0, + + /* U+F0A4 "" */ + 0x1e, 0x0, 0x1f, 0xbf, 0x9f, 0xdf, 0xde, 0xe0, + 0xf, 0x77, 0x7, 0xbb, 0x83, 0xe0, 0x1, 0xfb, + 0xc0, 0xfd, 0xe0, 0x3e, 0x0, 0x1e, 0xf0, 0x3, + 0x78, 0x0, + + /* U+F0A5 "" */ + 0x0, 0x78, 0xff, 0x7e, 0xff, 0x7e, 0x0, 0x6f, + 0xf, 0x6f, 0xf, 0x6f, 0x0, 0x1f, 0x7, 0xbf, + 0x7, 0xbf, 0x0, 0x3e, 0x1, 0xde, 0x1, 0xd8, + + /* U+F0A6 "" */ + 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, 0x6c, 0x6, + 0xd8, 0x6d, 0xb0, 0x1b, 0x1, 0xb7, 0xc3, 0xfd, + 0xce, 0x3f, 0xff, 0xf7, 0xfe, 0x7f, 0xe1, 0xf8, + + /* U+F0A7 "" */ + 0x1f, 0x87, 0xfe, 0x7f, 0xef, 0xff, 0xe3, 0xff, + 0xdc, 0x7c, 0x30, 0x1b, 0x1, 0xb6, 0xdb, 0x6d, + 0x86, 0xc0, 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, + + /* U+F0A8 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0xfe, 0xfc, 0xff, 0xf9, 0xff, 0xf0, 0xf, + 0xf0, 0xf, 0xf9, 0xff, 0xfc, 0xff, 0x7e, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F0A9 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0x7e, 0xff, 0x3f, 0xff, 0x9f, 0xf0, 0xf, + 0xf0, 0xf, 0xff, 0x9f, 0xff, 0x3f, 0x7f, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F0AA "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfc, 0x3f, 0xf8, 0x1f, 0xf9, 0x9f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F0AB "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf9, 0x9f, 0xf8, 0x1f, 0xfc, 0x3f, 0x7e, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F0AC "" */ + 0x1, 0x80, 0x1b, 0xd8, 0x33, 0xcc, 0x77, 0xce, + 0x77, 0xee, 0xf7, 0xef, 0xf7, 0xef, 0x0, 0x0, + 0x0, 0x0, 0xf7, 0xef, 0xf7, 0xef, 0x77, 0xee, + 0x77, 0xce, 0x33, 0xcc, 0x1b, 0xd8, 0x1, 0x80, + + /* U+F0AD "" */ + 0x0, 0x78, 0x1, 0xf8, 0x1, 0xf0, 0x3, 0xe3, + 0x3, 0xc7, 0x3, 0xcf, 0x3, 0xff, 0x7, 0xfe, + 0xf, 0xfe, 0x1f, 0xf8, 0x3f, 0x80, 0x7f, 0x0, + 0xfe, 0x0, 0xfc, 0x0, 0xf8, 0x0, 0xf0, 0x0, + + /* U+F0AE "" */ + 0x30, 0x1, 0x67, 0xff, 0x8f, 0xfa, 0x0, 0x0, + 0x0, 0x6, 0x0, 0x2c, 0xff, 0xf1, 0xff, 0x40, + 0x0, 0x0, 0x0, 0x0, 0x7, 0x7f, 0xfe, 0xff, + 0xe0, + + /* U+F0B0 "" */ + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfc, + 0x1f, 0xf8, 0xf, 0xf0, 0x7, 0xe0, 0x3, 0xc0, + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, + 0x1, 0xc0, 0x0, 0xc0, + + /* U+F0B1 "" */ + 0x7, 0xe0, 0x4, 0x20, 0xc, 0x30, 0x7f, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0, 0x0, 0xfc, 0x3f, 0xfc, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F0B2 "" */ + 0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, + 0x1, 0x80, 0x31, 0x8c, 0x71, 0x8e, 0xff, 0xff, + 0xff, 0xff, 0x71, 0x8e, 0x31, 0x8c, 0x1, 0x80, + 0x7, 0xe0, 0x7, 0xe0, 0x3, 0xc0, 0x1, 0x80, + + /* U+F0C0 "" */ + 0x0, 0xf0, 0x0, 0x1f, 0x80, 0x31, 0xf8, 0xc7, + 0x9f, 0x9e, 0x79, 0xf9, 0xe3, 0x6, 0xc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x39, 0xf9, 0xc7, 0xbf, + 0xde, 0xf7, 0xfe, 0xff, 0x7f, 0xef, 0xf7, 0xfe, + 0xff, 0x7f, 0xef, + + /* U+F0C1 "" */ + 0x0, 0x1e, 0x0, 0xf, 0xe0, 0x78, 0x18, 0x3f, + 0x83, 0x1c, 0x60, 0xcc, 0xc, 0x36, 0x33, 0x1f, + 0xc, 0xc6, 0xc3, 0x3, 0x30, 0x63, 0x8c, 0x1f, + 0xc1, 0x81, 0xe0, 0x7e, 0x0, 0x7, 0xc0, 0x0, + + /* U+F0C2 "" */ + 0x7, 0x80, 0x3, 0xf8, 0x1, 0xff, 0xe0, 0x7f, + 0xfc, 0x1f, 0xff, 0xf, 0xff, 0xc7, 0xff, 0xf3, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0x8f, 0xff, 0xc0, + + /* U+F0C3 "" */ + 0x1f, 0xe0, 0x7f, 0x80, 0xcc, 0x3, 0x30, 0xc, + 0xc0, 0x33, 0x0, 0xcc, 0x3, 0x30, 0x18, 0x60, + 0xe1, 0xc3, 0xff, 0x1f, 0xfe, 0x7f, 0xfb, 0xff, + 0xff, 0xff, 0xdf, 0xfe, + + /* U+F0C4 "" */ + 0x38, 0x0, 0x7c, 0x6, 0xc6, 0x1f, 0xc6, 0x3e, + 0xc6, 0x7c, 0x7f, 0xf8, 0x3f, 0xf0, 0x7, 0xe0, + 0x3, 0xc0, 0x3f, 0x90, 0x7f, 0x38, 0xc6, 0x7c, + 0xc6, 0x3e, 0xc6, 0x1f, 0x7c, 0x6, 0x38, 0x0, + + /* U+F0C5 "" */ + 0x7, 0xf0, 0x3f, 0xe0, 0xff, 0xc3, 0xff, 0x6f, + 0xff, 0xbf, 0xfc, 0xff, 0xf3, 0xff, 0xcf, 0xff, + 0x3f, 0xfc, 0xff, 0xf1, 0xfe, 0xc0, 0x3, 0x3, + 0xf, 0xfc, 0x1f, 0xe0, + + /* U+F0C6 "" */ + 0x0, 0x20, 0x0, 0xf8, 0x1, 0x9c, 0x3, 0xc, + 0x6, 0x66, 0xc, 0xe6, 0x19, 0xcc, 0x31, 0x9c, + 0x63, 0x38, 0x66, 0x70, 0x4c, 0xe7, 0x4d, 0xce, + 0x67, 0x9c, 0x63, 0x38, 0x30, 0x70, 0x3d, 0xe0, + 0xf, 0xc0, 0x0, 0x0, + + /* U+F0C7 "" */ + 0x7f, 0xe3, 0xff, 0xce, 0x3, 0xb8, 0xf, 0xe0, + 0x3f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, + 0xe1, 0xff, 0x87, 0xff, 0x3f, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F0C8 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F0C9 "" */ + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xff, 0xff, 0xff, + + /* U+F0CA "" */ + 0x40, 0x0, 0xe7, 0xff, 0xe7, 0xff, 0x40, 0x0, + 0x0, 0x0, 0x40, 0x0, 0xe7, 0xff, 0xe7, 0xff, + 0x40, 0x0, 0x0, 0x0, 0x40, 0x0, 0xe7, 0xff, + 0xe7, 0xff, 0x40, 0x0, + + /* U+F0CB "" */ + 0x60, 0x0, 0x38, 0xff, 0xcc, 0x7f, 0xe6, 0x0, + 0x3, 0x0, 0x7, 0xe0, 0x0, 0x7, 0xfe, 0x3, + 0xff, 0x78, 0x0, 0x24, 0x0, 0xe, 0x0, 0xe, + 0x3f, 0xf7, 0xcf, 0xf0, + + /* U+F0CC "" */ + 0x7, 0xf0, 0xf, 0xf0, 0x1c, 0x0, 0x18, 0x0, + 0x18, 0x0, 0x1c, 0x0, 0xff, 0xff, 0xff, 0xff, + 0x0, 0x0, 0x0, 0x18, 0x0, 0x18, 0x0, 0x38, + 0xf, 0xf0, 0xf, 0xe0, + + /* U+F0CD "" */ + 0xf0, 0xff, 0xf, 0x60, 0x66, 0x6, 0x60, 0x66, + 0x6, 0x60, 0x66, 0x6, 0x60, 0x63, 0xc, 0x3f, + 0xc0, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + + /* U+F0CE "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, + 0xf, 0xc, 0x3c, 0x30, 0xff, 0xff, 0xff, 0xff, + 0xc, 0x3c, 0x30, 0xf0, 0xc3, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F0D0 "" */ + 0x0, 0xc, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x3f, + 0x0, 0x9e, 0x1, 0xcc, 0x3, 0xe0, 0x7, 0xf0, + 0xf, 0xe0, 0x1f, 0xc0, 0x3f, 0x80, 0x7f, 0x0, + 0xfe, 0x0, 0xfc, 0x0, 0x78, 0x0, 0x30, 0x0, + + /* U+F0D1 "" */ + 0x7f, 0xf8, 0x3f, 0xfe, 0xf, 0xff, 0xc3, 0xff, + 0xfc, 0xff, 0xff, 0xbf, 0xff, 0x7f, 0xff, 0xcf, + 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xcf, 0xcf, 0x73, 0xf3, 0x84, 0x84, 0xc1, + 0xc0, 0xe0, + + /* U+F0D6 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xcf, 0xf3, 0xdc, 0x3b, + 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xdc, 0x3b, 0xcf, 0xf3, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F0D7 "" */ + 0xff, 0xff, 0xf7, 0xf8, 0xfc, 0x1e, 0x3, 0x0, + + /* U+F0D8 "" */ + 0xc, 0x7, 0x83, 0xf1, 0xfe, 0xff, 0xff, 0xf0, + + /* U+F0D9 "" */ + 0xc, 0x73, 0xdf, 0xff, 0xf7, 0xcf, 0x1c, 0x30, + + /* U+F0DA "" */ + 0xc3, 0x8f, 0x3e, 0xff, 0xff, 0xbc, 0xe3, 0x0, + + /* U+F0DB "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, + 0xf, 0xc, 0x3c, 0x30, 0xf0, 0xc3, 0xc3, 0xf, + 0xc, 0x3c, 0x30, 0xf0, 0xc3, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F0DC "" */ + 0x6, 0x0, 0xf0, 0x1f, 0x83, 0xfc, 0x7f, 0xef, + 0xff, 0xff, 0xf0, 0x0, 0x0, 0xf, 0xff, 0xff, + 0xf7, 0xfe, 0x3f, 0xc1, 0xf8, 0xf, 0x0, 0x60, + + /* U+F0DD "" */ + 0xff, 0xff, 0xff, 0x7f, 0xe3, 0xfc, 0x1f, 0x80, + 0xf0, 0x6, 0x0, + + /* U+F0DE "" */ + 0x6, 0x0, 0xf0, 0x1f, 0x83, 0xfc, 0x7f, 0xef, + 0xff, 0xff, 0xf0, + + /* U+F0E0 "" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, + 0x1f, 0xf8, 0xcf, 0xf3, 0xe3, 0xc7, 0xf1, 0x8f, + 0xf8, 0x1f, 0xfe, 0x7f, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F0E2 "" */ + 0xc7, 0xe0, 0xdf, 0xf8, 0xfc, 0x3c, 0xf0, 0xe, + 0xfc, 0x6, 0xfc, 0x7, 0x0, 0x3, 0x0, 0x3, + 0x0, 0x3, 0x0, 0x3, 0x0, 0x7, 0x60, 0x6, + 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F0E3 "" */ + 0x1, 0x80, 0x1, 0xe0, 0x1, 0xe0, 0x1, 0xe4, + 0x1, 0xe7, 0x0, 0x67, 0xc0, 0x7, 0xf0, 0x3, + 0xf2, 0x1, 0xf3, 0x81, 0xd3, 0xc1, 0xc3, 0xc1, + 0xc3, 0xc1, 0xc1, 0xc1, 0xc0, 0x41, 0xc0, 0x1, + 0xc0, 0x0, 0xc0, 0x0, 0x0, + + /* U+F0E4 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xcf, 0xff, 0x9f, 0xff, 0x9f, + 0xff, 0x3f, 0xfe, 0x3f, 0xfc, 0x3f, 0x7c, 0x3e, + 0x7e, 0x7e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F0E5 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfc, 0x7f, 0xf8, 0xf7, 0xe0, 0xc0, 0x0, + + /* U+F0E6 "" */ + 0x1f, 0x80, 0xf, 0xf0, 0x7, 0xfe, 0x3, 0xff, + 0xc0, 0xff, 0xf0, 0x3f, 0xfc, 0xf, 0xff, 0x43, + 0xff, 0xdc, 0x7f, 0xe7, 0x9f, 0xf3, 0xff, 0xf0, + 0xff, 0x0, 0x7f, 0x0, 0x7f, 0xc0, 0xff, 0xf0, + 0x1f, 0xf8, 0x3, 0xfe, 0x0, 0x7f, 0xc0, 0x0, + 0x30, + + /* U+F0E7 "" */ + 0x0, 0x0, 0x3, 0x80, 0x1e, 0x0, 0xf0, 0x7, + 0xc0, 0x3f, 0x3, 0xf8, 0x1f, 0xe0, 0xff, 0xff, + 0xff, 0xf0, 0x7f, 0x81, 0xfc, 0x7, 0xc0, 0x3e, + 0x0, 0xf0, 0x7, 0x80, 0x1c, 0x0, 0x0, 0x0, + + /* U+F0E8 "" */ + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, + 0x1, 0x80, 0x1, 0x80, 0x3f, 0xfc, 0x61, 0x86, + 0x61, 0x86, 0x61, 0x86, 0xf3, 0xcf, 0xf3, 0xcf, + 0xf3, 0xcf, 0xf3, 0xcf, + + /* U+F0E9 "" */ + 0x1, 0x80, 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, + 0x7f, 0xfe, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x84, 0x21, 0x1, 0x80, 0x1, 0x80, + 0x1, 0x80, 0x1, 0x80, 0xd, 0x80, 0xf, 0x80, + 0x7, 0x0, + + /* U+F0EA "" */ + 0x7f, 0xc0, 0xff, 0xe0, 0xe0, 0xe0, 0xff, 0xe0, + 0xff, 0x0, 0xfe, 0xf8, 0xfd, 0xfe, 0xfd, 0xfe, + 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfd, 0xff, + 0xfd, 0xff, 0xfd, 0xff, 0x3d, 0xff, 0x0, 0xfe, + + /* U+F0EB "" */ + 0xf, 0x3, 0xfc, 0x73, 0xe6, 0x3e, 0xcf, 0xfc, + 0xff, 0xdf, 0xff, 0xff, 0x7f, 0xe7, 0xfe, 0x3f, + 0xc1, 0xf8, 0x0, 0x0, 0x0, 0x1f, 0x81, 0xf8, + 0xf, 0x0, + + /* U+F0EC "" */ + 0x0, 0x18, 0x0, 0x1c, 0x0, 0xe, 0xff, 0xff, + 0xff, 0xff, 0x0, 0xe, 0x0, 0x1c, 0x0, 0x18, + 0x18, 0x0, 0x38, 0x0, 0x70, 0x0, 0xff, 0xff, + 0xff, 0xff, 0x70, 0x0, 0x38, 0x0, 0x18, 0x0, + + /* U+F0ED "" */ + 0x3, 0xc0, 0x3, 0xf8, 0x0, 0xfe, 0x0, 0x7f, + 0xf8, 0x1f, 0xff, 0x7, 0xcf, 0xc7, 0xf3, 0xf1, + 0xfc, 0xfe, 0xfd, 0x2f, 0xff, 0x83, 0xff, 0xe1, + 0xff, 0xfc, 0xff, 0x7f, 0xff, 0x8f, 0xff, 0xc0, + + /* U+F0EE "" */ + 0x7, 0xc0, 0x3, 0xf8, 0x1, 0xff, 0xe0, 0x7f, + 0xfc, 0x1f, 0x3f, 0xf, 0xc7, 0xc7, 0xe0, 0xfb, + 0xf4, 0xbe, 0xff, 0x3f, 0xff, 0xcf, 0xff, 0xf3, + 0xfd, 0xff, 0xff, 0x7f, 0xff, 0x8f, 0xff, 0xc0, + + /* U+F0F0 "" */ + 0x7, 0x80, 0x7e, 0x7, 0xf0, 0x3f, 0xc1, 0xfc, + 0x7, 0xe0, 0x1e, 0x0, 0x0, 0x0, 0x0, 0xbc, + 0xd, 0xec, 0xce, 0x2e, 0x35, 0xf1, 0xaf, 0xff, + 0xe0, + + /* U+F0F1 "" */ + 0xf3, 0xc0, 0x79, 0xe0, 0x30, 0x30, 0x18, 0x19, + 0xec, 0xd, 0xfe, 0x6, 0xcf, 0x3, 0x67, 0x81, + 0xbf, 0x61, 0x8f, 0x3f, 0xc3, 0x7, 0x81, 0x81, + 0x80, 0xc0, 0xc0, 0x60, 0x70, 0x70, 0x1c, 0x70, + 0x7, 0xf0, 0x1, 0xf0, 0x0, + + /* U+F0F2 "" */ + 0x7, 0xe0, 0xc, 0x30, 0xc, 0x30, 0x6f, 0xf6, + 0xef, 0xf7, 0xef, 0xf7, 0xef, 0xf7, 0xef, 0xf7, + 0xef, 0xf7, 0xef, 0xf7, 0xef, 0xf7, 0xef, 0xf7, + 0xef, 0xf7, 0xef, 0xf7, 0x6f, 0xf6, + + /* U+F0F3 "" */ + 0x3, 0x0, 0x1e, 0x1, 0xfe, 0x7, 0xf8, 0x3f, + 0xf0, 0xff, 0xc3, 0xff, 0xf, 0xfc, 0x3f, 0xf1, + 0xff, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xfc, 0x0, + 0x0, 0x0, 0x1, 0xe0, + + /* U+F0F4 "" */ + 0x7f, 0xfe, 0x3f, 0xff, 0x9f, 0xfe, 0xef, 0xff, + 0x37, 0xff, 0x9b, 0xff, 0xdd, 0xff, 0xfc, 0xff, + 0xfc, 0x7f, 0xf8, 0x3f, 0xfc, 0xf, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xff, 0xe3, 0xff, 0xf0, + + /* U+F0F5 "" */ + 0x5a, 0x6, 0xb4, 0x3d, 0x68, 0x7a, 0xd1, 0xf5, + 0xa3, 0xff, 0xc7, 0xdf, 0x8f, 0x9e, 0x1f, 0x18, + 0x3e, 0x30, 0x7c, 0x60, 0x78, 0xc0, 0x31, 0x80, + 0x63, 0x0, 0xc6, 0x1, 0x8c, 0x3, + + /* U+F0F6 "" */ + 0x3e, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xe3, 0xff, 0xff, 0xff, 0xe0, 0x7e, 0x7, 0xff, + 0xfe, 0x7, 0xe0, 0x7f, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F0F7 "" */ + 0x7f, 0xef, 0xff, 0xff, 0xfe, 0x67, 0xe6, 0x7f, + 0xff, 0xff, 0xfe, 0x67, 0xe6, 0x7f, 0xff, 0xff, + 0xff, 0x9f, 0xf9, 0xff, 0x9f, 0xf9, 0xf7, 0xfe, + + /* U+F0F8 "" */ + 0x7, 0xf8, 0x3, 0xff, 0x0, 0xff, 0xc0, 0x3c, + 0xf0, 0x7f, 0x3f, 0xbf, 0xcf, 0xfc, 0xf3, 0xcf, + 0x3f, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, + 0xcf, 0x3c, 0xf3, 0xfe, 0x1f, 0xff, 0x87, 0xff, + 0xe1, 0xfd, 0xff, 0xfe, + + /* U+F0F9 "" */ + 0x7f, 0xf0, 0x3f, 0xfe, 0xf, 0xff, 0x83, 0xf7, + 0xfc, 0xfd, 0xff, 0xbc, 0x1e, 0x7f, 0x7, 0x8f, + 0xf7, 0xe3, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xdf, 0xef, 0x73, 0xf3, 0x8c, 0x84, 0xc1, + 0xc0, 0xe0, + + /* U+F0FA "" */ + 0x3, 0xe0, 0x6, 0x30, 0x6, 0x30, 0x67, 0xf6, + 0xe7, 0xf7, 0xe7, 0xf7, 0xe7, 0x77, 0xe7, 0x77, + 0xe4, 0x17, 0xe4, 0x17, 0xe7, 0x77, 0xe7, 0x77, + 0xe7, 0xf7, 0xe7, 0xf7, 0x67, 0xf6, + + /* U+F0FB "" */ + 0xf, 0xc0, 0x1, 0xc0, 0x0, 0x78, 0x0, 0x1f, + 0x0, 0xc7, 0xc0, 0x39, 0xf8, 0xf, 0xff, 0xf0, + 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xce, 0x7e, + 0x3, 0x1f, 0x0, 0x7, 0x80, 0x1, 0xe0, 0x0, + 0x70, 0x0, 0x3f, 0x0, + + /* U+F0FC "" */ + 0xff, 0xf0, 0xff, 0xf0, 0xff, 0xfe, 0xe9, 0x7f, + 0xe9, 0x73, 0xe9, 0x73, 0xe9, 0x73, 0xe9, 0x73, + 0xe9, 0x7f, 0xe9, 0x7c, 0xe9, 0x70, 0xff, 0xf0, + 0xff, 0xf0, 0x7f, 0xe0, + + /* U+F0FD "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xfd, 0xcf, 0xf7, + 0x3f, 0xdc, 0xff, 0x3, 0xfc, 0xf, 0xf7, 0x3f, + 0xdc, 0xff, 0x73, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F0FE "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3, 0xfc, 0xf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F100 "" */ + 0x6, 0x18, 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, + 0x71, 0xc3, 0x8e, 0xe, 0x38, 0x38, 0xe0, 0xe3, + 0x83, 0x8e, 0xc, 0x30, + + /* U+F101 "" */ + 0xc3, 0x7, 0x1c, 0x1c, 0x70, 0x71, 0xc1, 0xc7, + 0x7, 0x1c, 0x38, 0xe3, 0x8e, 0x38, 0xe3, 0x8e, + 0x38, 0xe1, 0x86, 0x0, + + /* U+F102 "" */ + 0x6, 0x0, 0xf0, 0x1f, 0x83, 0x9c, 0x70, 0xee, + 0x7, 0xc6, 0x30, 0xf0, 0x1f, 0x83, 0x9c, 0x70, + 0xee, 0x7, 0xc0, 0x30, + + /* U+F103 "" */ + 0xc0, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, 0x80, + 0xf0, 0xc6, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, + 0x80, 0xf0, 0x6, 0x0, + + /* U+F104 "" */ + 0x6, 0x1c, 0x71, 0xc7, 0x1c, 0x38, 0x38, 0x38, + 0x38, 0x38, 0x30, + + /* U+F105 "" */ + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc3, 0x8e, 0x38, + 0xe3, 0x86, 0x0, + + /* U+F106 "" */ + 0x6, 0x0, 0xf0, 0x1f, 0x83, 0x9c, 0x70, 0xee, + 0x7, 0xc0, 0x30, + + /* U+F107 "" */ + 0xc0, 0x3e, 0x7, 0x70, 0xe3, 0x9c, 0x1f, 0x80, + 0xf0, 0x6, 0x0, + + /* U+F108 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xc0, 0x3, 0xc0, 0x3, + 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, + 0xc0, 0x3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x3, 0xc0, 0x3, 0xc0, 0x1f, 0xf8, + + /* U+F109 "" */ + 0x1f, 0xff, 0x83, 0xff, 0xfc, 0x30, 0x0, 0xc3, + 0x0, 0xc, 0x30, 0x0, 0xc3, 0x0, 0xc, 0x30, + 0x0, 0xc3, 0x0, 0xc, 0x30, 0x0, 0xc3, 0x0, + 0xc, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xfe, + + /* U+F10A "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xf3, + 0xff, 0xcf, 0xdf, 0xfe, + + /* U+F10B "" */ + 0x7f, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xf7, 0xfe, 0xfb, 0xfe, + + /* U+F10C "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F10D "" */ + 0x38, 0x39, 0xe1, 0xee, 0xe, 0x30, 0x30, 0xf8, + 0xfb, 0xf3, 0xff, 0xcf, 0xff, 0x3f, 0xfc, 0xfd, + 0xe1, 0xe0, + + /* U+F10E "" */ + 0x78, 0x7b, 0xf3, 0xff, 0xcf, 0xff, 0x3f, 0xfc, + 0xfd, 0xf1, 0xf0, 0xc0, 0xc7, 0x7, 0x78, 0x79, + 0xc1, 0xc0, + + /* U+F110 "" */ + 0x1, 0x0, 0x3, 0x80, 0x33, 0x80, 0x38, 0x0, + 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x6, + 0xe0, 0x7, 0xe0, 0x6, 0x0, 0x0, 0x10, 0x8, + 0x38, 0x1c, 0x33, 0x9c, 0x3, 0x80, 0x3, 0x80, + + /* U+F111 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F112 "" */ + 0x0, 0x0, 0x6, 0x0, 0xe, 0x0, 0x1e, 0x0, + 0x3f, 0xf8, 0x7f, 0xfc, 0xff, 0xfe, 0x7f, 0xff, + 0x3f, 0xff, 0x1e, 0xf, 0xe, 0x7, 0x6, 0x7, + 0x0, 0x6, 0x0, 0x6, 0x0, 0xc, + + /* U+F114 "" */ + 0x3c, 0x0, 0xff, 0x0, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, + + /* U+F115 "" */ + 0x3c, 0x0, 0x7f, 0x80, 0x3f, 0xff, 0x1f, 0xff, + 0xcc, 0x0, 0x4, 0x0, 0x2, 0xff, 0xff, 0x7f, + 0xff, 0x3f, 0xff, 0xbf, 0xff, 0x9f, 0xff, 0xcf, + 0xff, 0xe7, 0xff, 0xe0, + + /* U+F118 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0xef, 0xf3, 0xcf, 0x78, 0x1e, + 0x7c, 0x3e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F119 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xfc, 0x3f, 0xf8, 0x1f, 0x73, 0xce, + 0x77, 0xee, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F11A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xf9, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0x78, 0x1e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F11B "" */ + 0xf, 0xff, 0x3, 0xff, 0xfc, 0x7f, 0xff, 0xe7, + 0xdf, 0xce, 0xfd, 0xfc, 0xff, 0xf, 0xcf, 0xf0, + 0xfb, 0xff, 0xdf, 0xbf, 0x7d, 0xfb, 0xe7, 0xff, + 0xfe, 0x3f, 0xff, 0xc0, 0xff, 0xf0, + + /* U+F11C "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xfc, 0x92, 0x4f, 0x24, + 0x93, 0xff, 0xff, 0xf2, 0x49, 0x3c, 0x92, 0x4f, + 0xff, 0xff, 0xf8, 0x7, 0xfe, 0x1, 0xff, 0xff, + 0xfd, 0xff, 0xfe, + + /* U+F11D "" */ + 0xc0, 0x3, 0x7c, 0x3f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xbf, 0xf0, 0x18, 0xc0, 0x3, 0x0, + 0xc, 0x0, 0x30, 0x0, + + /* U+F11E "" */ + 0xc0, 0x3, 0xfc, 0x3f, 0xff, 0xf3, 0x3f, 0xcc, + 0xcf, 0xf, 0x3f, 0x33, 0xff, 0xf, 0xcc, 0xcf, + 0x33, 0x3f, 0xff, 0xfc, 0x7f, 0xc0, 0x23, 0x0, + 0xc, 0x0, 0x30, 0x0, + + /* U+F120 "" */ + 0xc0, 0x0, 0xe0, 0x0, 0x70, 0x0, 0x38, 0x0, + 0x1c, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1c, 0x0, + 0x38, 0x0, 0x70, 0x0, 0xe3, 0xff, 0xc3, 0xff, + + /* U+F121 "" */ + 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, 0x1, + 0x80, 0x18, 0x66, 0xe, 0x19, 0xc7, 0xc, 0x3b, + 0x83, 0x7, 0xe0, 0xc1, 0xdc, 0x30, 0xe3, 0x98, + 0x70, 0x66, 0x18, 0x1, 0x80, 0x0, 0xc0, 0x0, + 0x30, 0x0, 0xc, 0x0, + + /* U+F122 "" */ + 0x6, 0x60, 0x3, 0x38, 0x1, 0x9e, 0x0, 0xcf, + 0x80, 0x67, 0xff, 0x33, 0xff, 0xec, 0xff, 0xf9, + 0x9f, 0xff, 0x33, 0xef, 0xc6, 0x78, 0xf0, 0xce, + 0x1c, 0x19, 0x86, 0x0, 0x1, 0x80, 0x0, 0xc0, + + /* U+F123 "" */ + 0x0, 0x0, 0x30, 0x1c, 0x7, 0x3, 0xcf, 0xff, + 0xfd, 0xff, 0x3f, 0xc7, 0xf0, 0xfc, 0x3f, 0xf, + 0xc3, 0xe0, 0xf0, 0x70, + + /* U+F124 "" */ + 0x0, 0xe, 0x0, 0x7c, 0x7, 0xf0, 0x3f, 0xe3, + 0xff, 0xdf, 0xff, 0x3f, 0xfe, 0x1f, 0xfc, 0x7, + 0xf0, 0x7, 0xe0, 0x7, 0x80, 0xf, 0x0, 0x1e, + 0x0, 0x18, 0x0, 0x30, 0x0, + + /* U+F125 "" */ + 0x30, 0x3, 0x30, 0x7, 0xf7, 0xfe, 0xf7, 0xfc, + 0x30, 0x3c, 0x30, 0x7c, 0x30, 0xec, 0x31, 0xcc, + 0x33, 0x8c, 0x37, 0xc, 0x3e, 0xc, 0x3c, 0xc, + 0x3f, 0xef, 0x1f, 0xef, 0x0, 0xc, 0x0, 0xc, + + /* U+F126 "" */ + 0x70, 0x3b, 0xe1, 0xfd, 0x86, 0xf6, 0x1b, 0x70, + 0x38, 0x80, 0x42, 0x1, 0x8, 0x1c, 0x3f, 0xe0, + 0x80, 0x2, 0x0, 0x8, 0x0, 0xf8, 0x3, 0x60, + 0xf, 0x80, 0x1c, 0x0, + + /* U+F127 "" */ + 0xc0, 0x0, 0x38, 0x0, 0x7, 0x1, 0xe0, 0xe0, + 0xfe, 0x1f, 0x81, 0x83, 0xf8, 0x30, 0x76, 0xc, + 0xce, 0xc3, 0x61, 0xf1, 0xf8, 0x3c, 0x6c, 0x27, + 0x33, 0x4, 0xf8, 0xc1, 0x9c, 0x18, 0x13, 0x87, + 0xe0, 0x70, 0x7c, 0xe, 0x0, 0x1, 0xc0, 0x0, + 0x30, + + /* U+F128 "" */ + 0x1e, 0x1f, 0xe6, 0x1b, 0x3, 0xc0, 0xf0, 0x30, + 0xc, 0x6, 0x7, 0x83, 0xc0, 0xc0, 0x30, 0x0, + 0x0, 0x0, 0xc0, 0x30, + + /* U+F129 "" */ + 0x31, 0xe3, 0x0, 0x3, 0xcf, 0xc, 0x30, 0xc3, + 0xc, 0x30, 0xcf, 0xff, + + /* U+F12A "" */ + 0xff, 0xff, 0xff, 0xf, + + /* U+F12B "" */ + 0x0, 0x6, 0x0, 0xe, 0xe0, 0xe6, 0xf1, 0xe6, + 0x31, 0x86, 0x1b, 0xf, 0x1f, 0xf, 0xe, 0x0, + 0xe, 0x0, 0x1f, 0x0, 0x1b, 0x0, 0x31, 0x80, + 0xf1, 0xe0, 0xe0, 0xe0, + + /* U+F12C "" */ + 0xe0, 0xe0, 0xf1, 0xe0, 0x31, 0x80, 0x1b, 0x0, + 0x1f, 0x0, 0xe, 0x0, 0xe, 0x0, 0x1f, 0x6, + 0x1b, 0xe, 0x31, 0x86, 0xf1, 0xe6, 0xe0, 0xe6, + 0x0, 0xf, 0x0, 0xf, + + /* U+F12D "" */ + 0x0, 0xe0, 0x0, 0xf8, 0x0, 0xfe, 0x0, 0xff, + 0x80, 0xff, 0xe0, 0xff, 0xf8, 0xe7, 0xfe, 0xe1, + 0xff, 0xe0, 0x7f, 0xe0, 0x1f, 0xb8, 0x7, 0x8e, + 0x3, 0x83, 0x83, 0x80, 0xff, 0xfc, 0x3f, 0xfe, + + /* U+F12E "" */ + 0x3, 0x0, 0x7, 0x80, 0x7, 0x80, 0x3, 0x0, + 0xff, 0xf0, 0xff, 0xf0, 0xff, 0xf0, 0xdf, 0xf6, + 0xf, 0xff, 0xf, 0xff, 0xdf, 0xf6, 0xff, 0xf0, + 0xfc, 0xf0, 0xf8, 0x70, 0xfc, 0xf0, 0xfc, 0xf0, + + /* U+F130 "" */ + 0xf, 0x1, 0xf8, 0x1f, 0x81, 0xf8, 0x1f, 0x8d, + 0xfb, 0xdf, 0xbd, 0xfb, 0xdf, 0xbc, 0xf7, 0x60, + 0x63, 0xc, 0x1f, 0x80, 0x60, 0x6, 0x1, 0xf8, + + /* U+F131 "" */ + 0x0, 0x0, 0x30, 0x0, 0x6, 0x1e, 0x0, 0xcf, + 0xc0, 0x1b, 0xf0, 0x3, 0xfc, 0x0, 0x7f, 0x0, + 0x4f, 0xd8, 0x19, 0xf6, 0x6, 0x3d, 0x81, 0x86, + 0x60, 0x30, 0xf0, 0xe, 0x18, 0x0, 0xf3, 0x0, + 0xc, 0x60, 0x3, 0xc, 0x3, 0xf1, 0x80, 0x0, + 0x30, + + /* U+F132 "" */ + 0x3, 0x80, 0x1f, 0xc1, 0xff, 0xf7, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xfc, 0xff, 0xf9, 0xff, 0xf1, 0xff, 0xc1, 0xff, + 0x3, 0xfe, 0x1, 0xf0, 0x1, 0xc0, + + /* U+F133 "" */ + 0x18, 0x60, 0x61, 0x87, 0xff, 0xbf, 0xff, 0xff, + 0xfc, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F134 "" */ + 0xe, 0x3, 0xe, 0x7f, 0x3f, 0xff, 0x6e, 0x7f, + 0xdf, 0x3, 0xbf, 0x80, 0x3f, 0x80, 0x3f, 0x80, + 0x3f, 0x80, 0x3f, 0x80, 0x3f, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0x80, 0x3f, 0x80, 0x1f, 0x0, + + /* U+F135 "" */ + 0x0, 0x1e, 0x0, 0x7f, 0x0, 0xe7, 0x1, 0xe7, + 0x1f, 0xe7, 0x3f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfc, + 0x7f, 0xf8, 0x3, 0xf0, 0x1, 0xf0, 0x1, 0xf0, + 0x1, 0xf0, 0x1, 0xe0, 0x1, 0xc0, 0x0, 0x0, + + /* U+F137 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0x3e, 0xfe, 0x3f, 0xfc, 0xff, 0xf9, 0xff, + 0xf9, 0xff, 0xfc, 0xff, 0xfe, 0x3f, 0x7f, 0x3e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F138 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7c, 0xfe, 0xfc, 0x7f, 0xff, 0x3f, 0xff, 0x9f, + 0xff, 0x9f, 0xff, 0x3f, 0xfc, 0x7f, 0x7c, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F139 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xfe, 0x7f, 0xfc, 0x3f, 0xf9, 0x9f, + 0xf3, 0xcf, 0xf3, 0xcf, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F13A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xf3, 0xcf, 0xf3, 0xcf, + 0xf9, 0x9f, 0xfc, 0x3f, 0xfe, 0x7f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F13D "" */ + 0x3, 0xc0, 0x3, 0xf0, 0x1, 0x98, 0x0, 0xcc, + 0x0, 0x7e, 0x0, 0x1e, 0x0, 0x6, 0x0, 0x63, + 0xc, 0x79, 0x8f, 0x7e, 0xcf, 0xcc, 0x61, 0x86, + 0x31, 0xc1, 0x98, 0xc0, 0xed, 0xe0, 0x3f, 0xe0, + 0x7, 0xc0, + + /* U+F13E "" */ + 0xf, 0x1, 0xf8, 0x39, 0xc3, 0xc, 0x30, 0x3, + 0x0, 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xe0, + + /* U+F140 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, + 0x67, 0xc6, 0xef, 0xe7, 0xdc, 0x73, 0xd9, 0xb3, + 0xd9, 0xb3, 0xd8, 0x33, 0xfc, 0x77, 0x6f, 0xe6, + 0x77, 0xce, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F141 "" */ + 0x63, 0x1b, 0xde, 0xf6, 0x31, 0x80, + + /* U+F142 "" */ + 0x6f, 0x60, 0x0, 0x6f, 0x60, 0x6, 0xf6, + + /* U+F143 "" */ + 0x7f, 0xfb, 0xff, 0xfe, 0x3f, 0xf8, 0x3f, 0xfc, + 0x7f, 0x9c, 0xfe, 0x1b, 0xfe, 0x67, 0xfc, 0xdf, + 0x9b, 0x7e, 0x6d, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F144 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7d, 0xfe, 0xfc, 0x7f, 0xfc, 0x3f, 0xfc, 0x1f, + 0xfc, 0x1f, 0xfc, 0x3f, 0xfc, 0x7f, 0x7d, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F145 "" */ + 0x7f, 0xff, 0xcf, 0xff, 0xfb, 0xc0, 0x7, 0xf8, + 0x0, 0xf7, 0x7f, 0x9c, 0x6f, 0xf3, 0xd, 0xfe, + 0x63, 0xbf, 0xce, 0xf7, 0xf9, 0xfe, 0x0, 0x3d, + 0xff, 0xff, 0x3f, 0xff, 0xe0, + + /* U+F146 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3, 0xfc, 0xf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F147 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3, 0xfc, 0xf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F148 "" */ + 0x6, 0x1, 0xe0, 0x7e, 0x1f, 0xe7, 0x6e, 0xcc, + 0xc1, 0x80, 0x30, 0x6, 0x0, 0xc0, 0x18, 0x3, + 0x0, 0x60, 0xc, 0x3f, 0x87, 0xe0, + + /* U+F149 "" */ + 0xfc, 0x1f, 0xc0, 0x18, 0x3, 0x0, 0x60, 0xc, + 0x1, 0x80, 0x30, 0x6, 0x0, 0xc1, 0x99, 0xbb, + 0x73, 0xfc, 0x3f, 0x3, 0xc0, 0x30, + + /* U+F14A "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x9f, 0xfe, 0xff, 0xf3, 0xf9, 0x9f, 0xe4, 0xff, + 0xc7, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F14B "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, + 0x1f, 0xf6, 0x7f, 0x8f, 0xfc, 0x1f, 0xe0, 0xff, + 0x87, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, + + /* U+F14C "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x3f, 0xf8, 0xff, 0xc3, 0xfe, 0x2f, 0xf1, 0xbf, + 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F14D "" */ + 0x0, 0x18, 0x0, 0xe, 0x0, 0x7, 0x8e, 0x3f, + 0xef, 0x7f, 0xfe, 0x7f, 0xff, 0x3f, 0xfd, 0x9e, + 0x3c, 0xce, 0x1c, 0x63, 0xc, 0x31, 0x80, 0x18, + 0x20, 0xc, 0x1, 0x86, 0x0, 0xc3, 0xff, 0xe0, + 0xff, 0xe0, + + /* U+F14E "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xce, 0xfe, 0xf, 0xfc, 0x1f, 0xf9, 0x9f, + 0xf9, 0x9f, 0xf8, 0x3f, 0xf0, 0x7f, 0x73, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F150 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x80, 0x7e, 0x1, 0xfc, 0xf, 0xf8, 0x7f, + 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F151 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0xff, 0xe1, 0xff, 0x3, 0xf8, 0x7, 0xe0, 0x1f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F152 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xf8, + 0xff, 0xe1, 0xff, 0x83, 0xfe, 0xf, 0xf8, 0x7f, + 0xe3, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F153 "" */ + 0x3, 0xe0, 0xfe, 0x1c, 0x3, 0x80, 0x30, 0xf, + 0xf8, 0xff, 0x8f, 0xf8, 0xff, 0x83, 0x0, 0x38, + 0x1, 0xc0, 0xf, 0xe0, 0x3e, + + /* U+F154 "" */ + 0xf, 0xf, 0xe3, 0x1d, 0x80, 0x60, 0x1c, 0xf, + 0xfb, 0xfe, 0x30, 0xc, 0x6, 0x3, 0x80, 0xff, + 0xff, 0xf0, + + /* U+F155 "" */ + 0x18, 0xc, 0x1f, 0xdf, 0xec, 0x6, 0x3, 0x80, + 0xfc, 0x3f, 0x1, 0xc0, 0x60, 0x37, 0xf3, 0xf0, + 0x60, 0x30, + + /* U+F156 "" */ + 0xfc, 0x3, 0xf8, 0xc, 0x70, 0x30, 0xc0, 0xc3, + 0x3, 0xc, 0xc, 0x77, 0xbf, 0x9e, 0xfc, 0x63, + 0x31, 0xec, 0xc3, 0xf1, 0x83, 0xc6, 0x7f, 0x19, + 0xe0, + + /* U+F157 "" */ + 0x0, 0x6, 0x6, 0x60, 0x63, 0xc, 0x39, 0xc1, + 0x98, 0xf, 0x0, 0xf0, 0x3f, 0xc3, 0xfc, 0x6, + 0x3, 0xfc, 0x3f, 0xc0, 0x60, 0x6, 0x0, + + /* U+F158 "" */ + 0x3f, 0xc3, 0xfe, 0x30, 0x73, 0x3, 0x30, 0x33, + 0x3, 0x30, 0x7f, 0xfe, 0xff, 0xc3, 0x0, 0xff, + 0xcf, 0xfc, 0x30, 0x3, 0x0, + + /* U+F159 "" */ + 0x0, 0x0, 0xc1, 0x83, 0xc1, 0x83, 0xe3, 0xc7, + 0x63, 0xc6, 0x63, 0xc6, 0x73, 0xce, 0xff, 0xff, + 0xff, 0xff, 0x36, 0x6c, 0x1e, 0x78, 0x1e, 0x78, + 0x1c, 0x38, 0xc, 0x30, 0xc, 0x30, + + /* U+F15B "" */ + 0x3e, 0x7, 0xfc, 0x3f, 0xf1, 0xfd, 0xcf, 0xe7, + 0x7f, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xcf, 0xfe, + + /* U+F15C "" */ + 0x3e, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xe3, 0xff, 0xff, 0xff, 0xe0, 0x7e, 0x7, 0xff, + 0xfe, 0x7, 0xe0, 0x7f, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F15D "" */ + 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x3c, + 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x42, 0x18, 0x0, + 0x18, 0x7e, 0x5a, 0x7e, 0x7e, 0x1c, 0x7e, 0x38, + 0x3c, 0x7e, 0x18, 0x7e, + + /* U+F15E "" */ + 0x0, 0x0, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x3c, + 0x5a, 0x7e, 0x18, 0x7e, 0x18, 0x42, 0x18, 0x0, + 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x1c, 0x18, 0x38, + 0x18, 0x7e, 0x18, 0x7e, + + /* U+F160 "" */ + 0x18, 0x7f, 0xc6, 0x1f, 0xf1, 0x80, 0x0, 0x60, + 0x0, 0x18, 0x7f, 0x6, 0x1f, 0xc1, 0x80, 0x0, + 0x60, 0x0, 0x18, 0x7c, 0x36, 0xdf, 0xf, 0xf0, + 0x1, 0xf8, 0x0, 0x3c, 0x70, 0x6, 0x1c, 0x0, + + /* U+F161 "" */ + 0x18, 0x7f, 0xcf, 0x1f, 0xf7, 0xe0, 0x3, 0xfc, + 0x0, 0xdb, 0x7f, 0x6, 0x1f, 0xc1, 0x80, 0x0, + 0x60, 0x0, 0x18, 0x7c, 0x6, 0x1f, 0x1, 0x80, + 0x0, 0x60, 0x0, 0x18, 0x70, 0x6, 0x1c, 0x0, + + /* U+F162 "" */ + 0x18, 0x18, 0x30, 0x78, 0x60, 0x70, 0xc0, 0xe1, + 0x83, 0xe3, 0x7, 0xc6, 0x0, 0xc, 0xe, 0x18, + 0x3f, 0xb6, 0x6f, 0xfc, 0xfb, 0xf0, 0xe3, 0xc1, + 0xc3, 0x3, 0x0, + + /* U+F163 "" */ + 0x18, 0x18, 0x78, 0x79, 0xf8, 0x77, 0xf8, 0xed, + 0xb3, 0xe3, 0x7, 0xc6, 0x0, 0xc, 0xe, 0x18, + 0x3e, 0x30, 0x6c, 0x60, 0xf8, 0xc0, 0xe1, 0x81, + 0xc3, 0x3, 0x0, + + /* U+F164 "" */ + 0x0, 0x0, 0x1, 0xc0, 0x1, 0xc0, 0x3, 0xc0, + 0x3, 0x80, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, + 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xfe, 0xf7, 0xfe, + 0xf7, 0xfe, 0xf3, 0xfc, 0xf1, 0xfc, + + /* U+F165 "" */ + 0x1, 0xfc, 0x3, 0xfc, 0xf7, 0xfe, 0xf7, 0xfe, + 0xf7, 0xfe, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, + 0xf7, 0xff, 0xf7, 0xff, 0xf3, 0x80, 0xf3, 0xc0, + 0x1, 0xc0, 0x1, 0xc0, 0x0, 0x0, + + /* U+F175 "" */ + 0xc, 0x3, 0x0, 0xc0, 0x30, 0xc, 0x3, 0x0, + 0xc0, 0x30, 0xc, 0x3, 0x0, 0xc0, 0x30, 0xcc, + 0xfb, 0x77, 0xf8, 0xfc, 0x1e, 0x3, 0x0, + + /* U+F176 "" */ + 0xc, 0x7, 0x83, 0xf1, 0xfe, 0xed, 0xf3, 0x30, + 0xc0, 0x30, 0xc, 0x3, 0x0, 0xc0, 0x30, 0xc, + 0x3, 0x0, 0xc0, 0x30, 0xc, 0x3, 0x0, + + /* U+F177 "" */ + 0xc, 0x0, 0x7, 0x0, 0x3, 0x80, 0x1, 0xc0, + 0x0, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x0, 0x0, + 0xe0, 0x0, 0x1c, 0x0, 0x3, 0x0, 0x0, + + /* U+F178 "" */ + 0x0, 0xc, 0x0, 0x3, 0x80, 0x0, 0x70, 0x0, + 0xe, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x38, + 0x0, 0x1c, 0x0, 0xe, 0x0, 0x3, 0x0, + + /* U+F182 "" */ + 0xe, 0x1, 0xc0, 0x38, 0x0, 0x0, 0x0, 0x3e, + 0xf, 0xe3, 0xfe, 0x7f, 0xdb, 0xef, 0xff, 0x9f, + 0xc3, 0xf8, 0x36, 0x6, 0xc0, 0xd8, 0x1b, 0x3, + 0x60, + + /* U+F183 "" */ + 0xe, 0x1, 0xc0, 0x38, 0x0, 0x0, 0x0, 0x1c, + 0xf, 0xe1, 0xfc, 0x7f, 0xdf, 0xff, 0x7d, 0x8f, + 0x81, 0xb0, 0x36, 0x6, 0xc0, 0xd8, 0x1b, 0x3, + 0x60, 0x0, 0x0, + + /* U+F185 "" */ + 0x4, 0x10, 0x7, 0xbc, 0x3, 0xfe, 0x1, 0xff, + 0x7, 0xff, 0xf7, 0xe0, 0xfd, 0xe7, 0x3c, 0xf7, + 0xde, 0x3b, 0xee, 0x3d, 0xf7, 0x9e, 0x73, 0xdf, + 0x83, 0xf7, 0xff, 0xf0, 0x7f, 0xc0, 0x3f, 0xe0, + 0x1e, 0xf0, 0x4, 0x10, 0x0, + + /* U+F186 "" */ + 0xf, 0xe0, 0x7f, 0x3, 0xf0, 0x1f, 0xc0, 0x7e, + 0x3, 0xf8, 0xf, 0xe0, 0x3f, 0x80, 0xfe, 0x3, + 0xfc, 0x7, 0xf8, 0x1f, 0xf0, 0x3f, 0xfc, 0x7f, + 0xe0, 0x7e, 0x0, + + /* U+F187 "" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xfe, 0x7f, 0xfe, 0x78, 0x1e, + 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, + + /* U+F188 "" */ + 0x1, 0xe0, 0x0, 0xfc, 0x0, 0x3f, 0x1, 0x8f, + 0xc6, 0x70, 0x3, 0x8f, 0x7b, 0xc0, 0xff, 0xc0, + 0x3f, 0xf0, 0xff, 0x3f, 0xff, 0xcf, 0xf0, 0xf3, + 0xc0, 0x3c, 0xf0, 0x3f, 0x3f, 0x1d, 0xce, 0xe6, + 0x73, 0x98, 0x4, 0x80, + + /* U+F18E "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0x7e, 0xff, 0x3f, 0xf0, 0x1f, 0xf0, 0xf, + 0xf0, 0xf, 0xf0, 0x1f, 0xff, 0x3f, 0x7f, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F190 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0xfe, 0xfc, 0xff, 0xf8, 0xf, 0xf0, 0xf, + 0xf0, 0xf, 0xf8, 0xf, 0xfc, 0xff, 0x7e, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F191 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xfc, + 0x7f, 0xe1, 0xff, 0x7, 0xfc, 0x1f, 0xf8, 0x7f, + 0xf1, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F192 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F193 "" */ + 0x6, 0x0, 0xf, 0x0, 0x6, 0x0, 0x0, 0x0, + 0x3, 0x0, 0x7, 0x80, 0x13, 0x80, 0x73, 0x80, + 0x63, 0x80, 0xc3, 0xf8, 0xc1, 0xfc, 0xc0, 0xc, + 0xc0, 0xcc, 0x61, 0xcf, 0x7f, 0x86, 0x1e, 0x0, + + /* U+F195 "" */ + 0xf, 0x83, 0xf8, 0xe3, 0x18, 0x3, 0x0, 0xff, + 0x9f, 0xf0, 0xc0, 0x7f, 0xcf, 0xf8, 0xc0, 0x38, + 0x7, 0xfe, 0xff, 0xc0, + + /* U+F196 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3, 0xfc, 0xf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F197 "" */ + 0xfc, 0x0, 0x6f, 0x80, 0x36, 0x60, 0x1b, 0x1c, + 0xf, 0x80, 0x7, 0xff, 0xe3, 0xff, 0xfd, 0xff, + 0xf7, 0xff, 0xff, 0x7f, 0xff, 0x3e, 0x0, 0x1b, + 0x18, 0xd, 0xb0, 0x7, 0xe0, 0x0, + + /* U+F199 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x1f, 0xc0, 0xfe, 0xcd, 0xf8, 0xc7, 0xe0, 0x1f, + 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F19C "" */ + 0x1, 0x80, 0x7, 0xe0, 0x3e, 0x7c, 0xfe, 0x7f, + 0xff, 0xff, 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, + 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + + /* U+F19D "" */ + 0x1, 0xe0, 0x0, 0xff, 0x80, 0xff, 0xfc, 0x7f, + 0xff, 0xef, 0xff, 0xfd, 0xbf, 0xfe, 0x31, 0xff, + 0x7, 0x7, 0x0, 0xd8, 0x6, 0x1b, 0xc3, 0xc3, + 0x7f, 0xf8, 0x6f, 0xff, 0xc, 0xff, 0xc1, 0x87, + 0xe0, 0x0, + + /* U+F1AB "" */ + 0xc, 0x0, 0x3, 0x0, 0xf, 0xfe, 0x3, 0xff, + 0x80, 0x1, 0xc0, 0x4, 0x63, 0x3, 0xb8, 0xc0, + 0x7c, 0x78, 0xe, 0x1e, 0x7, 0xef, 0xc7, 0x9f, + 0x31, 0x81, 0xce, 0x0, 0x7f, 0x80, 0x1f, 0xe0, + 0xc, 0xc, 0x3, 0x3, + + /* U+F1AC "" */ + 0x3, 0xf8, 0x7, 0xfc, 0x6, 0x6, 0x6, 0x6, + 0xf6, 0x6, 0xf0, 0x0, 0xf7, 0xff, 0xf7, 0xff, + 0xf6, 0x4b, 0xf6, 0x4b, 0xf7, 0xff, 0xf6, 0x4b, + 0xf6, 0x4b, 0xf7, 0xff, 0xf7, 0xff, + + /* U+F1AD "" */ + 0x7f, 0xef, 0xff, 0xff, 0xfe, 0x67, 0xe6, 0x7f, + 0xff, 0xff, 0xfe, 0x67, 0xe6, 0x7f, 0xff, 0xff, + 0xff, 0x9f, 0xf9, 0xff, 0x9f, 0xf9, 0xf7, 0xfe, + + /* U+F1AE "" */ + 0xe, 0x1, 0xc0, 0x38, 0x7, 0x0, 0x0, 0x1e, + 0xf, 0xe1, 0xfc, 0x7f, 0xcf, 0xf9, 0x7d, 0xf, + 0x81, 0xb0, 0x36, 0x6, 0xc0, 0xd8, + + /* U+F1B0 "" */ + 0xc, 0x30, 0xe, 0x70, 0xe, 0x70, 0xe, 0x70, + 0xe6, 0x67, 0xe0, 0x7, 0xe3, 0xc7, 0x67, 0xe6, + 0xf, 0xf0, 0x1f, 0xf8, 0x1f, 0xf8, 0x3f, 0xfc, + 0x3f, 0xfc, 0x3c, 0x3c, + + /* U+F1B1 "" */ + 0x0, 0x1e, 0x0, 0x7f, 0x0, 0xff, 0x1, 0xff, + 0x1, 0xff, 0x1, 0xfe, 0x1, 0xfe, 0x1, 0xfc, + 0x3, 0xf8, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, + 0x38, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xc0, 0x0, + + /* U+F1B2 "" */ + 0x3, 0x80, 0xf, 0x80, 0x7f, 0xc3, 0xff, 0xef, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, + 0x87, 0xfe, 0xf, 0xfc, 0x1f, 0xf8, 0x3f, 0xf1, + 0xef, 0xe7, 0x87, 0xfc, 0x7, 0xe0, 0x3, 0x80, + + /* U+F1B3 "" */ + 0x3, 0x80, 0xf, 0xe0, 0x1f, 0xf0, 0x1f, 0xb0, + 0x1f, 0x30, 0x1f, 0x30, 0x1f, 0x30, 0x7f, 0xfc, + 0xff, 0xff, 0xfd, 0xfb, 0xf9, 0xf3, 0xf1, 0xe3, + 0xf1, 0xe3, 0xf7, 0xef, 0x3e, 0x7c, 0x8, 0x10, + + /* U+F1B8 "" */ + 0x0, 0x0, 0x0, 0xfc, 0x0, 0x33, 0x0, 0x8, + 0x68, 0x0, 0x1e, 0xf, 0x7, 0x87, 0xc1, 0xe0, + 0xf0, 0x0, 0x34, 0x0, 0x1c, 0x0, 0x66, 0x0, + 0x19, 0x80, 0x86, 0x60, 0x61, 0x8f, 0x3f, 0xc1, + 0xcf, 0xe0, 0x1, 0x80, 0x0, 0x20, 0x0, + + /* U+F1B9 "" */ + 0xf, 0xf0, 0x1f, 0xf8, 0x30, 0xc, 0x30, 0xc, + 0x70, 0xe, 0x7f, 0xfe, 0xff, 0xff, 0xcf, 0xf3, + 0xcf, 0xf3, 0xcf, 0xf3, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0x7, 0xe0, 0x7, + + /* U+F1BA "" */ + 0x7, 0xe0, 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, + 0x30, 0xc, 0x70, 0xe, 0x7f, 0xfe, 0xff, 0xff, + 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xff, 0xff, + 0xff, 0xff, 0xe0, 0x7, 0xe0, 0x7, + + /* U+F1BB "" */ + 0x3, 0x0, 0x1e, 0x0, 0x78, 0x3, 0xf0, 0x1f, + 0xe0, 0xff, 0xc1, 0xfe, 0x7, 0xf8, 0x3f, 0xf1, + 0xff, 0xe3, 0xff, 0xf, 0xfc, 0x7f, 0xfb, 0xff, + 0xff, 0xff, 0xc0, 0xc0, 0x3, 0x0, 0xc, 0x0, + + /* U+F1C0 "" */ + 0x1f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfc, 0x7f, 0x88, 0x0, 0x78, 0x7, 0xff, 0xfd, + 0xff, 0xe1, 0xfe, 0x20, 0x1, 0xe0, 0x1f, 0xff, + 0xf7, 0xff, 0x87, 0xf8, + + /* U+F1C1 "" */ + 0x3e, 0x0, 0x7f, 0xc0, 0x3f, 0xf0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xf1, 0x83, 0xff, 0xe1, 0xff, + 0xf0, 0xff, 0xf8, 0x7f, 0xfc, 0x3f, 0xfe, 0x1f, + 0x80, 0xf, 0xbb, 0xbf, 0xdb, 0x53, 0xef, 0xae, + 0xf7, 0x54, 0x3, 0x3a, 0x0, + + /* U+F1C2 "" */ + 0x7f, 0x7, 0xfc, 0x3f, 0xb1, 0xfc, 0xcf, 0xe3, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x3f, 0x49, + 0xf8, 0x1f, 0xe4, 0xff, 0x27, 0xf9, 0x3f, 0xff, + 0xcf, 0xfe, + + /* U+F1C3 "" */ + 0x3e, 0x7, 0xfc, 0x3f, 0xf1, 0xfd, 0xcf, 0xe7, + 0x7f, 0x1b, 0xff, 0xff, 0xff, 0xf7, 0xff, 0x93, + 0xfe, 0x3f, 0xf1, 0xff, 0x8f, 0xf9, 0x3f, 0xff, + 0xcf, 0xfe, + + /* U+F1C4 "" */ + 0x3e, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xe7, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xf, 0xf6, + 0xff, 0xf, 0xf7, 0xff, 0x7f, 0xff, 0xf7, 0xfe, + + /* U+F1C5 "" */ + 0x7f, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xff, 0xff, 0xfc, 0xff, 0xcf, 0xff, 0x9f, 0xf0, + 0xfe, 0x7, 0xc0, 0x3c, 0x3, 0xff, 0xf7, 0xfe, + + /* U+F1C6 "" */ + 0x7f, 0x6, 0x3c, 0x31, 0xb1, 0xfc, 0xcc, 0x67, + 0x63, 0x1f, 0xff, 0xf8, 0xff, 0xc7, 0xfe, 0xbf, + 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xcf, 0xfe, + + /* U+F1C7 "" */ + 0x7f, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xe3, 0xff, 0xff, 0xff, 0xf7, 0x7c, 0x73, 0xc6, + 0xbc, 0x6b, 0xc7, 0x3f, 0x77, 0xff, 0xf7, 0xfe, + + /* U+F1C8 "" */ + 0x3e, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xe7, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xe0, + 0x7e, 0x7, 0xe0, 0x7e, 0x1f, 0xff, 0xf7, 0xfe, + + /* U+F1C9 "" */ + 0x7f, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xe3, 0xff, 0xff, 0xff, 0xf6, 0xfe, 0x67, 0xcf, + 0x3e, 0x67, 0xf6, 0xff, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F1CD "" */ + 0x7, 0xe0, 0x1f, 0xf0, 0x78, 0x3c, 0x30, 0x1c, + 0x78, 0x3e, 0xff, 0xf7, 0xcf, 0xe3, 0xcc, 0x63, + 0xcc, 0x63, 0xcc, 0x63, 0xcf, 0xe3, 0x7f, 0xf6, + 0x78, 0x3e, 0x78, 0x3c, 0x3f, 0xf0, 0x7, 0xe0, + + /* U+F1CE "" */ + 0x6, 0x60, 0x1e, 0x78, 0x3c, 0x3c, 0x70, 0xe, + 0x60, 0x6, 0xe0, 0x7, 0xc0, 0x3, 0xc0, 0x3, + 0xc0, 0x3, 0xc0, 0x3, 0xe0, 0x7, 0x60, 0x6, + 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F1D8 "" */ + 0x0, 0x0, 0xc0, 0x1, 0xf0, 0x3, 0xf8, 0x3, + 0xfe, 0x7, 0xff, 0x8f, 0xff, 0xc7, 0xff, 0xf1, + 0xff, 0x7c, 0x1f, 0xbe, 0x1, 0x8f, 0x80, 0x7, + 0xe0, 0x3, 0xf0, 0x0, 0xfc, 0x0, 0x1e, 0x0, + 0x7, 0x80, 0x0, 0xe0, 0x0, 0x30, 0x0, 0x0, + 0x0, + + /* U+F1D9 "" */ + 0x0, 0x0, 0xc0, 0x1, 0xf0, 0x3, 0xf8, 0x3, + 0xfe, 0x7, 0xff, 0x8f, 0xff, 0xc7, 0xff, 0xf1, + 0xff, 0x7c, 0x1f, 0xbe, 0x1, 0x8f, 0x80, 0x7, + 0xe0, 0x3, 0xf0, 0x0, 0xfc, 0x0, 0x1e, 0x0, + 0x7, 0x80, 0x0, 0xe0, 0x0, 0x30, 0x0, 0x0, + 0x0, + + /* U+F1DA "" */ + 0x3, 0xe0, 0xf, 0xf8, 0xdc, 0x1c, 0xf8, 0xe, + 0xf1, 0x86, 0xf9, 0x87, 0xf9, 0x83, 0x1, 0x83, + 0x1, 0xc3, 0x0, 0xe3, 0x0, 0x67, 0x60, 0x6, + 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F1DB "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F1DC "" */ + 0x78, 0x3c, 0xf0, 0x78, 0xc0, 0x61, 0x80, 0xc3, + 0x1, 0x86, 0x3, 0xf, 0xfe, 0x1f, 0xfc, 0x30, + 0x18, 0x60, 0x30, 0xc0, 0x61, 0x80, 0xc7, 0x83, + 0xcf, 0x7, 0x80, + + /* U+F1DD "" */ + 0x1f, 0xfc, 0x7f, 0xf9, 0xfe, 0x63, 0xfc, 0xc7, + 0xf9, 0x8f, 0xf3, 0x1f, 0xe6, 0x3f, 0xcc, 0x3f, + 0x98, 0x3f, 0x30, 0x6, 0x60, 0xc, 0xc0, 0x19, + 0x80, 0x33, 0x0, 0x66, 0x0, 0xcc, + + /* U+F1DE "" */ + 0x0, 0x0, 0xf, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xf, 0x0, 0x0, 0x0, 0x0, 0x78, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x78, 0x0, 0x0, 0x1e, 0x0, + 0xff, 0xff, 0xff, 0xff, 0x1e, 0x0, 0x0, 0x0, + + /* U+F1E0 "" */ + 0x0, 0x3c, 0x0, 0xfc, 0x1, 0xf8, 0x3, 0xf0, + 0x1f, 0xef, 0xff, 0xbf, 0xc0, 0x7e, 0x0, 0xfc, + 0x1, 0xfe, 0x1, 0xff, 0xf0, 0xf, 0xf0, 0x7, + 0xe0, 0xf, 0xc0, 0x1f, 0x80, 0x1e, + + /* U+F1E1 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xfb, 0xff, 0xc7, 0xff, + 0x1f, 0x90, 0xfc, 0x1f, 0xf0, 0x7f, 0xe4, 0x3f, + 0xfc, 0x7f, 0xf1, 0xff, 0xef, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F1E2 "" */ + 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0xc0, 0x1, + 0xe0, 0xfe, 0x61, 0xff, 0x81, 0xc7, 0xe0, 0xcf, + 0xf0, 0xcf, 0xf8, 0x6f, 0xfc, 0x37, 0xfe, 0x1f, + 0xff, 0xf, 0xff, 0x83, 0xff, 0x81, 0xff, 0xc0, + 0x7f, 0xc0, 0xf, 0x80, 0x0, + + /* U+F1E3 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x71, 0x8e, + 0x60, 0x6, 0xf0, 0xf, 0xf1, 0x8f, 0xe3, 0xc7, + 0xc3, 0xc3, 0xc3, 0xc3, 0xe0, 0x7, 0x7c, 0x3e, + 0x7c, 0x3e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F1E4 "" */ + 0x0, 0x0, 0xf, 0xfe, 0x1f, 0xff, 0xcf, 0x83, + 0xef, 0xc0, 0xff, 0xe0, 0xfd, 0xc0, 0x1c, 0x0, + 0x0, 0x0, 0x0, 0x32, 0x49, 0x99, 0x24, 0xc0, + 0x0, 0x6, 0x7f, 0x33, 0x3f, 0x98, + + /* U+F1E5 "" */ + 0x1c, 0x38, 0x1c, 0x38, 0x0, 0x0, 0x3d, 0xbc, + 0x3d, 0xbc, 0x3d, 0xbc, 0x7d, 0xbc, 0x7d, 0xbe, + 0x7c, 0x3e, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0xfc, 0x3f, 0xfc, 0x3f, + + /* U+F1E6 "" */ + 0x18, 0x60, 0x61, 0x81, 0x86, 0x6, 0x18, 0xff, + 0xff, 0xff, 0xf7, 0xff, 0x9f, 0xfe, 0x7f, 0xf9, + 0xff, 0xe3, 0xff, 0xf, 0xfc, 0x1f, 0xe0, 0x1e, + 0x0, 0x30, 0x0, 0xc0, 0x3, 0x0, + + /* U+F1EA "" */ + 0xf, 0xfe, 0x1f, 0xff, 0x18, 0x7f, 0xd8, 0x7f, + 0xd8, 0x7f, 0xd8, 0x63, 0xdf, 0xff, 0xd8, 0x3, + 0xd8, 0x3, 0xdf, 0xff, 0xd8, 0x3, 0xd8, 0x3, + 0xdf, 0xff, 0x7f, 0xfe, + + /* U+F1EB "" */ + 0x3, 0xf0, 0x7, 0xff, 0x83, 0xc0, 0xf1, 0xc0, + 0xe, 0xe0, 0x1, 0xf0, 0x0, 0x20, 0x3f, 0x0, + 0x1f, 0xe0, 0xe, 0x1c, 0x2, 0x1, 0x0, 0x0, + 0x0, 0x3, 0x0, 0x0, 0xc0, 0x0, 0x30, 0x0, + + /* U+F1EC "" */ + 0x7f, 0xef, 0xff, 0xc0, 0x3c, 0x3, 0xc0, 0x3f, + 0xff, 0xd9, 0xbd, 0x9b, 0xff, 0xfd, 0x9b, 0xd9, + 0xbf, 0xff, 0xc1, 0xbc, 0x1b, 0xff, 0xf7, 0xfe, + + /* U+F1F6 "" */ + 0xc0, 0x0, 0x38, 0x30, 0x7, 0x1e, 0x0, 0xff, + 0xe0, 0x1f, 0xf8, 0x3, 0xff, 0x0, 0x7f, 0xc0, + 0xf, 0xf0, 0x9, 0xfc, 0x3, 0x3f, 0x1, 0xe7, + 0xe0, 0x7c, 0xf8, 0x3f, 0x9f, 0xf, 0xf3, 0xc0, + 0x0, 0x70, 0x0, 0xe, 0x1, 0xe1, 0xc0, 0x0, + 0x30, + + /* U+F1F7 "" */ + 0xc0, 0x0, 0x38, 0x30, 0x7, 0x1e, 0x0, 0xff, + 0xe0, 0x1f, 0xf8, 0x3, 0xff, 0x0, 0x7f, 0xc0, + 0xf, 0xf0, 0x9, 0xfc, 0x3, 0x3f, 0x1, 0xe7, + 0xe0, 0x7c, 0xf8, 0x3f, 0x9f, 0xf, 0xf3, 0xc0, + 0x0, 0x70, 0x0, 0xe, 0x1, 0xe1, 0xc0, 0x0, + 0x30, + + /* U+F1F8 "" */ + 0x7, 0x80, 0x3f, 0xf, 0xff, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x9f, 0xfe, 0x7f, 0xf9, + 0xff, 0xe7, 0xff, 0x9f, 0xfe, 0x7f, 0xf9, 0xff, + 0xe7, 0xff, 0x9f, 0xfe, 0x3f, 0xf0, + + /* U+F1F9 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xf8, 0x1f, 0xf9, 0x9f, 0xf3, 0xff, + 0xf3, 0xff, 0xfb, 0xdf, 0xf9, 0x1f, 0x7e, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F1FA "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0xe, + 0x63, 0xc6, 0xe7, 0xf7, 0xce, 0x73, 0xcc, 0x33, + 0xcc, 0x33, 0xce, 0x73, 0xe7, 0xff, 0x63, 0xde, + 0x70, 0x0, 0x3c, 0x0, 0x1f, 0x80, 0x7, 0x80, + + /* U+F1FB "" */ + 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x7f, 0x2, 0xff, + 0x7, 0xff, 0x3, 0xfe, 0x1, 0xfc, 0xc, 0xf8, + 0x1c, 0x70, 0x38, 0x38, 0x71, 0x90, 0x63, 0x80, + 0x67, 0x0, 0x7e, 0x0, 0xfc, 0x0, 0xc0, 0x0, + + /* U+F1FC "" */ + 0x0, 0x1, 0x80, 0x1, 0xf0, 0x0, 0xfc, 0x0, + 0xfe, 0x0, 0x7f, 0x80, 0x7f, 0xc0, 0x1f, 0xe0, + 0x7, 0xf8, 0x0, 0xfc, 0x3, 0x9e, 0x1, 0xf3, + 0x80, 0xfe, 0x80, 0x3f, 0x80, 0xf, 0xe0, 0xf, + 0xf0, 0x3, 0xf8, 0x0, + + /* U+F1FD "" */ + 0x33, 0x30, 0xcc, 0xc3, 0x33, 0x0, 0x0, 0x33, + 0x30, 0xcc, 0xc3, 0x33, 0x1f, 0xfe, 0xff, 0xff, + 0xff, 0xf3, 0x87, 0x0, 0x0, 0xc7, 0x8f, 0xff, + 0xff, 0xff, 0xdf, 0xfe, + + /* U+F1FE "" */ + 0xc0, 0x0, 0xc0, 0x0, 0xc1, 0x0, 0xc3, 0x98, + 0xc7, 0xfc, 0xcf, 0xfe, 0xcf, 0xfe, 0xcf, 0xfe, + 0xcf, 0xfe, 0xcf, 0xfe, 0xc0, 0x0, 0xc0, 0x0, + 0xff, 0xff, 0x7f, 0xff, + + /* U+F200 "" */ + 0x0, 0x60, 0x3, 0x7c, 0x7, 0xbf, 0x7, 0xdf, + 0xc7, 0xef, 0xe3, 0xf7, 0xfb, 0xfb, 0xfd, 0xfc, + 0xfc, 0xfe, 0x0, 0x7f, 0x8f, 0xff, 0xe7, 0xef, + 0xf3, 0xe7, 0xfc, 0xf1, 0xff, 0x30, 0x7f, 0xc0, + 0xf, 0x80, + + /* U+F201 "" */ + 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x6, 0xc1, 0xe, + 0xc3, 0x9c, 0xc7, 0xf8, 0xce, 0xf0, 0xdc, 0x60, + 0xc8, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, + 0xff, 0xff, 0x7f, 0xff, + + /* U+F204 "" */ + 0xf, 0xfc, 0xf, 0xff, 0xc7, 0x0, 0x39, 0x80, + 0x6, 0xce, 0x0, 0xf7, 0xc0, 0x3d, 0xf0, 0xf, + 0x7c, 0x3, 0x6e, 0x1, 0x9c, 0x0, 0xe3, 0xff, + 0xf0, 0x3f, 0xf0, + + /* U+F205 "" */ + 0xf, 0xfc, 0xf, 0xff, 0xc7, 0xff, 0xf9, 0xff, + 0xe, 0xff, 0x81, 0xff, 0xe0, 0x7f, 0xf8, 0x1f, + 0xfe, 0x7, 0x7f, 0xc3, 0x9f, 0xff, 0xe3, 0xff, + 0xf0, 0x3f, 0xf0, + + /* U+F206 "" */ + 0x0, 0x3e, 0x0, 0x6, 0x0, 0x38, 0xc0, 0x7, + 0xc, 0x0, 0x3f, 0x80, 0xe, 0x78, 0xf, 0xcd, + 0xe3, 0xef, 0x7e, 0xec, 0xde, 0xf9, 0xfb, 0x6f, + 0xc, 0x6d, 0xf3, 0x8e, 0x77, 0xe0, 0xfc, 0x78, + 0xf, 0x0, + + /* U+F207 "" */ + 0x7f, 0xfb, 0xe1, 0xff, 0x87, 0xff, 0xff, 0xc3, + 0xf, 0xc, 0x3c, 0x30, 0xf0, 0xc3, 0xff, 0xff, + 0xff, 0xfc, 0xfc, 0xf3, 0xf3, 0xff, 0xfd, 0xff, + 0xe7, 0x3, 0x8c, 0xc, + + /* U+F20A "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, + 0xe0, 0x87, 0xec, 0xb7, 0xef, 0xbf, 0xec, 0xb7, + 0xf1, 0x87, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F20B "" */ + 0xff, 0xf, 0xfe, 0x3c, 0x1c, 0xf0, 0x33, 0xcc, + 0xcf, 0x33, 0x3c, 0xcc, 0xf3, 0x33, 0xcc, 0xcf, + 0x33, 0x3c, 0xc0, 0xf3, 0x7, 0xcf, 0xfb, 0x3f, + 0xc0, + + /* U+F217 "" */ + 0xf0, 0x0, 0xf, 0xff, 0xf1, 0xfd, 0xfc, 0x7f, + 0x7f, 0x1f, 0x7, 0x87, 0xc1, 0xe1, 0xfd, 0xf8, + 0x3f, 0x7e, 0xf, 0xff, 0x2, 0x0, 0x0, 0xc0, + 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x1, 0xc3, 0x80, + 0x70, 0xe0, 0x1c, 0x38, + + /* U+F218 "" */ + 0xf0, 0x0, 0xf, 0xf7, 0xf1, 0xfd, 0xfc, 0x7d, + 0x5f, 0x1f, 0x7, 0x87, 0xe3, 0xe1, 0xfd, 0xf8, + 0x3f, 0xfe, 0xf, 0xff, 0x2, 0x0, 0x0, 0xc0, + 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x1, 0xc3, 0x80, + 0x70, 0xe0, 0x1c, 0x38, + + /* U+F219 "" */ + 0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0xf, 0xf0, + 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, + 0xf, 0xf0, 0x7, 0xe0, 0x3, 0xc0, 0x1, 0x80, + + /* U+F21A "" */ + 0x1, 0xf8, 0x0, 0x1f, 0x80, 0x7, 0xfe, 0x0, + 0xff, 0xf0, 0xc, 0x3, 0x0, 0xc0, 0x30, 0xd, + 0x9b, 0x0, 0xf9, 0xf0, 0x1f, 0x9f, 0x81, 0xf9, + 0xf8, 0x1f, 0x9f, 0x80, 0xf9, 0xf0, 0x0, 0x0, + 0x0, 0x60, 0x60, 0xf, 0x9f, 0xf, 0x8f, 0x1f, + 0x0, 0x0, 0x0, + + /* U+F21B "" */ + 0xf, 0x80, 0xfe, 0x7, 0xf0, 0xff, 0xe3, 0xfe, + 0x1f, 0xf0, 0x77, 0x7, 0x1c, 0x7f, 0xf3, 0xc7, + 0x8c, 0x18, 0x6e, 0xc7, 0x27, 0x7d, 0x7f, 0xff, + 0xff, 0xff, + + /* U+F21C "" */ + 0x1, 0xe0, 0x0, 0x7, 0xc0, 0x0, 0xf8, 0x0, + 0x1f, 0x3, 0xef, 0x80, 0x7, 0xf8, 0xf, 0x79, + 0xe3, 0xf6, 0x7e, 0xe7, 0xde, 0xfb, 0xfb, 0x6f, + 0xc, 0x61, 0xf3, 0xe, 0x77, 0xe0, 0xfc, 0x78, + 0xf, 0x0, + + /* U+F21D "" */ + 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x1, 0x80, + 0x0, 0x0, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, + 0x7, 0xe0, 0x3, 0xc0, 0x1b, 0xd8, 0x7b, 0xde, + 0xc1, 0x83, 0xc0, 0x3, 0x70, 0xe, 0x1f, 0xf8, + + /* U+F21E "" */ + 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff, 0xfb, 0xff, + 0xf9, 0x9f, 0xf1, 0x9f, 0x5, 0x0, 0xe, 0x20, + 0x3e, 0x7c, 0x1e, 0x78, 0x1f, 0xf8, 0xf, 0xf0, + 0x7, 0xe0, 0x1, 0x80, + + /* U+F221 "" */ + 0x1f, 0x7, 0xf1, 0xc7, 0x70, 0x7c, 0x7, 0x80, + 0xf0, 0x1f, 0x7, 0x71, 0xcf, 0xf0, 0x78, 0x6, + 0x0, 0xc0, 0x7e, 0xf, 0xc0, 0x60, 0xc, 0x0, + + /* U+F222 "" */ + 0x0, 0x7e, 0x0, 0xfc, 0x0, 0x78, 0x1, 0xf1, + 0xf7, 0x67, 0xfc, 0xdc, 0x70, 0x70, 0x70, 0xc0, + 0x61, 0x80, 0xc3, 0x1, 0x87, 0x7, 0x7, 0x1c, + 0x7, 0xf0, 0x7, 0xc0, 0x0, + + /* U+F223 "" */ + 0x0, 0xc, 0x31, 0xfe, 0x3f, 0xc7, 0x1d, 0xc1, + 0xf0, 0x1e, 0x3, 0xc0, 0x7c, 0x1d, 0xc7, 0x3f, + 0xc1, 0xe0, 0x18, 0xf, 0xc1, 0xf8, 0xc, 0x1, + 0x80, + + /* U+F224 "" */ + 0x0, 0x7c, 0x1, 0xf0, 0x3, 0xc7, 0xdf, 0x3f, + 0xed, 0xc7, 0xe, 0xe, 0x30, 0x18, 0xc0, 0x63, + 0x1, 0x8e, 0xe, 0x1c, 0x70, 0x3f, 0x80, 0x7c, + 0x0, 0xe0, 0x7, 0xc0, 0x1f, 0x0, 0x38, 0x0, + 0x40, 0x0, + + /* U+F225 "" */ + 0xf8, 0x7, 0xfe, 0x1, 0xfe, 0x0, 0x3f, 0xf0, + 0x1f, 0xdb, 0xfe, 0xc7, 0xff, 0x0, 0x61, 0xc0, + 0x30, 0x30, 0xc, 0xc, 0x3, 0x3, 0x0, 0xc0, + 0xc0, 0x18, 0x60, 0x7, 0xf8, 0x0, 0x78, 0x0, + 0xc, 0x0, 0xf, 0xc0, 0x3, 0xf0, 0x0, 0x30, + 0x0, 0x0, 0x0, + + /* U+F226 "" */ + 0x1f, 0x1f, 0x7, 0xf3, 0xf1, 0xc7, 0x7, 0x70, + 0x70, 0x7c, 0x6, 0x7, 0x80, 0xc0, 0xf0, 0x18, + 0x1f, 0x7, 0x7, 0x71, 0xc1, 0xcf, 0xf3, 0xf0, + 0x78, 0x7c, 0x6, 0x7, 0x0, 0xc0, 0xe0, 0x7e, + 0x3e, 0xf, 0xc7, 0xc0, 0x60, 0x70, 0xc, 0x4, + 0x0, + + /* U+F227 "" */ + 0x0, 0x7e, 0xf0, 0x7, 0xef, 0x0, 0x1e, 0xf0, + 0x3, 0xef, 0x1f, 0x76, 0xb3, 0xfe, 0x63, 0x71, + 0xc0, 0xe, 0xe, 0x70, 0xc0, 0x63, 0xc, 0x6, + 0x30, 0xc0, 0x63, 0xe, 0xe, 0x70, 0x71, 0xce, + 0x3, 0xf9, 0xc0, 0x1f, 0x38, 0x0, + + /* U+F228 "" */ + 0x0, 0x7, 0xe0, 0x0, 0xfc, 0x0, 0x3, 0x8f, + 0x3f, 0xf3, 0xff, 0xf6, 0xe7, 0x8e, 0xf8, 0xf8, + 0xe6, 0x1b, 0xc, 0xc7, 0x61, 0x98, 0x6c, 0x33, + 0x8f, 0x8e, 0x39, 0xe3, 0x87, 0xff, 0xe0, 0x3c, + 0xf8, 0x3, 0x0, 0x1, 0xf8, 0x0, 0x3f, 0x0, + 0x1, 0x80, 0x0, 0x30, 0x0, 0x0, + + /* U+F229 "" */ + 0x0, 0x3f, 0x0, 0x3f, 0x0, 0xf, 0x0, 0x5f, + 0x0, 0x7b, 0x1f, 0x73, 0x3f, 0xf8, 0x71, 0xc0, + 0xe0, 0xe0, 0xc0, 0x60, 0xc0, 0x60, 0xc0, 0x60, + 0xe0, 0xe0, 0x71, 0xc0, 0x3f, 0x80, 0x1f, 0x0, + + /* U+F22A "" */ + 0xc, 0x3, 0xc0, 0xfc, 0x16, 0x80, 0xc0, 0x7e, + 0xf, 0xc0, 0x60, 0x3f, 0xf, 0xfb, 0x83, 0x60, + 0x3c, 0x7, 0x80, 0xf8, 0x3b, 0x8e, 0x3f, 0x83, + 0xe0, + + /* U+F22B "" */ + 0x0, 0x0, 0xf, 0xc0, 0x7, 0xf8, 0x1, 0x87, + 0x6c, 0xc0, 0xd9, 0xb0, 0x3f, 0xfc, 0xf, 0xff, + 0x3, 0x66, 0xe0, 0xdb, 0x1c, 0x60, 0x3, 0xf8, + 0x0, 0x78, 0x0, + + /* U+F22C "" */ + 0x1e, 0xf, 0xc6, 0x3b, 0x87, 0xc0, 0xf0, 0x3c, + 0xf, 0x87, 0x63, 0x9f, 0xc1, 0xe0, 0x30, 0xc, + 0x3, 0x0, 0xc0, 0x30, 0xc, 0x0, + + /* U+F22D "" */ + 0xf, 0x3, 0xfc, 0x70, 0xe6, 0x6, 0xc0, 0x3c, + 0x3, 0xc0, 0x3c, 0x3, 0x60, 0x67, 0xe, 0x3f, + 0xc0, 0xf0, + + /* U+F233 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xf2, 0xff, 0xcb, 0xff, + 0xfd, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x7f, 0xfb, + 0xff, 0xff, 0xf2, 0xff, 0xcb, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F234 "" */ + 0x7, 0x0, 0x3, 0xe0, 0x1, 0xfc, 0x0, 0x7f, + 0xc, 0x1f, 0xc3, 0x7, 0xf1, 0xf0, 0xf8, 0x7c, + 0x1c, 0xc, 0x0, 0x3, 0x0, 0x0, 0x1, 0xfc, + 0x0, 0xff, 0x80, 0x7f, 0xf0, 0x3f, 0xfe, 0xf, + 0xff, 0x83, 0xff, 0xe0, + + /* U+F235 "" */ + 0xf, 0x80, 0x7, 0xf0, 0x1, 0xfc, 0x0, 0x7f, + 0x1b, 0x1f, 0xc3, 0xc7, 0xf0, 0xe0, 0xf8, 0x3c, + 0x0, 0x1b, 0x0, 0x0, 0x7, 0xf0, 0x3, 0xfe, + 0x1, 0xff, 0xc0, 0xff, 0xf8, 0x3f, 0xfe, 0xf, + 0xff, 0x80, + + /* U+F236 "" */ + 0xc0, 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x31, + 0xfe, 0xde, 0x7f, 0xf7, 0x9f, 0xfc, 0xc7, 0xff, + 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0, 0x3, 0xc0, 0x0, 0xf0, 0x0, 0x30, + + /* U+F238 "" */ + 0x7f, 0xef, 0xff, 0xff, 0xfc, 0x3, 0xc0, 0x3c, + 0x3, 0xc0, 0x3c, 0x3, 0xff, 0xff, 0xff, 0xf9, + 0xff, 0x9f, 0xff, 0xf7, 0xfe, 0x60, 0x6c, 0x3, + 0xc0, 0x30, + + /* U+F239 "" */ + 0x7f, 0xef, 0xff, 0xff, 0xfc, 0x63, 0xc6, 0x3c, + 0x63, 0xc6, 0x3c, 0x63, 0xff, 0xff, 0xff, 0xcf, + 0x3c, 0xf3, 0xff, 0xf7, 0xfe, 0x60, 0x6c, 0x3, + 0xc0, 0x10, + + /* U+F240 "" */ + 0x7f, 0xff, 0x9f, 0xff, 0xfb, 0x0, 0x3, 0x60, + 0x0, 0x6d, 0xff, 0xcd, 0xbf, 0xf9, 0xf7, 0xff, + 0x3e, 0xff, 0xe7, 0xdf, 0xfc, 0xd8, 0x0, 0x1b, + 0xff, 0xff, 0x3f, 0xff, 0xc0, + + /* U+F241 "" */ + 0x7f, 0xff, 0x9f, 0xff, 0xfb, 0x0, 0x3, 0x60, + 0x0, 0x6d, 0xff, 0xd, 0xbf, 0xe1, 0xf7, 0xfc, + 0x3e, 0xff, 0x87, 0xdf, 0xf0, 0xd8, 0x0, 0x1b, + 0xff, 0xff, 0x3f, 0xff, 0xc0, + + /* U+F242 "" */ + 0x7f, 0xff, 0x9f, 0xff, 0xfb, 0x0, 0x3, 0x60, + 0x0, 0x6d, 0xf8, 0xd, 0xbf, 0x1, 0xf7, 0xe0, + 0x3e, 0xfc, 0x7, 0xdf, 0x80, 0xd8, 0x0, 0x1b, + 0xff, 0xff, 0x3f, 0xff, 0xc0, + + /* U+F243 "" */ + 0x7f, 0xff, 0x9f, 0xff, 0xfb, 0x0, 0x3, 0x60, + 0x0, 0x6d, 0xe0, 0xd, 0xbc, 0x1, 0xf7, 0x80, + 0x3e, 0xf0, 0x7, 0xde, 0x0, 0xd8, 0x0, 0x1b, + 0xff, 0xff, 0x3f, 0xff, 0xc0, + + /* U+F244 "" */ + 0x7f, 0xff, 0x9f, 0xff, 0xfb, 0x0, 0x3, 0x60, + 0x0, 0x6c, 0x0, 0xf, 0x80, 0x1, 0xf0, 0x0, + 0x3e, 0x0, 0x7, 0xc0, 0x0, 0xd8, 0x0, 0x1b, + 0xff, 0xff, 0x3f, 0xff, 0xc0, + + /* U+F245 "" */ + 0xc0, 0xe, 0x0, 0xf0, 0xf, 0xc0, 0xfe, 0xf, + 0xf0, 0xff, 0xcf, 0xfe, 0xff, 0xef, 0xc0, 0xf6, + 0xe, 0x60, 0xc7, 0xc, 0x30, 0x3, 0x80, 0x18, + + /* U+F246 "" */ + 0xe7, 0xff, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x7e, + 0x7e, 0x18, 0x18, 0x18, 0x18, 0x3c, 0xff, 0xe7, + + /* U+F247 "" */ + 0x60, 0x1, 0xbf, 0xff, 0xff, 0xff, 0xfd, 0x80, + 0x6, 0x67, 0x81, 0x9b, 0xf0, 0x66, 0xfc, 0x19, + 0xbf, 0x66, 0x67, 0x9d, 0x98, 0xf, 0x66, 0xf, + 0xd9, 0x81, 0xe6, 0x60, 0x1, 0xbf, 0xff, 0xff, + 0xff, 0xfd, 0x80, 0x6, + + /* U+F248 "" */ + 0x60, 0x18, 0xf, 0xff, 0xc0, 0xff, 0xfc, 0x6, + 0x1, 0x80, 0x60, 0x18, 0x6, 0x1, 0x86, 0x60, + 0x1b, 0xf6, 0x1, 0x9f, 0xff, 0xfc, 0x6f, 0xff, + 0xc6, 0x60, 0x18, 0x60, 0x18, 0x6, 0x1, 0x80, + 0x60, 0x3f, 0xff, 0x3, 0xff, 0xf0, 0x18, 0x6, + + /* U+F249 "" */ + 0x7f, 0xfd, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x8d, 0xff, 0x3b, 0xfe, 0xe7, 0xff, 0x8f, 0xfe, + 0x7, 0xf0, 0x0, + + /* U+F24A "" */ + 0x7f, 0xfd, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x8d, 0xff, 0x3b, 0xfe, 0xe7, 0xff, 0x8f, 0xfe, + 0x7, 0xf0, 0x0, + + /* U+F24D "" */ + 0x3, 0xfe, 0x7, 0xff, 0x7, 0xff, 0x7, 0xff, + 0x7, 0xff, 0x77, 0xff, 0xf7, 0xff, 0xc7, 0xff, + 0xc7, 0xff, 0xc7, 0xff, 0xc3, 0xfe, 0xc0, 0x0, + 0xc0, 0x60, 0xc0, 0x60, 0xff, 0xe0, 0x7f, 0xc0, + + /* U+F24E "" */ + 0x0, 0x60, 0x1, 0xff, 0xf8, 0x1f, 0xff, 0x80, + 0xf, 0x0, 0x18, 0xe1, 0x81, 0x86, 0x18, 0x3c, + 0x63, 0xc6, 0x46, 0x66, 0x66, 0x66, 0x6c, 0x36, + 0xc3, 0xff, 0x6f, 0xff, 0xe6, 0x7e, 0x3c, 0x63, + 0xc0, 0x6, 0x0, 0x1f, 0xff, 0x81, 0xff, 0xf8, + + /* U+F250 "" */ + 0xff, 0xff, 0xff, 0x60, 0x66, 0x6, 0x70, 0xc3, + 0x9c, 0x1f, 0x80, 0xf0, 0xf, 0x1, 0xf8, 0x39, + 0xc7, 0xc, 0x60, 0x66, 0x6, 0xff, 0xff, 0xff, + + /* U+F251 "" */ + 0xff, 0xff, 0xff, 0x7f, 0xe7, 0xfe, 0x7f, 0xc3, + 0xfc, 0x1f, 0x80, 0xf0, 0xf, 0x1, 0xf8, 0x39, + 0xc7, 0xc, 0x60, 0x66, 0x6, 0xff, 0xff, 0xff, + + /* U+F252 "" */ + 0xff, 0xff, 0xff, 0x60, 0x66, 0x6, 0x7f, 0xc3, + 0xfc, 0x1f, 0x80, 0xf0, 0xf, 0x1, 0xf8, 0x39, + 0xc7, 0xc, 0x7f, 0xe7, 0xfe, 0xff, 0xff, 0xff, + + /* U+F253 "" */ + 0xff, 0xff, 0xff, 0x60, 0x66, 0x6, 0x70, 0xc3, + 0x9c, 0x1f, 0x80, 0xf0, 0xf, 0x1, 0xf8, 0x3f, + 0xc7, 0xfc, 0x7f, 0xe7, 0xfe, 0xff, 0xff, 0xff, + + /* U+F254 "" */ + 0xff, 0xff, 0xff, 0x60, 0x66, 0x6, 0x70, 0xc3, + 0x9c, 0x1f, 0x80, 0xf0, 0xf, 0x1, 0xf8, 0x39, + 0xc7, 0xc, 0x60, 0x66, 0x6, 0xff, 0xff, 0xff, + + /* U+F255 "" */ + 0x16, 0x3, 0xfc, 0x3f, 0xe3, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x3f, + 0xc0, 0x0, 0x0, 0x7, 0xfe, 0x7f, 0xe7, 0xfe, + + /* U+F256 "" */ + 0x1, 0x80, 0x1b, 0x60, 0x36, 0xc0, 0x6d, 0xb0, + 0xdb, 0x61, 0xb6, 0xc3, 0x6d, 0x86, 0xdb, 0xf, + 0xff, 0xdf, 0xff, 0xff, 0xfb, 0xff, 0xf3, 0xff, + 0xe3, 0xff, 0x83, 0xfe, 0x1, 0xf8, + + /* U+F257 "" */ + 0x0, 0x18, 0x1e, 0x1f, 0xf, 0xe3, 0xc1, 0xff, + 0xf0, 0x1f, 0xfb, 0xff, 0xfd, 0xff, 0xfe, 0x3, + 0xff, 0x1, 0xff, 0x80, 0x7f, 0xc0, 0x3f, 0xc0, + 0x1f, 0xc0, + + /* U+F258 "" */ + 0xff, 0xe0, 0xff, 0xf0, 0xff, 0xf8, 0x0, 0x78, + 0x0, 0x7c, 0x0, 0x7e, 0x3f, 0xfe, 0x3f, 0xff, + 0x3f, 0xff, 0x0, 0x7f, 0x0, 0x1f, 0x0, 0x1f, + + /* U+F259 "" */ + 0x6, 0x0, 0x6, 0x18, 0x6, 0x18, 0x36, 0x1b, + 0x3b, 0x1b, 0x1b, 0x3b, 0x1b, 0x36, 0x1f, 0xb6, + 0xf, 0xfe, 0xef, 0xfc, 0xff, 0xfc, 0x7f, 0xfc, + 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf8, 0x3, 0xe0, + + /* U+F25A "" */ + 0x4, 0x0, 0x1c, 0x0, 0x38, 0x0, 0x70, 0x0, + 0xe0, 0x1, 0xc0, 0x3, 0xe8, 0x7, 0xfe, 0xf, + 0xff, 0xdd, 0x5f, 0xba, 0xbb, 0xf5, 0x73, 0xea, + 0xc7, 0xff, 0x87, 0xff, 0x3, 0xf8, + + /* U+F25B "" */ + 0x6, 0x6, 0x30, 0x19, 0x80, 0xcc, 0x7, 0x60, + 0x1b, 0x60, 0xdb, 0x60, 0x1b, 0x0, 0xd9, 0xf0, + 0xdf, 0xb8, 0xe3, 0xf7, 0xff, 0x9f, 0xf8, 0xff, + 0xc1, 0xf8, + + /* U+F25C "" */ + 0xff, 0x60, 0x7f, 0xee, 0x1c, 0x61, 0xc3, 0x8c, + 0x3c, 0xf1, 0x87, 0xfe, 0x30, 0xde, 0xc6, 0x1b, + 0xd8, 0xc3, 0x33, 0x18, 0x60, 0x63, 0xc, 0xc, + + /* U+F25D "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7c, 0x3e, 0xfc, 0x1f, 0xfd, 0x9f, 0xfd, 0x9f, + 0xfc, 0x3f, 0xfd, 0x7f, 0xfd, 0x3f, 0x7d, 0xbe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F26C "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xfc, 0x0, 0xf, 0x0, + 0x3, 0xc0, 0x0, 0xf0, 0x0, 0x3c, 0x0, 0xf, + 0x0, 0x3, 0xc0, 0x0, 0xf0, 0x0, 0x3f, 0xff, + 0xfd, 0xff, 0xfe, 0x0, 0x0, 0x3, 0xff, 0x0, + 0xff, 0xc0, + + /* U+F271 "" */ + 0x18, 0x60, 0x61, 0x87, 0xff, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xf0, 0x3f, + 0xc0, 0xff, 0xcf, 0xff, 0x3f, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F272 "" */ + 0x18, 0x60, 0x61, 0x87, 0xff, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, + 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F273 "" */ + 0x18, 0x60, 0x61, 0x87, 0xff, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xb7, 0xfe, 0x1f, 0xfc, 0x7f, + 0xf1, 0xff, 0x87, 0xfe, 0xdf, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F274 "" */ + 0x18, 0x60, 0x61, 0x8f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x7f, 0xfb, 0xff, 0xcf, 0xe6, 0x7f, + 0x93, 0xff, 0x1f, 0xfe, 0x7f, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F275 "" */ + 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0xc3, + 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + + /* U+F276 "" */ + 0x1e, 0x1c, 0xce, 0x3b, 0x3e, 0xcf, 0xff, 0xe7, + 0xf9, 0xfc, 0x1e, 0x3, 0x0, 0xc0, 0x30, 0xc, + 0x3, 0x0, 0xc0, 0x30, + + /* U+F277 "" */ + 0x1, 0x80, 0x1, 0x80, 0x7f, 0xfe, 0x7f, 0xff, + 0x7f, 0xff, 0x7f, 0xfc, 0x1, 0x80, 0x1, 0x80, + 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfe, + 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, + + /* U+F278 "" */ + 0x0, 0x0, 0x1f, 0x7, 0x7f, 0xff, 0xfc, 0xff, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0xff, 0x3f, 0xff, 0xfe, 0xe0, 0xf8, 0x0, 0x0, + + /* U+F279 "" */ + 0x0, 0x0, 0x1f, 0x7, 0x7f, 0xff, 0xfc, 0xff, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0xff, 0x3f, 0xff, 0xfe, 0xe0, 0xf8, 0x0, 0x0, + + /* U+F27A "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, 0xf, 0x0, 0xe, 0x0, 0xc, 0x0, + + /* U+F27B "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xe6, 0x67, 0xe6, 0x67, + 0xe6, 0x67, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfc, 0x7f, 0xf8, 0xff, 0xe0, 0xc0, 0x0, + + /* U+F283 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xc6, 0x3f, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F28B "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0x9f, 0xf9, 0x9f, 0xf9, 0x9f, + 0xf9, 0x9f, 0xf9, 0x9f, 0xf9, 0x9f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F28C "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0x9f, 0xf9, 0x9f, 0xf9, 0x9f, + 0xf9, 0x9f, 0xf9, 0x9f, 0xf9, 0x9f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F28D "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F28E "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F290 "" */ + 0x7, 0x80, 0x12, 0x0, 0x84, 0x2, 0x10, 0x8, + 0x43, 0xff, 0xff, 0xff, 0xfd, 0xef, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xdf, 0xfe, + + /* U+F291 "" */ + 0x0, 0x80, 0x0, 0xe0, 0x0, 0xd8, 0x0, 0xc6, + 0x0, 0xc1, 0x87, 0xff, 0xff, 0xff, 0xfe, 0xf6, + 0xde, 0x7b, 0x6f, 0x3d, 0xb7, 0x8e, 0xdb, 0xc7, + 0x6d, 0xc3, 0xb6, 0xe1, 0xff, 0xf0, 0x7f, 0xf0, + + /* U+F292 "" */ + 0x2, 0xc, 0x6, 0xc, 0x6, 0x18, 0x6, 0x18, + 0x7f, 0xff, 0x7f, 0xff, 0xc, 0x38, 0xc, 0x30, + 0xc, 0x30, 0x1c, 0x30, 0xff, 0xfe, 0xff, 0xfe, + 0x18, 0x60, 0x18, 0x60, 0x30, 0x60, 0x30, 0x40, + + /* U+F295 "" */ + 0x78, 0xf, 0xf0, 0x7f, 0xc3, 0xbf, 0x1c, 0xfc, + 0xe1, 0xe7, 0x0, 0x38, 0x1, 0xc0, 0xe, 0x78, + 0x73, 0xf3, 0x8f, 0xdc, 0x3f, 0xe0, 0xff, 0x1, + 0xe0, + + /* U+F29A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3e, 0x7c, 0x7e, 0x7e, + 0x7e, 0x7e, 0xfb, 0xdf, 0xf8, 0x1f, 0xfe, 0x7f, + 0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0x7f, 0x7d, 0x3e, + 0x7d, 0xbe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F29C "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfc, 0x3f, 0xfd, 0xbf, 0xfd, 0xbf, + 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F29D "" */ + 0xe, 0x0, 0x1e, 0x0, 0xe, 0x0, 0x0, 0x0, + 0x1e, 0x0, 0x3f, 0x0, 0x7f, 0x80, 0xdf, 0xc0, + 0xde, 0xc0, 0xde, 0x40, 0x1e, 0x0, 0xf, 0x30, + 0x13, 0x98, 0x19, 0x98, 0x39, 0x8c, 0x71, 0x86, + 0xe1, 0xc3, 0x0, 0x83, + + /* U+F29E "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, + 0xe0, 0x87, 0xec, 0xb7, 0xec, 0xb7, 0xec, 0xb7, + 0xec, 0x8f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F2A0 "" */ + 0x0, 0x70, 0x1c, 0x6, 0x1e, 0x1, 0x9f, 0x8e, + 0x6f, 0xc1, 0xb7, 0xe0, 0x6f, 0xf1, 0xb7, 0xf0, + 0xdb, 0x78, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3, + 0xe7, 0x81, 0xfb, 0xf0, 0x7f, 0xf8, 0xf, 0xfc, + 0x3, 0xfc, 0x0, 0x7c, 0x0, + + /* U+F2A1 "" */ + 0x70, 0xef, 0x9f, 0xf9, 0xff, 0x9f, 0x70, 0xe0, + 0x0, 0x70, 0xef, 0x9b, 0xf9, 0xb7, 0xe, 0x0, + 0x7, 0xe, 0xf9, 0xfd, 0x9b, 0xd9, 0xbf, 0x9f, + 0x70, 0xe0, + + /* U+F2A2 "" */ + 0x0, 0x1c, 0x0, 0x1e, 0x7, 0xc6, 0xf, 0xe7, + 0x1c, 0x73, 0x3b, 0xbb, 0x36, 0xda, 0x36, 0xd8, + 0x0, 0x18, 0x0, 0x38, 0xc, 0x70, 0x6c, 0x60, + 0x70, 0x60, 0x38, 0xe0, 0xd9, 0xc0, 0xc1, 0x80, + + /* U+F2A3 "" */ + 0x19, 0x80, 0x1, 0xb8, 0x0, 0x37, 0x0, 0x3, + 0xfc, 0x0, 0x7f, 0xcf, 0xc7, 0xf1, 0xfe, 0xff, + 0x99, 0xff, 0xf9, 0x1f, 0xf8, 0x9f, 0xff, 0x99, + 0xff, 0x7f, 0x8f, 0xe3, 0xf3, 0xfe, 0x0, 0x3f, + 0xc0, 0x0, 0xec, 0x0, 0x1d, 0x80, 0x1, 0x98, + + /* U+F2A4 "" */ + 0x0, 0x3, 0x0, 0x7, 0x7, 0xc6, 0xf, 0xe0, + 0x1c, 0x70, 0x3b, 0xb8, 0x36, 0xd8, 0x36, 0xd8, + 0x0, 0x18, 0x0, 0x38, 0xc, 0x70, 0x1c, 0x60, + 0x38, 0x60, 0x70, 0xe0, 0xe1, 0xc0, 0xc1, 0x80, + + /* U+F2A7 "" */ + 0x0, 0x40, 0x3, 0x40, 0x1, 0xe0, 0x6, 0xb0, + 0x0, 0x33, 0x9, 0x1f, 0xd, 0xcf, 0x0, 0xe7, + 0x7f, 0xf3, 0x3, 0xfa, 0xff, 0xf8, 0x3, 0xf8, + 0x7f, 0xf8, 0x3, 0xf0, 0x3, 0xf0, 0x3f, 0xc0, + + /* U+F2A8 "" */ + 0x40, 0x0, 0xc, 0x0, 0x0, 0xcf, 0xe0, 0xf, + 0xff, 0x0, 0xf0, 0xf0, 0x4e, 0xf, 0xc, 0xfd, + 0xf0, 0xcf, 0x9e, 0x4c, 0xf3, 0xec, 0xce, 0x7c, + 0xcc, 0xef, 0xc, 0xc7, 0xc0, 0xcc, 0x70, 0xc, + 0xc6, 0x0, 0x8c, 0x60, 0x0, 0x6, 0x0, 0x0, + 0x60, 0x0, 0x0, + + /* U+F2B4 "" */ + 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0xff, 0xf7, + 0xff, 0xef, 0xff, 0x9f, 0xff, 0x3f, 0xfc, 0x7f, + 0xf8, 0xff, 0xf1, 0xff, 0xf3, 0xff, 0xe7, 0xff, + 0xef, 0xff, 0xd0, 0x0, 0x20, 0x0, + + /* U+F2B5 "" */ + 0x80, 0x0, 0x7b, 0x9f, 0x7f, 0xcf, 0xff, 0xe7, + 0xff, 0xf3, 0xff, 0xf9, 0xe7, 0xfe, 0x30, 0xff, + 0xc1, 0x9f, 0xfd, 0xf3, 0xff, 0xfe, 0x73, 0xff, + 0xc0, 0x7f, 0xf0, 0xf, 0xe4, 0x0, 0xcc, 0x0, + + /* U+F2B6 "" */ + 0x0, 0x0, 0x3, 0xc0, 0x7, 0xe0, 0x1e, 0x78, + 0x38, 0x1c, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, + 0xf0, 0xf, 0xf8, 0x1f, 0xfe, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F2B7 "" */ + 0x0, 0x0, 0x3, 0xc0, 0x7, 0xe0, 0x1e, 0x78, + 0x38, 0x1c, 0x70, 0xe, 0xe0, 0x7, 0xe0, 0x7, + 0xf0, 0xf, 0xf8, 0x1f, 0xfe, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F2B9 "" */ + 0x7f, 0xf1, 0xff, 0xf3, 0xff, 0xef, 0xff, 0xdf, + 0xdf, 0xbf, 0x1f, 0x3e, 0x3e, 0xfc, 0x7d, 0xff, + 0xfb, 0xe0, 0xf3, 0x80, 0xef, 0x1, 0xdf, 0xff, + 0xbf, 0xff, 0x3f, 0xfe, 0x3f, 0xf8, + + /* U+F2BA "" */ + 0x7f, 0xf1, 0xff, 0xf3, 0xff, 0xef, 0xff, 0xdf, + 0xdf, 0xbf, 0x1f, 0x3e, 0x3e, 0xfc, 0x7d, 0xff, + 0xfb, 0xe0, 0xf3, 0x80, 0xef, 0x1, 0xdf, 0xff, + 0xbf, 0xff, 0x3f, 0xfe, 0x3f, 0xf8, + + /* U+F2BB "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xc7, + 0x7, 0xf1, 0xc1, 0xfc, 0x7f, 0xff, 0x3f, 0xff, + 0xff, 0x7, 0xe0, 0xff, 0xf0, 0x3f, 0xfc, 0xf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xe0, + + /* U+F2BC "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xc7, + 0x7, 0xf1, 0xc1, 0xfc, 0x7f, 0xff, 0x3f, 0xff, + 0xff, 0x7, 0xe0, 0xff, 0xf0, 0x3f, 0xfc, 0xf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xe0, + + /* U+F2BD "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0xfe, 0x7f, 0xff, 0xff, 0xf8, 0x1f, 0x70, 0xe, + 0x70, 0xe, 0x3c, 0x1c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F2BE "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0xfe, 0x7f, 0xff, 0xff, 0xf8, 0x1f, 0x70, 0xe, + 0x70, 0xe, 0x3c, 0x1c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F2C0 "" */ + 0x7, 0x0, 0xfe, 0x7, 0xf0, 0x3f, 0x81, 0xfc, + 0xf, 0xe0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0xfe, + 0xf, 0xf8, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xe0, + + /* U+F2C1 "" */ + 0x7f, 0xef, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf9, 0xff, 0x9f, 0xf9, 0xff, 0x9f, 0xff, + 0xff, 0xf, 0xe0, 0x7e, 0x7, 0xff, 0xf7, 0xfe, + + /* U+F2C2 "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xf0, 0x0, 0x3, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x78, 0x7f, 0x1e, 0x1f, + 0xc7, 0xff, 0xf1, 0xff, 0xff, 0xf8, 0x7e, 0xf, + 0xff, 0x3, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xe0, + + /* U+F2C3 "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xf0, 0x0, 0x3, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x78, 0x7f, 0x1e, 0x1f, + 0xc7, 0xff, 0xf1, 0xff, 0xff, 0xf8, 0x7e, 0xf, + 0xff, 0x3, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xe0, + + /* U+F2C7 "" */ + 0x1e, 0xf, 0xc3, 0x30, 0xcc, 0x33, 0xc, 0xc3, + 0x30, 0xcc, 0x33, 0x1c, 0xef, 0x1b, 0x87, 0xe1, + 0xbc, 0xe7, 0xf0, 0xf8, + + /* U+F2C8 "" */ + 0x1e, 0xf, 0xc3, 0xf0, 0xfc, 0x33, 0xc, 0xc3, + 0x30, 0xcc, 0x33, 0x1c, 0xef, 0x1b, 0x87, 0xe1, + 0xbc, 0xe7, 0xf0, 0xf8, + + /* U+F2C9 "" */ + 0x1e, 0xf, 0xc3, 0xf0, 0xfc, 0x3f, 0xf, 0xc3, + 0x30, 0xcc, 0x33, 0x1c, 0xef, 0x1b, 0x87, 0xe1, + 0xbc, 0xe7, 0xf0, 0xf8, + + /* U+F2CA "" */ + 0x1c, 0x1f, 0xf, 0x87, 0xc3, 0xe1, 0xf0, 0xf8, + 0x7c, 0x77, 0x3b, 0xb8, 0xfc, 0x7e, 0x3f, 0xbd, + 0xfc, 0x7c, + + /* U+F2CB "" */ + 0x1c, 0x1f, 0xf, 0x87, 0xc3, 0xe1, 0xf0, 0xf8, + 0x7c, 0x7f, 0x7b, 0xf8, 0xfc, 0x7e, 0x3f, 0xb9, + 0xfc, 0x78, + + /* U+F2CC "" */ + 0x78, 0x0, 0xff, 0x80, 0xcf, 0xe0, 0xcf, 0xc0, + 0xcf, 0x98, 0xcf, 0x1b, 0xc6, 0x63, 0xc4, 0x6c, + 0xc1, 0x8c, 0xc1, 0xb0, 0xc0, 0x30, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0x0, + + /* U+F2CD "" */ + 0x38, 0x0, 0x7f, 0x0, 0x6f, 0x80, 0x6f, 0x0, + 0x6e, 0x0, 0x64, 0x0, 0x60, 0x0, 0x60, 0x0, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x3f, 0xfc, 0x30, 0xc, + + /* U+F2CE "" */ + 0xf, 0xc0, 0x61, 0x83, 0x3, 0x19, 0xe6, 0xcc, + 0xcf, 0x61, 0xbd, 0xb6, 0xf6, 0xdb, 0xd8, 0x4f, + 0x0, 0x76, 0x31, 0x8d, 0xec, 0x17, 0xa0, 0xc, + 0x0, 0x30, 0x0, 0xc0, + + /* U+F2D0 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xc0, 0x3, 0xc0, 0x3, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F2D1 "" */ + 0xff, 0xff, 0xff, 0xff, + + /* U+F2D2 "" */ + 0x3, 0xff, 0x81, 0xff, 0xf0, 0x0, 0xc, 0x0, + 0x3, 0x7f, 0xf0, 0xff, 0xfe, 0x3c, 0x1, 0x8f, + 0x0, 0x63, 0xff, 0xfb, 0xff, 0xfe, 0xef, 0xff, + 0x83, 0xff, 0xe0, 0xff, 0xf8, 0x1f, 0xfc, 0x0, + + /* U+F2D3 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, + 0x3f, 0xc0, 0xff, 0x87, 0xfe, 0x1f, 0xf0, 0x3f, + 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F2D4 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9f, + 0xf8, 0x1f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf8, 0x1f, + 0xf9, 0x9f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F2DB "" */ + 0x9, 0x90, 0xd, 0xb0, 0x1f, 0xf8, 0x3f, 0xfc, + 0xf0, 0xf, 0x77, 0xee, 0x37, 0xec, 0xf7, 0xef, + 0xf7, 0xef, 0x37, 0xec, 0x77, 0xee, 0xf0, 0xf, + 0x3f, 0xfc, 0x1f, 0xf8, 0xd, 0xb0, 0x9, 0x90, + + /* U+F2DC "" */ + 0x1, 0x80, 0x1, 0x80, 0x7, 0xe0, 0x7, 0xe0, + 0xdb, 0xdb, 0xf9, 0x9f, 0x3d, 0xbc, 0x7f, 0xfe, + 0x7, 0xe0, 0x7, 0xe0, 0x7f, 0xfe, 0x3d, 0xbc, + 0xf9, 0x9f, 0xdb, 0xdb, 0x7, 0xe0, 0x7, 0xe0, + 0x1, 0x80, 0x1, 0x80, + + /* U+F2E5 "" */ + 0x0, 0x1e, 0x0, 0x7f, 0x0, 0xff, 0x1, 0xff, + 0x1, 0xff, 0x1, 0xfe, 0x1, 0xfe, 0x1, 0xfc, + 0x3, 0xf8, 0x7, 0x0, 0xe, 0x0, 0x1c, 0x0, + 0x38, 0x0, 0x70, 0x0, 0xe0, 0x0, 0xc0, 0x0, + + /* U+F2E7 "" */ + 0x5a, 0x6, 0xb4, 0x3d, 0x68, 0x7a, 0xd1, 0xf5, + 0xa3, 0xff, 0xc7, 0xdf, 0x8f, 0x9e, 0x1f, 0x18, + 0x3e, 0x30, 0x7c, 0x60, 0x78, 0xc0, 0x31, 0x80, + 0x63, 0x0, 0xc6, 0x1, 0x8c, 0x3, + + /* U+F2EA "" */ + 0x0, 0x0, 0x63, 0xf8, 0x3f, 0xfe, 0x1f, 0x1, + 0x8f, 0x80, 0x67, 0xe0, 0x39, 0xf0, 0xc, 0x0, + 0x6, 0x0, 0x3, 0x0, 0x1, 0x80, 0x0, 0xc0, + 0x0, 0x62, 0x0, 0x71, 0x80, 0x30, 0xe0, 0x70, + 0x3f, 0xf0, 0x7, 0xf0, 0x0, 0x0, 0x0, + + /* U+F2ED "" */ + 0x7, 0x80, 0x3f, 0xf, 0xff, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x9f, 0xfe, 0x6c, 0xd9, + 0xb3, 0x66, 0xcd, 0x9b, 0x36, 0x6c, 0xd9, 0xb3, + 0x66, 0xcd, 0x9f, 0xfe, 0x3f, 0xf0, + + /* U+F2F1 "" */ + 0x7, 0xe3, 0x1f, 0xff, 0x3c, 0x3f, 0x70, 0x1f, + 0x60, 0x3f, 0xe0, 0x3f, 0xc0, 0x0, 0xc0, 0x0, + 0x0, 0x3, 0x0, 0x3, 0xfc, 0x7, 0xfc, 0x6, + 0xf8, 0xe, 0xfc, 0x3c, 0xff, 0xf8, 0xc7, 0xe0, + + /* U+F2F2 "" */ + 0xf, 0x80, 0x10, 0x3, 0xe0, 0x7f, 0xf7, 0xff, + 0xbe, 0xfb, 0xf7, 0xff, 0xbf, 0xfd, 0xff, 0xef, + 0xff, 0xff, 0xff, 0xf7, 0xff, 0x1f, 0xf0, 0x7f, + 0x1, 0xf0, + + /* U+F2F5 "" */ + 0x7c, 0x0, 0xfc, 0x0, 0xc0, 0x30, 0xc0, 0x38, + 0xc0, 0x3c, 0xc7, 0xfe, 0xc7, 0xff, 0xc7, 0xff, + 0xc7, 0xfe, 0xc0, 0x3c, 0xc0, 0x38, 0xc0, 0x30, + 0xfc, 0x0, 0x7c, 0x0, + + /* U+F2F6 "" */ + 0x0, 0x3e, 0x0, 0x3f, 0x6, 0x3, 0x7, 0x3, + 0x7, 0x83, 0xff, 0xc3, 0xff, 0xe3, 0xff, 0xe3, + 0xff, 0xc3, 0x7, 0x83, 0x7, 0x3, 0x6, 0x3, + 0x0, 0x3f, 0x0, 0x3e, + + /* U+F2F9 "" */ + 0x0, 0x0, 0x3, 0xf8, 0xc3, 0xff, 0xe3, 0x1, + 0xf3, 0x0, 0xfb, 0x0, 0xfd, 0x80, 0x7c, 0xc0, + 0x0, 0x60, 0x0, 0x30, 0x0, 0x18, 0x0, 0xc, + 0x0, 0x7, 0x0, 0x21, 0x80, 0x30, 0x70, 0x38, + 0x1f, 0xf8, 0x7, 0xf0, 0x0, 0x0, 0x0, + + /* U+F2FE "" */ + 0x0, 0xc0, 0x0, 0xe0, 0x0, 0xe0, 0x1, 0xe0, + 0xf, 0xf0, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, + 0x79, 0x9e, 0x79, 0x9e, 0x7f, 0xfe, 0x3f, 0xfc, + 0xf8, 0x1f, 0xfc, 0x3f, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F302 "" */ + 0xf, 0xff, 0xf, 0xff, 0xc6, 0x7f, 0xe3, 0x3f, + 0xfd, 0xfe, 0xfe, 0xfe, 0x3f, 0x79, 0x1f, 0xb8, + 0x7, 0xdc, 0x1, 0xec, 0x0, 0xf7, 0xff, 0xf9, + 0xff, 0xec, 0x0, 0x6, 0x0, 0x1, 0xff, 0xf8, + + /* U+F303 "" */ + 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x9f, + 0x1, 0xcf, 0x3, 0xe6, 0x7, 0xf0, 0xf, 0xf8, + 0x1f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0, 0x7f, 0x80, + 0x4f, 0x0, 0xce, 0x0, 0xfc, 0x0, 0xe0, 0x0, + + /* U+F304 "" */ + 0x0, 0x1c, 0x0, 0x3e, 0x0, 0x3f, 0x0, 0x9f, + 0x1, 0xcf, 0x3, 0xe6, 0x7, 0xf0, 0xf, 0xf8, + 0x1f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0, 0x7f, 0x80, + 0x7f, 0x0, 0xfe, 0x0, 0xfc, 0x0, 0xe0, 0x0, + + /* U+F305 "" */ + 0x0, 0xc, 0x0, 0x3e, 0x7, 0x3f, 0xd, 0x9f, + 0x19, 0xcf, 0x33, 0xe6, 0x27, 0xf0, 0xf, 0xf0, + 0x1f, 0xe0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x0, + 0x7e, 0x0, 0xfc, 0x0, 0xf8, 0x0, 0x80, 0x0, + + /* U+F306 "" */ + 0x7, 0xe0, 0xf, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf0, 0x7, 0xe0, + + /* U+F309 "" */ + 0x1e, 0x7, 0x81, 0xe0, 0x78, 0x1e, 0x7, 0x81, + 0xe0, 0x78, 0x1e, 0x7, 0x81, 0xe0, 0x78, 0xff, + 0xff, 0xf7, 0xf8, 0xfc, 0x1e, 0x3, 0x0, + + /* U+F30A "" */ + 0xc, 0x0, 0x7, 0x0, 0x3, 0xc0, 0x1, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xfc, + 0xf0, 0x0, 0x1c, 0x0, 0x3, 0x0, 0x0, + + /* U+F30B "" */ + 0x0, 0xc, 0x0, 0x3, 0x80, 0x0, 0xf3, 0xff, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x0, 0x3c, 0x0, 0xe, 0x0, 0x3, 0x0, + + /* U+F30C "" */ + 0xc, 0x7, 0x83, 0xf1, 0xfe, 0xff, 0xff, 0xf1, + 0xe0, 0x78, 0x1e, 0x7, 0x81, 0xe0, 0x78, 0x1e, + 0x7, 0x81, 0xe0, 0x78, 0x1e, 0x7, 0x80, + + /* U+F312 "" */ + 0xf, 0xf8, 0xf, 0xfe, 0x7, 0xff, 0x7, 0xff, + 0xc7, 0xff, 0xf3, 0xff, 0xfb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xbf, 0xff, 0x9f, 0xff, 0xc7, + 0xff, 0xc1, 0xff, 0xc0, 0xff, 0xe0, 0x3f, 0xe0, + + /* U+F31C "" */ + 0x3e, 0x0, 0x3f, 0xe0, 0xf, 0xfc, 0x3, 0xfb, + 0x80, 0xfe, 0x70, 0x3f, 0x8c, 0xf, 0xff, 0x83, + 0xff, 0xe0, 0xff, 0xf9, 0xbf, 0xfc, 0xff, 0xfe, + 0x5f, 0xff, 0x3a, 0xff, 0x9f, 0x3f, 0xcf, 0x8f, + 0xe7, 0xc1, 0xf9, 0xe0, 0x0, 0xe0, 0x0, + + /* U+F31E "" */ + 0xfc, 0xff, 0xf3, 0xff, 0x87, 0xff, 0x3f, 0xff, + 0xff, 0x7f, 0xb0, 0xfc, 0x3, 0xf0, 0xdf, 0xef, + 0xff, 0xff, 0xcf, 0xfe, 0x1f, 0xfc, 0xff, 0xf3, + 0xf0, + + /* U+F328 "" */ + 0x1f, 0x83, 0xfc, 0xf0, 0xff, 0xf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F332 "" */ + 0x7, 0xe0, 0xf, 0xf0, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, + + /* U+F337 "" */ + 0x18, 0x0, 0x38, 0x0, 0x78, 0x0, 0xff, 0xff, + 0xff, 0xff, 0x78, 0x0, 0x38, 0x0, 0x18, 0x0, + 0x0, 0x18, 0x0, 0x1c, 0x0, 0x1e, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x1e, 0x0, 0x1c, 0x0, 0x18, + + /* U+F338 "" */ + 0x18, 0x18, 0x3c, 0x18, 0x7e, 0x18, 0xff, 0x18, + 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x18, 0xff, 0x18, 0x7e, 0x18, 0x3c, 0x18, 0x18, + + /* U+F34E "" */ + 0x78, 0x1e, 0xf0, 0xf, 0xe7, 0xe7, 0xcf, 0xf3, + 0x1f, 0xf8, 0x3e, 0x7c, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x3e, 0x7f, 0xbe, 0x7f, 0xfc, + 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfe, 0x63, 0xc6, + + /* U+F358 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, + 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0x7e, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F359 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0xfe, 0xfc, 0xff, 0xf8, 0xf, 0xf0, 0xf, + 0xf0, 0xf, 0xf8, 0xf, 0xfc, 0xff, 0x7e, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F35A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0x7e, 0xff, 0x3f, 0xf0, 0x1f, 0xf0, 0xf, + 0xf0, 0xf, 0xf0, 0x1f, 0xff, 0x3f, 0x7f, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F35B "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0x7e, 0x7e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F35D "" */ + 0x0, 0x7f, 0x0, 0x7f, 0x0, 0x3f, 0x7c, 0x1f, + 0xfc, 0x3f, 0xc0, 0x77, 0xc0, 0xe3, 0xc1, 0xc0, + 0xc3, 0x80, 0xc3, 0x0, 0xc0, 0x18, 0xc0, 0x18, + 0xc0, 0x18, 0xc0, 0x18, 0xff, 0xf8, 0x7f, 0xf0, + + /* U+F360 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x3f, 0xe0, 0xff, 0x83, 0xfe, 0xf, 0xf1, 0x3f, + 0x8e, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F362 "" */ + 0x0, 0x18, 0x0, 0x1c, 0x0, 0x1e, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x1e, 0x0, 0x1c, 0x0, 0x18, + 0x18, 0x0, 0x38, 0x0, 0x78, 0x0, 0xff, 0xff, + 0xff, 0xff, 0x78, 0x0, 0x38, 0x0, 0x18, 0x0, + + /* U+F363 "" */ + 0x0, 0x18, 0x0, 0x1c, 0xf, 0xfe, 0x3f, 0xfe, + 0x70, 0x1c, 0x60, 0x18, 0xc0, 0x0, 0xc0, 0x3, + 0xc0, 0x3, 0x0, 0x3, 0x18, 0x6, 0x38, 0xe, + 0x7f, 0xfc, 0x7f, 0xf0, 0x38, 0x0, 0x18, 0x0, + + /* U+F381 "" */ + 0x3, 0xc0, 0x3, 0xf8, 0x0, 0xfe, 0x0, 0x7f, + 0xf8, 0x1f, 0xff, 0x7, 0xcf, 0xc7, 0xf3, 0xf1, + 0xfc, 0xfe, 0xfd, 0x2f, 0xff, 0x83, 0xff, 0xe1, + 0xff, 0xfc, 0xff, 0x7f, 0xff, 0x8f, 0xff, 0xc0, + + /* U+F382 "" */ + 0x7, 0xc0, 0x3, 0xf8, 0x1, 0xff, 0xe0, 0x7f, + 0xfc, 0x1f, 0x3f, 0xf, 0xc7, 0xc7, 0xe0, 0xfb, + 0xf4, 0xbe, 0xff, 0x3f, 0xff, 0xcf, 0xff, 0xf3, + 0xfd, 0xff, 0xff, 0x7f, 0xff, 0x8f, 0xff, 0xc0, + + /* U+F386 "" */ + 0x1, 0xe0, 0x0, 0xfc, 0x0, 0x73, 0x80, 0x18, + 0x60, 0xfe, 0x1f, 0xff, 0x87, 0xf0, 0x61, 0x80, + 0x1c, 0xe0, 0x3, 0xf0, 0x0, 0x78, 0x0, + + /* U+F387 "" */ + 0x70, 0x3, 0xe0, 0xd, 0x80, 0x36, 0x0, 0x70, + 0x0, 0xc0, 0x3, 0x0, 0xe, 0xe, 0x3f, 0xec, + 0xbf, 0xb2, 0x3, 0x88, 0x0, 0xf8, 0x3, 0x60, + 0xf, 0x80, 0x1c, 0x0, + + /* U+F390 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xc0, 0x3, 0xc0, 0x3, + 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, + 0xc0, 0x3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x3, 0xc0, 0x3, 0xc0, 0x1f, 0xf8, + + /* U+F3A0 "" */ + 0x7f, 0xfb, 0xff, 0xfc, 0xfe, 0xf3, 0xfb, 0xff, + 0xff, 0xff, 0xfc, 0xfe, 0xf3, 0xfb, 0xff, 0xff, + 0xff, 0xfc, 0xfe, 0xf3, 0xfb, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F3A5 "" */ + 0xf, 0xf8, 0x1f, 0xf8, 0x3b, 0xdc, 0x7d, 0xbe, + 0x7e, 0x3f, 0xc0, 0x3, 0x7f, 0xfe, 0x3f, 0xfc, + 0x1f, 0xf8, 0xf, 0xf8, 0xf, 0xf0, 0x7, 0xe0, + 0x3, 0xc0, 0x1, 0x80, + + /* U+F3BE "" */ + 0xf8, 0x1f, 0xc3, 0xf8, 0x7f, 0x80, 0xf0, 0x1e, + 0x3, 0xc0, 0x78, 0xf, 0x1, 0xe1, 0xff, 0xbf, + 0xf3, 0xfc, 0x3f, 0x3, 0xc0, 0x30, + + /* U+F3BF "" */ + 0x6, 0x1, 0xe0, 0x7e, 0x1f, 0xe7, 0xfe, 0xff, + 0xc3, 0xc0, 0x78, 0xf, 0x1, 0xe0, 0x3c, 0x7, + 0x8f, 0xf1, 0xfc, 0x3f, 0x87, 0xc0, + + /* U+F3C1 "" */ + 0x0, 0x78, 0x1, 0xf8, 0x7, 0x38, 0xc, 0x30, + 0x18, 0x60, 0x30, 0xdf, 0xf8, 0x7f, 0xf8, 0xff, + 0xf1, 0xff, 0xe3, 0xff, 0xc7, 0xff, 0x8f, 0xff, + 0x1f, 0xfe, 0x3f, 0xfc, 0x7f, 0xf8, 0x7f, 0xe0, + + /* U+F3C5 "" */ + 0xf, 0x3, 0xfc, 0x7f, 0xef, 0xfe, 0xf9, 0xff, + 0xf, 0xf0, 0xff, 0x9f, 0x7f, 0xe7, 0xfe, 0x7f, + 0xc3, 0xfc, 0x1f, 0x81, 0xf8, 0xf, 0x0, 0x60, + + /* U+F3C9 "" */ + 0xf, 0x1, 0xf0, 0x1f, 0x81, 0xe0, 0x1f, 0x8d, + 0xe3, 0xde, 0x3d, 0xfb, 0xdf, 0x36, 0xe7, 0x60, + 0x63, 0xc, 0x1f, 0x80, 0x20, 0x2, 0x1, 0xf8, + + /* U+F3CD "" */ + 0x7f, 0xdf, 0xff, 0x1, 0xe0, 0x3c, 0x7, 0x80, + 0xf0, 0x1e, 0x3, 0xc0, 0x78, 0xf, 0x1, 0xe0, + 0x3f, 0xff, 0xf7, 0xfe, 0xfb, 0xfe, + + /* U+F3CE "" */ + 0x7f, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xe3, 0xfc, 0x7b, 0xfe, + + /* U+F3CF "" */ + 0x7f, 0xdf, 0xff, 0x1, 0xe0, 0x3c, 0x7, 0x80, + 0xf0, 0x1e, 0x3, 0xc0, 0x78, 0xf, 0x1, 0xe0, + 0x3f, 0xff, 0xe3, 0xfc, 0x7b, 0xfe, + + /* U+F3D1 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xcf, 0xf3, 0xdc, 0x33, + 0xfb, 0x1f, 0xf9, 0x1f, 0xf9, 0x1f, 0xfb, 0x9f, + 0xdc, 0x3b, 0xcf, 0xf3, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F3DD "" */ + 0x0, 0x0, 0xc7, 0x0, 0x73, 0xc0, 0x39, 0xf8, + 0x1c, 0x7e, 0xe, 0x1f, 0x87, 0x7, 0xe3, 0x81, + 0xf1, 0xc0, 0x3c, 0xe0, 0xf, 0xf0, 0x1, 0xf8, + 0x0, 0x3c, 0x78, 0xe, 0x5f, 0x87, 0x3f, 0xe3, + 0x9f, 0xf9, 0xc3, 0xfc, 0xe0, 0x3e, 0x30, 0x0, + 0x0, + + /* U+F3E0 "" */ + 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, + 0x9f, 0xf9, 0xff, 0x9f, 0xff, 0xff, 0xf, 0xe0, + 0x7e, 0x7, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F3E5 "" */ + 0x0, 0x0, 0x6, 0x0, 0xe, 0x0, 0x1e, 0x0, + 0x3f, 0xf8, 0x7f, 0xfc, 0xff, 0xfe, 0x7f, 0xff, + 0x3f, 0xff, 0x1e, 0xf, 0xe, 0x7, 0x6, 0x7, + 0x0, 0x6, 0x0, 0x6, 0x0, 0xc, + + /* U+F3ED "" */ + 0x3, 0x80, 0x1f, 0xc1, 0xfd, 0xf7, 0xf8, 0xff, + 0xf0, 0x7f, 0xe0, 0xff, 0xc1, 0xff, 0x83, 0x7f, + 0xc, 0xfe, 0x19, 0xfc, 0x71, 0xf8, 0xc1, 0xf3, + 0x3, 0xee, 0x1, 0xf0, 0x1, 0xc0, + + /* U+F3FA "" */ + 0x7f, 0xfb, 0xff, 0xfc, 0x0, 0xf0, 0x3, 0xc0, + 0xf, 0x0, 0x3c, 0x0, 0xf0, 0x3, 0xc0, 0xf, + 0x0, 0x3c, 0x0, 0xff, 0xff, 0xfc, 0xff, 0xf3, + 0xff, 0xcf, 0xdf, 0xfe, + + /* U+F3FB "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xe1, + 0xff, 0xff, 0xdf, 0xfe, + + /* U+F3FD "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3e, 0x7c, 0x7e, 0x7e, + 0x77, 0xfe, 0xff, 0xcf, 0xff, 0x9f, 0xcf, 0x93, + 0xcf, 0x33, 0xfe, 0x3f, 0xfc, 0x3f, 0x7c, 0x3e, + 0x7e, 0x7e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F3FF "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdf, 0xff, 0xe7, 0xff, 0xfb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfd, 0xff, 0xfe, + + /* U+F406 "" */ + 0x7, 0x0, 0xfe, 0x7, 0xf0, 0x3f, 0x81, 0xfc, + 0xf, 0xe0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0xfe, + 0xf, 0xf8, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xe0, + + /* U+F410 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9f, + 0xf8, 0x1f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf8, 0x1f, + 0xf9, 0x9f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F422 "" */ + 0x0, 0x3, 0x0, 0x3, 0x80, 0x1b, 0xc0, 0xf, + 0xc0, 0x7, 0xc0, 0x3, 0xe0, 0x1, 0xf8, 0x0, + 0x78, 0x3e, 0x0, 0x1f, 0x80, 0x7, 0xc0, 0x3, + 0xe0, 0x3, 0xf0, 0x3, 0xd8, 0x3, 0xc0, 0x0, + 0xc0, 0x0, + + /* U+F424 "" */ + 0x0, 0x3f, 0x0, 0x1f, 0x0, 0xf, 0x0, 0x1f, + 0x0, 0x3f, 0x0, 0x79, 0x0, 0x20, 0x0, 0x0, + 0x0, 0x0, 0x6, 0x0, 0x8f, 0x0, 0xde, 0x0, + 0xfc, 0x0, 0xf8, 0x0, 0xfc, 0x0, 0xfc, 0x0, + + /* U+F425 "" */ + 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0xff, 0xf7, + 0xff, 0xef, 0xff, 0x9f, 0xff, 0x3f, 0xfc, 0x7f, + 0xf8, 0xff, 0xf1, 0xff, 0xf3, 0xff, 0xe7, 0xff, + 0xef, 0xff, 0xd0, 0x0, 0x20, 0x0, + + /* U+F432 "" */ + 0x0, 0x3, 0x0, 0x3, 0xe0, 0x1, 0xfc, 0x0, + 0xff, 0x0, 0x7f, 0xc0, 0x3f, 0xe0, 0x1f, 0xf0, + 0x7, 0xf8, 0x3, 0xfc, 0x0, 0xfe, 0x0, 0x7f, + 0x0, 0x1f, 0x0, 0xf, 0x0, 0x7, 0x1, 0xc3, + 0x80, 0xfb, 0xc0, 0x3e, 0xe0, 0xf, 0x98, 0x1, + 0xc0, + + /* U+F433 "" */ + 0x6, 0x60, 0x1e, 0x78, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7d, 0xfe, 0xf9, 0xff, 0xf3, 0xff, 0x3f, 0xfc, + 0x3f, 0xfc, 0xff, 0xcf, 0xff, 0x9f, 0x7f, 0xbe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1e, 0x78, 0x6, 0x60, + + /* U+F434 "" */ + 0x4, 0xe0, 0x1c, 0xf8, 0xc, 0xf0, 0x45, 0xe2, + 0x61, 0xc6, 0xf1, 0x8f, 0x0, 0x1f, 0x1c, 0x3f, + 0xfc, 0x38, 0xf8, 0x0, 0xf1, 0x8f, 0x63, 0x86, + 0x47, 0xa2, 0xf, 0x30, 0x1f, 0x38, 0x7, 0x20, + + /* U+F436 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3e, 0xfc, 0x7e, 0xfe, + 0x73, 0xfe, 0xf2, 0xff, 0xf2, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F439 "" */ + 0xc, 0x0, 0x3c, 0x0, 0x30, 0x0, 0x60, 0x7, + 0xf8, 0xf, 0xf0, 0xf, 0xc0, 0x1f, 0x9b, 0x7f, + 0x3e, 0x7e, 0x7c, 0xfd, 0xf9, 0xfb, 0xf3, 0xf7, + 0xc7, 0xe7, 0x9f, 0xe7, 0x7f, 0xef, 0xff, 0xde, + + /* U+F43A "" */ + 0x3f, 0xf, 0xc1, 0xe0, 0xfc, 0x7e, 0x1f, 0x2f, + 0x8f, 0xe7, 0xff, 0xff, 0xf7, 0xf9, 0xfc, 0x3f, + 0x1f, 0xef, 0xff, 0xff, + + /* U+F43C "" */ + 0x7f, 0xfb, 0xff, 0xfc, 0xcc, 0xf3, 0x33, 0xf3, + 0x3f, 0xcc, 0xfc, 0xcc, 0xf3, 0x33, 0xf3, 0x3f, + 0xcc, 0xfc, 0xcc, 0xf3, 0x33, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F43F "" */ + 0x3, 0x0, 0xc, 0x0, 0xfc, 0x3, 0xf0, 0x3, + 0x0, 0xc, 0xf, 0xff, 0xff, 0xff, 0x7f, 0xf9, + 0xff, 0xe3, 0xff, 0xf, 0xfc, 0x1f, 0xe0, 0x7f, + 0x83, 0xff, 0x1f, 0xfe, 0x7f, 0xf8, + + /* U+F441 "" */ + 0x1f, 0x1, 0xfc, 0x3f, 0xe3, 0x3e, 0x73, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x67, 0xf0, 0xff, 0x1f, + 0xf3, 0xfe, 0x3f, 0xe7, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xf0, + + /* U+F443 "" */ + 0xe, 0x7, 0xe0, 0xfe, 0x1f, 0xc3, 0xf8, 0x7f, + 0xf, 0xe1, 0xfc, 0x1f, 0x3, 0xe0, 0xfe, 0x1f, + 0xc3, 0xf8, 0x7f, 0x1f, 0xf7, 0xff, 0xff, 0xe0, + + /* U+F445 "" */ + 0x1, 0x80, 0x3, 0xc0, 0x1, 0x80, 0x4, 0x20, + 0x4e, 0x72, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf0, + 0xf, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, + + /* U+F447 "" */ + 0xee, 0x7e, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0x7f, 0xe3, 0xfc, 0x3f, 0xc3, 0xfc, 0x3f, + 0xc3, 0xfc, 0x3f, 0xc7, 0xfe, 0xff, 0xff, 0xff, + + /* U+F44B "" */ + 0x1c, 0x3, 0x81, 0xc0, 0x38, 0x7c, 0x3, 0xe7, + 0xc0, 0x3e, 0x7c, 0x3, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xf7, 0xc0, 0x3e, 0x7c, 0x3, 0xe7, 0xc0, + 0x3e, 0x1c, 0x3, 0x81, 0xc0, 0x38, + + /* U+F44E "" */ + 0x0, 0x30, 0x3, 0x9e, 0xf, 0xce, 0x1f, 0xe7, + 0x3f, 0x33, 0x3f, 0x19, 0x7c, 0x8c, 0x7c, 0x4e, + 0x72, 0x3e, 0x31, 0x3e, 0x98, 0xfc, 0xcc, 0xfc, + 0xe7, 0xf8, 0x73, 0xf0, 0x79, 0xc0, 0x14, 0x0, + + /* U+F450 "" */ + 0xf, 0x81, 0xfe, 0x1f, 0xf9, 0xff, 0xef, 0xff, + 0x7e, 0xdb, 0xfc, 0xdf, 0xfe, 0x7d, 0xf3, 0xff, + 0x0, 0x0, 0x0, 0x3, 0xfe, 0x3, 0x0, 0x18, + 0x0, 0xc0, 0x0, 0x0, + + /* U+F453 "" */ + 0xf, 0xf0, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, 0x1f, 0xf0, 0x80, 0x1, 0xf0, 0xf, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x1f, 0xf0, + + /* U+F458 "" */ + 0x0, 0x0, 0xc0, 0x0, 0x70, 0x0, 0x38, 0x0, + 0x1c, 0x0, 0xe, 0x0, 0x37, 0x0, 0xf, 0x80, + 0x19, 0xc0, 0x1f, 0x38, 0x7, 0xe6, 0x3, 0xfc, + 0x0, 0xbf, 0x80, 0x1f, 0xe3, 0x8f, 0xf1, 0xf7, + 0xf8, 0x7f, 0xfc, 0x1f, 0x0, 0x3, 0x80, + + /* U+F45C "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F45D "" */ + 0x1, 0xf0, 0x7, 0xfc, 0xf, 0xfe, 0x1f, 0xfe, + 0xf, 0xff, 0x27, 0xff, 0x73, 0xff, 0x79, 0xff, + 0x7c, 0xff, 0x3e, 0x42, 0x3f, 0x0, 0x3f, 0xbc, + 0x7f, 0x7e, 0xff, 0x7e, 0xf1, 0x7e, 0x60, 0x7e, + 0x0, 0x3c, + + /* U+F45F "" */ + 0x3, 0x0, 0x13, 0x90, 0x39, 0xcc, 0x71, 0xe4, + 0x64, 0xe6, 0xce, 0xf3, 0x9e, 0xf3, 0xbe, 0xf3, + 0x3c, 0x2, 0x39, 0x80, 0x73, 0xfe, 0x67, 0xfe, + 0x61, 0xf8, 0x2c, 0x0, 0xf, 0xf8, 0x7, 0xe0, + + /* U+F461 "" */ + 0x1, 0x80, 0x1b, 0x60, 0x36, 0xc0, 0x6d, 0xb0, + 0xdb, 0x61, 0xb6, 0xc3, 0x6d, 0x86, 0xdb, 0x4f, + 0xff, 0xdf, 0x3f, 0xf3, 0xfb, 0xff, 0x33, 0xff, + 0xe3, 0xef, 0x81, 0xfe, 0x1, 0xf8, + + /* U+F462 "" */ + 0x77, 0xfb, 0xbd, 0xfe, 0xff, 0x7f, 0xbf, 0xdb, + 0x6f, 0xf7, 0xfb, 0xfd, 0xfe, 0xff, 0x6d, 0xbf, + 0xdf, 0xef, 0xf7, 0xfb, 0xdd, 0xfe, 0xe0, + + /* U+F466 "" */ + 0x3f, 0xf1, 0xff, 0xe6, 0x1, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F468 "" */ + 0x2, 0x40, 0xe, 0x70, 0xe, 0x70, 0xf, 0xf0, + 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, + 0x24, 0x24, 0xe7, 0x67, 0xe7, 0x67, 0xff, 0x7f, + 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x7e, 0x7e, + + /* U+F469 "" */ + 0x7, 0xe0, 0x6, 0x18, 0x3, 0xc, 0xf, 0xff, + 0xef, 0xff, 0xf7, 0xff, 0xff, 0xf9, 0xff, 0xfc, + 0xff, 0xf8, 0x1f, 0xfc, 0xf, 0xff, 0x9f, 0xff, + 0xcf, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xfc, + + /* U+F46A "" */ + 0x6, 0x0, 0xf0, 0x1f, 0x81, 0xf8, 0x3f, 0xc7, + 0xfe, 0x79, 0xe7, 0x1e, 0xf0, 0xfe, 0x7, 0xe0, + 0x7e, 0x7, 0x60, 0x67, 0xe, 0x3f, 0xc0, 0xf0, + + /* U+F46B "" */ + 0x38, 0x0, 0x3e, 0x0, 0x31, 0x80, 0x18, 0xdc, + 0xc, 0x7f, 0x6, 0x38, 0xc3, 0x1c, 0x71, 0xfe, + 0x18, 0xff, 0x86, 0x7f, 0xe7, 0xbf, 0xbf, 0xdf, + 0xcf, 0xff, 0xe7, 0xff, 0xf1, 0xfd, 0xf0, 0x7c, + 0x70, 0x1c, 0x0, 0x0, 0x0, + + /* U+F46C "" */ + 0x1f, 0x87, 0xfe, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xfe, 0xcf, 0xe1, + 0xff, 0x3f, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F46D "" */ + 0x1f, 0x87, 0xfe, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfc, 0x83, 0xc8, 0x3f, 0xff, 0xff, + 0xfc, 0x83, 0xc8, 0x3f, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F470 "" */ + 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, + 0x0, 0x0, 0x30, 0x0, 0x7, 0xe0, 0xf, 0xf0, + 0x1f, 0xbb, 0x3f, 0xfc, 0x37, 0xec, 0x36, 0xec, + 0x37, 0xec, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + + /* U+F471 "" */ + 0xc0, 0x3f, 0xff, 0xff, 0xf6, 0x6, 0x7f, 0xe3, + 0xfc, 0x1f, 0x80, 0xf0, 0xf, 0x1, 0xf8, 0x3f, + 0xc7, 0xfe, 0xe0, 0x6f, 0xff, 0xff, 0xfc, 0x3, + + /* U+F472 "" */ + 0xf8, 0x0, 0x3f, 0x0, 0x1, 0xc3, 0xc0, 0x33, + 0xf8, 0xe, 0xfe, 0x1, 0xbf, 0x80, 0x6f, 0xf0, + 0x1d, 0xfc, 0x3, 0x7c, 0x0, 0xc8, 0xf0, 0x3d, + 0xf8, 0x1d, 0xf8, 0x6, 0x30, 0x1, 0x88, 0x0, + 0x76, 0x0, 0xf, 0x0, + + /* U+F474 "" */ + 0xe0, 0x0, 0x3c, 0x0, 0x3, 0x7f, 0xf0, 0xdf, + 0xfc, 0x37, 0xff, 0xd, 0xff, 0xc3, 0x7f, 0xf0, + 0xdf, 0xfc, 0x37, 0xff, 0xd, 0xff, 0xc3, 0x0, + 0x0, 0xc0, 0x0, 0x3f, 0xff, 0xc7, 0xff, 0xf0, + 0xe0, 0x70, 0x30, 0x1c, + + /* U+F477 "" */ + 0x3e, 0xf, 0xf8, 0xff, 0xcf, 0xce, 0xfc, 0x7f, + 0xc3, 0xff, 0xff, 0xff, 0xf9, 0xff, 0x9f, 0xe0, + 0x7e, 0x7, 0xf9, 0xff, 0x9f, 0xff, 0xf7, 0xfe, + + /* U+F478 "" */ + 0x3e, 0xf, 0xf8, 0xff, 0xcf, 0xee, 0xfe, 0x7f, + 0xe3, 0xff, 0xff, 0xff, 0xfd, 0xff, 0x8f, 0x12, + 0x3c, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F479 "" */ + 0x6f, 0xf6, 0xef, 0xf7, 0xef, 0xf7, 0xee, 0x77, + 0xee, 0x77, 0xe8, 0x17, 0xe8, 0x17, 0xee, 0x77, + 0xee, 0x77, 0xef, 0xf7, 0xef, 0xf7, 0x6f, 0xf6, + + /* U+F47D "" */ + 0x7, 0xf8, 0x3, 0xff, 0x0, 0xff, 0xc0, 0x3c, + 0xf0, 0x7f, 0x3f, 0xbf, 0xcf, 0xfc, 0xf3, 0xcf, + 0x3f, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, + 0xcf, 0x3c, 0xf3, 0xfe, 0x1f, 0xff, 0x87, 0xff, + 0xe1, 0xfd, 0xff, 0xfe, + + /* U+F47E "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7b, 0x9e, 0xfb, 0x9f, 0xfb, 0x9f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xfb, 0x9f, 0xfb, 0x9f, 0x7b, 0x9e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F47F "" */ + 0x1, 0xe0, 0x0, 0x78, 0x7, 0xde, 0xfb, 0xf0, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, + 0xfc, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xff, 0xff, + 0xff, 0xf8, 0x7f, 0xfc, 0xf, 0xff, 0x3, 0xff, + 0xff, 0xfd, 0xff, 0xfe, + + /* U+F481 "" */ + 0xf, 0xfe, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xbf, + 0xdf, 0xbf, 0xde, 0xf, 0xde, 0xf, 0xde, 0xf, + 0xdf, 0xbf, 0xdf, 0xbe, 0xdf, 0xfc, 0xdf, 0xf8, + 0xcf, 0xf0, 0xc0, 0x0, 0xc0, 0x0, 0x7f, 0xf0, + + /* U+F482 "" */ + 0xff, 0xff, 0xff, 0xff, 0xf3, 0xc, 0x30, 0xc3, + 0xc, 0xff, 0xff, 0xff, 0xff, 0xf0, + + /* U+F484 "" */ + 0x38, 0x0, 0x7c, 0x0, 0xc6, 0x0, 0xc6, 0x0, + 0xc6, 0x0, 0xc6, 0x0, 0xc6, 0x0, 0xfe, 0x7c, + 0xfc, 0xf8, 0xfd, 0xf1, 0xfd, 0xe3, 0xfd, 0xc7, + 0xfd, 0x8f, 0xfd, 0x1f, 0x7c, 0x3e, 0x38, 0x7c, + + /* U+F485 "" */ + 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x7, + 0xfe, 0x7f, 0xe0, 0xfe, 0x7f, 0xe0, 0xfe, 0xf, + 0xe7, 0xfe, 0xf, 0xe0, 0xfe, 0x7f, 0xe3, 0xfc, + + /* U+F486 "" */ + 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x7f, 0xe7, + 0xfe, 0x7f, 0xe7, 0x9e, 0x79, 0xe6, 0x6, 0x60, + 0x67, 0x9e, 0x79, 0xe7, 0xfe, 0x7f, 0xe3, 0xfc, + + /* U+F487 "" */ + 0x0, 0x3, 0x0, 0x0, 0x73, 0x1, 0xdf, 0xe0, + 0x1f, 0x6c, 0x0, 0xc1, 0x98, 0xd3, 0x37, 0x98, + 0x76, 0xf3, 0xfe, 0xcc, 0x7f, 0xd8, 0xf, 0xfb, + 0xff, 0xff, 0x7f, 0xff, 0xef, 0xff, 0xfd, 0x80, + 0x1, 0xb0, 0x0, 0x36, 0x0, 0x6, + + /* U+F48B "" */ + 0x1f, 0xfc, 0x3, 0xff, 0xe0, 0xff, 0xfe, 0x0, + 0x1f, 0xfc, 0x1, 0xff, 0xef, 0xff, 0xe7, 0x7, + 0xfe, 0x30, 0x7f, 0xe3, 0xff, 0xff, 0xf7, 0xff, + 0xff, 0x3f, 0xff, 0xf3, 0xcf, 0xcf, 0x3c, 0xfc, + 0xf0, 0xc8, 0x4c, 0x7, 0x87, 0x80, + + /* U+F48D "" */ + 0x0, 0x12, 0x0, 0xd, 0x80, 0x1, 0x20, 0x0, + 0x6c, 0x0, 0x19, 0x80, 0x3, 0x30, 0x0, 0x6c, + 0x0, 0x1b, 0x0, 0x2, 0xc0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0xfb, 0xff, 0xfe, 0xff, 0xf1, 0xbf, + 0xff, 0xed, 0xff, 0xfb, + + /* U+F48E "" */ + 0x0, 0x6, 0x0, 0x31, 0x80, 0xd, 0xe0, 0xf, + 0x80, 0xf, 0xc0, 0x7, 0xf0, 0x9, 0xfc, 0xf, + 0xf8, 0x3, 0xf8, 0xd, 0xf8, 0xf, 0xf8, 0x7, + 0xf8, 0x3, 0xf0, 0x1, 0xf0, 0x1, 0x80, 0x1, + 0x80, 0x0, + + /* U+F490 "" */ + 0x0, 0x7c, 0x0, 0xf8, 0x1, 0xf0, 0x1, 0xe3, + 0x1, 0xc7, 0x1, 0x8f, 0x1, 0x1f, 0x3c, 0x3e, + 0x7e, 0x7c, 0x7f, 0x0, 0xff, 0x80, 0x0, 0x0, + 0xff, 0x80, 0x7f, 0x0, 0x7f, 0x0, 0x1c, 0x0, + + /* U+F491 "" */ + 0x0, 0xc, 0x0, 0x1e, 0x0, 0xf, 0x0, 0xcf, + 0x0, 0x7f, 0x2, 0x7e, 0x3, 0xfc, 0x1, 0xf8, + 0x19, 0xf0, 0x1f, 0xe0, 0x1f, 0xc0, 0x1f, 0x80, + 0x1f, 0x0, 0x30, 0x0, 0x60, 0x0, 0xc0, 0x0, + + /* U+F492 "" */ + 0x0, 0x60, 0x0, 0x70, 0x0, 0x78, 0x0, 0xfc, + 0x1, 0xce, 0x3, 0x8f, 0x7, 0x1f, 0xe, 0x38, + 0x1f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0, 0xff, 0x80, + 0xff, 0x0, 0xfe, 0x0, 0xfc, 0x0, 0x78, 0x0, + + /* U+F493 "" */ + 0xff, 0xff, 0xff, 0xff, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x3c, 0x3c, + + /* U+F494 "" */ + 0x1, 0xe0, 0x3, 0xff, 0x7, 0xff, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0xf, + 0x0, 0x3, 0xdf, 0xfc, 0xf7, 0xff, 0x3c, 0x0, + 0xf, 0x7f, 0xf3, 0xdf, 0xfc, 0xf0, 0x0, 0x3d, + 0xff, 0xcf, 0x7f, 0xf3, + + /* U+F496 "" */ + 0x7, 0x81, 0xf3, 0xef, 0x87, 0xfc, 0xf, 0xf1, + 0xbf, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F497 "" */ + 0xff, 0xff, 0xff, 0xff, 0x7e, 0x7e, 0x78, 0x1e, + 0x78, 0x1e, 0x7e, 0x7e, 0x70, 0xe, 0x70, 0xe, + 0x7e, 0x7e, 0x78, 0x1e, 0x78, 0x1e, 0x7e, 0x7e, + 0xff, 0xff, 0xff, 0xff, + + /* U+F49E "" */ + 0x0, 0xe0, 0x0, 0x7f, 0x0, 0x3e, 0xf8, 0xf, + 0x7, 0x83, 0x80, 0x38, 0xfc, 0x1f, 0x9b, 0xc7, + 0xff, 0x1f, 0xfe, 0x78, 0xff, 0x87, 0xdf, 0xf0, + 0xff, 0xfe, 0x1f, 0xff, 0xc1, 0xff, 0xf0, 0xf, + 0xf8, 0x0, 0xfe, 0x0, 0x7, 0x0, + + /* U+F4A1 "" */ + 0x2, 0x40, 0xe, 0x70, 0xe, 0x70, 0xf, 0xf0, + 0xf, 0xf0, 0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, + 0x24, 0x24, 0xe7, 0x67, 0xe7, 0x67, 0xff, 0x7f, + 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x7e, 0x7e, + + /* U+F4AD "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xe6, 0x67, 0xe6, 0x67, + 0xe6, 0x67, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfc, 0x7f, 0xf8, 0xff, 0xe0, 0xc0, 0x0, + + /* U+F4B3 "" */ + 0xc0, 0x0, 0x38, 0xfc, 0x7, 0xff, 0xc0, 0xff, + 0xf8, 0x1f, 0xff, 0x3, 0xff, 0xc6, 0x7f, 0xf9, + 0xcf, 0xfe, 0x79, 0xff, 0x9f, 0x3f, 0xe7, 0xe7, + 0xf8, 0xfc, 0xfc, 0x3f, 0x9f, 0xf, 0xf3, 0x83, + 0xfe, 0x71, 0xef, 0xce, 0x60, 0x1, 0xc0, 0x0, + 0x30, + + /* U+F4B8 "" */ + 0xf, 0xff, 0x1, 0xff, 0xf8, 0x3f, 0xff, 0xc3, + 0xff, 0xfc, 0x1f, 0xff, 0xe, 0xff, 0xe7, 0xef, + 0xfe, 0x7e, 0x0, 0x7, 0xe0, 0x0, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xf7, 0xff, 0xfe, + + /* U+F4B9 "" */ + 0x1, 0xe0, 0x1, 0xfe, 0x0, 0xfb, 0xc0, 0x38, + 0xf0, 0x1e, 0x3e, 0x7, 0xbf, 0x81, 0xf1, 0xe0, + 0x7f, 0x78, 0xe, 0x1c, 0x3, 0xef, 0xc, 0x7f, + 0x8f, 0x7, 0x83, 0xc0, 0x0, 0xf0, 0x0, 0x37, + 0xff, 0xf8, + + /* U+F4BA "" */ + 0x0, 0x0, 0x6, 0x0, 0x7, 0x0, 0x47, 0x1f, + 0x71, 0xbe, 0x7c, 0x36, 0x7f, 0x3e, 0x7f, 0xbe, + 0x7f, 0xfe, 0x3f, 0xfe, 0x1f, 0xfe, 0xf, 0xfe, + 0xf, 0xfe, 0x7f, 0xfc, 0x7f, 0xf8, 0x3e, 0x0, + 0x8, 0x0, + + /* U+F4BD "" */ + 0xf, 0xf0, 0xc7, 0xfc, 0xff, 0xf0, 0x7b, 0xff, + 0xfc, 0xff, 0xfc, 0x3f, 0xfe, 0x0, + + /* U+F4BE "" */ + 0x0, 0x0, 0x1, 0xfe, 0x0, 0x7f, 0x80, 0x1f, + 0xe0, 0x7, 0xf8, 0x0, 0xfc, 0x0, 0x3e, 0x0, + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xc, 0x7f, 0xcf, 0xff, 0x7, 0xbf, 0xff, 0xcf, + 0xff, 0xc3, 0xff, 0xe0, + + /* U+F4C0 "" */ + 0x0, 0xc0, 0x0, 0x78, 0x0, 0x3e, 0x0, 0xc, + 0x0, 0x3, 0xe0, 0x0, 0x1c, 0x0, 0x1f, 0x0, + 0x7, 0x80, 0x0, 0xc0, 0x0, 0x0, 0x0, 0xff, + 0xc, 0x7f, 0xcf, 0xff, 0x7, 0xbf, 0xff, 0xcf, + 0xff, 0xe3, 0xff, 0xe0, + + /* U+F4C1 "" */ + 0x0, 0xc0, 0x0, 0x30, 0x0, 0x1e, 0x0, 0xf, + 0xc0, 0x3, 0xf0, 0x0, 0xfc, 0x0, 0x3f, 0x0, + 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xc, 0x7f, 0xcf, 0xff, 0x7, 0xbf, 0xff, 0xcf, + 0xff, 0xc3, 0xff, 0xe0, + + /* U+F4C2 "" */ + 0xe0, 0x0, 0x7e, 0x0, 0x7, 0xe0, 0x0, 0x7e, + 0x0, 0x7, 0xe0, 0x0, 0x7e, 0x40, 0x37, 0xe6, + 0x7, 0x7e, 0x70, 0x67, 0xf3, 0x8e, 0xff, 0xb8, + 0xff, 0x7f, 0xdf, 0xe3, 0xfd, 0xfc, 0x1f, 0xdf, + 0x80, 0xf8, 0xf0, + + /* U+F4C4 "" */ + 0x0, 0x0, 0x43, 0x9f, 0x71, 0xcf, 0xfc, 0xe7, + 0xff, 0x73, 0xff, 0xf9, 0xe7, 0xfe, 0x30, 0xff, + 0xc1, 0x9f, 0xfd, 0xf3, 0xff, 0xfe, 0x7f, 0xff, + 0x83, 0xff, 0xf0, 0xff, 0xe4, 0x3c, 0xcc, 0xe, + 0x0, 0x3, 0x0, 0x0, 0x80, 0x0, 0x0, + + /* U+F4C6 "" */ + 0x80, 0x0, 0x7b, 0x9f, 0x7f, 0xcf, 0xff, 0xe7, + 0xff, 0xf3, 0xff, 0xf9, 0xe7, 0xfe, 0x30, 0xff, + 0xc1, 0x9f, 0xfd, 0xf3, 0xff, 0xfe, 0x73, 0xff, + 0xc0, 0x7f, 0xf0, 0xf, 0xe4, 0x0, 0xcc, 0x0, + + /* U+F4CD "" */ + 0x9, 0x90, 0x13, 0xc8, 0x37, 0xec, 0x67, 0xee, + 0x6f, 0xf6, 0xef, 0xf7, 0xef, 0xf7, 0xef, 0xf7, + 0x71, 0x8e, 0x39, 0x9c, 0x1d, 0xb8, 0xf, 0xf0, + 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, + 0x3, 0xc0, + + /* U+F4CE "" */ + 0x70, 0x1, 0xbc, 0x0, 0xf7, 0x0, 0x18, 0x0, + 0x0, 0x3, 0xf0, 0x18, 0xfc, 0x7f, 0x3f, 0x3f, + 0xef, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, + 0x3d, 0xc0, 0xf, 0x38, 0x7, 0x27, 0x3, 0x8c, + 0xc0, 0xcf, 0x30, 0x33, 0xcc, 0xc, 0xf3, 0x3, + 0x30, + + /* U+F4D3 "" */ + 0x3, 0x80, 0x7, 0xc0, 0x7, 0xc0, 0x7, 0xc0, + 0x7, 0xc4, 0x13, 0x9c, 0x38, 0x3c, 0x7f, 0xfc, + 0xff, 0xfe, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xf8, 0x1f, 0xf0, + 0x1c, 0x70, + + /* U+F4D6 "" */ + 0x1f, 0x7, 0xf1, 0xff, 0x7f, 0xef, 0x1f, 0xf7, + 0xdf, 0xf3, 0xfe, 0x3f, 0x83, 0xe0, 0x3e, 0x33, + 0xee, 0x7f, 0xe7, 0xcc, 0x60, 0x0, + + /* U+F4D7 "" */ + 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x33, 0x0, 0x33, + 0x0, 0x3f, 0x0, 0x1e, 0x0, 0xfc, 0x1, 0xfc, + 0x79, 0x80, 0xfd, 0x80, 0xcd, 0xfe, 0xcc, 0xff, + 0xfc, 0x3, 0x78, 0x3, 0x33, 0xff, 0x7, 0xfe, + + /* U+F4D8 "" */ + 0x0, 0x1f, 0x0, 0x3f, 0xf8, 0x7f, 0xfc, 0xff, + 0xfe, 0x7e, 0xff, 0x3c, 0x7f, 0xb8, 0x3f, 0xb0, + 0x1f, 0x80, 0xf, 0x80, 0x1, 0x80, 0x1, 0x80, + 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, + + /* U+F4D9 "" */ + 0x30, 0x0, 0x30, 0x0, 0xff, 0xff, 0xff, 0xff, + 0x30, 0x0, 0x33, 0xfc, 0x37, 0xfe, 0x37, 0xfe, + 0x37, 0xfe, 0x37, 0xfe, 0x37, 0xfe, 0x33, 0xfe, + 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, 0x30, 0x0, + + /* U+F4DA "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0x87, 0xf9, 0xb7, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0xef, 0xf3, 0xcf, 0x78, 0x1e, + 0x7c, 0x3e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F4DB "" */ + 0xf, 0xc0, 0xf, 0xf0, 0xf, 0xfc, 0xf, 0xff, + 0xf, 0x87, 0xc7, 0x81, 0xe3, 0xdc, 0xf1, 0xee, + 0x78, 0xf7, 0x3c, 0x7c, 0x3e, 0x1f, 0xfe, 0x7, + 0xfe, 0x1, 0xff, 0xf8, 0x7f, 0xfc, + + /* U+F4DE "" */ + 0x0, 0xf, 0xe0, 0x3, 0xfc, 0x0, 0xff, 0x8f, + 0x9f, 0xf3, 0xf3, 0xfe, 0xfe, 0x7f, 0xdf, 0xef, + 0xf9, 0xfd, 0xff, 0x3f, 0xbf, 0xe7, 0xe7, 0xfc, + 0x0, 0xff, 0x81, 0xff, 0x31, 0xfc, 0x66, 0xfc, + 0xc, 0xd8, 0x0, 0xf0, + + /* U+F4DF "" */ + 0x7f, 0xfc, 0xf, 0xff, 0xe0, 0xff, 0xfe, 0xf, + 0xff, 0xfc, 0xff, 0xff, 0xef, 0xff, 0xe7, 0xff, + 0xfe, 0x3f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0xcf, 0xe7, 0xcc, 0xfe, + 0x6c, 0xc8, 0x26, 0x7f, 0x1, 0xc0, + + /* U+F4E2 "" */ + 0xc0, 0x0, 0x38, 0x0, 0x7, 0x0, 0x0, 0xff, + 0xc0, 0x1f, 0xf8, 0x13, 0xfe, 0x76, 0x7f, 0xbd, + 0xcf, 0xef, 0x79, 0xfb, 0xdf, 0x3e, 0xf7, 0xe7, + 0xbd, 0xfc, 0xef, 0x7f, 0x9d, 0xdf, 0xf3, 0x83, + 0xfe, 0x70, 0x0, 0xe, 0x0, 0x1, 0xc0, 0x0, + 0x30, + + /* U+F4E3 "" */ + 0x7f, 0x9f, 0xe6, 0x1b, 0x87, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xdf, 0xe3, 0xf0, 0x30, 0xc, + 0x3, 0x0, 0xc1, 0xfe, 0x7f, 0x80, + + /* U+F4E6 "" */ + 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0xff, 0xf7, + 0xff, 0xef, 0xff, 0x9f, 0xff, 0x3f, 0xfc, 0x7f, + 0xf8, 0xff, 0xf1, 0xff, 0xf3, 0xff, 0xe7, 0xff, + 0xef, 0xff, 0xd0, 0x0, 0x20, 0x0, + + /* U+F4FA "" */ + 0xc0, 0x0, 0x18, 0x78, 0x3, 0x3f, 0x0, 0x7f, + 0xe0, 0xf, 0xf8, 0x1, 0xfe, 0x0, 0x3f, 0x0, + 0x7, 0xc0, 0x0, 0xc0, 0x0, 0x18, 0x0, 0x3, + 0x0, 0x1c, 0x60, 0xf, 0x8c, 0x7, 0xf3, 0x81, + 0xfe, 0x70, 0x7f, 0xce, 0x1f, 0xf9, 0xc0, 0x0, + 0x30, + + /* U+F4FB "" */ + 0x0, 0x0, 0x3f, 0x3, 0xfe, 0xf, 0xfc, 0x70, + 0x79, 0x80, 0xe7, 0xe3, 0x98, 0xe, 0x30, 0x30, + 0xe1, 0x81, 0xfc, 0x1, 0xe0, 0x30, 0x21, 0xff, + 0xce, 0x3, 0xb8, 0x6, 0xed, 0x98, + + /* U+F4FC "" */ + 0x7, 0x0, 0x7, 0xf0, 0x1, 0xfc, 0x4, 0x7f, + 0x3, 0x1f, 0xc1, 0x87, 0xf0, 0x60, 0x70, 0xf0, + 0x0, 0x18, 0x0, 0x0, 0x7, 0xf0, 0x3, 0xfe, + 0x1, 0xff, 0xc0, 0xff, 0xf8, 0x3f, 0xfe, 0xf, + 0xff, 0x80, + + /* U+F4FD "" */ + 0x6, 0x0, 0x3, 0xe0, 0x1, 0xf8, 0x0, 0x7f, + 0x0, 0x1f, 0xc0, 0x7, 0xe0, 0x0, 0xf8, 0x0, + 0x18, 0x0, 0x0, 0x1e, 0x0, 0xdf, 0xe3, 0xef, + 0x79, 0xfb, 0xdf, 0x7e, 0xf1, 0xff, 0xbf, 0xff, + 0xef, 0xfb, 0xfd, 0xfe, 0x0, 0x1e, 0x0, + + /* U+F4FE "" */ + 0x3, 0x0, 0x3, 0xf0, 0x1, 0xfe, 0x0, 0x7f, + 0x80, 0x1f, 0xe0, 0x7, 0xf8, 0x0, 0xfc, 0x0, + 0xc, 0x38, 0x0, 0xe, 0x1, 0xcf, 0xf1, 0xf7, + 0x1c, 0xfc, 0xc6, 0x7f, 0x31, 0xdf, 0xdc, 0x77, + 0xf3, 0xfd, 0xfe, 0x38, 0x0, 0xe, 0x0, + + /* U+F4FF "" */ + 0x7, 0x80, 0x1, 0xf8, 0x0, 0x7f, 0x80, 0xf, + 0xf0, 0x1, 0xfe, 0x0, 0x1f, 0x80, 0x1, 0xe0, + 0x0, 0x0, 0x6, 0x0, 0x1, 0xc1, 0xfc, 0x18, + 0xff, 0x19, 0x3f, 0xcf, 0x87, 0xf3, 0xe1, 0xfe, + 0x78, 0x3f, 0xde, 0x0, 0x3, 0x80, + + /* U+F500 "" */ + 0x4, 0x0, 0x7, 0xc0, 0x3, 0xf8, 0xe0, 0xfe, + 0x7c, 0x3f, 0x9f, 0xf, 0xe7, 0xc1, 0xf1, 0xf0, + 0x10, 0x38, 0x0, 0x0, 0x7, 0xc1, 0x3, 0xf9, + 0xf1, 0xff, 0x3e, 0xff, 0xef, 0xff, 0xfb, 0xff, + 0xfe, 0xff, 0xff, 0xbf, + + /* U+F501 "" */ + 0xf, 0xc3, 0xff, 0xff, 0xff, 0xf7, 0xf8, 0xdf, + 0xe3, 0x61, 0x8c, 0x84, 0x1, 0xe0, 0x0, 0x0, + 0x40, 0x3, 0xcf, 0x1f, 0x3e, 0x7c, 0xf9, 0xf3, + 0xef, 0xcf, 0xdf, 0x3e, + + /* U+F502 "" */ + 0x7, 0x0, 0x7, 0xc0, 0x7, 0xf0, 0x3, 0xf8, + 0x1, 0xfc, 0x0, 0xfc, 0x0, 0x3e, 0x0, 0x4, + 0x1c, 0x0, 0x1b, 0x7, 0xcd, 0x8f, 0xe6, 0xcf, + 0xf7, 0xff, 0xfb, 0xff, 0xfd, 0xff, 0xfe, 0xff, + 0xff, 0x7f, 0x0, 0x3f, 0x80, + + /* U+F503 "" */ + 0x7, 0x0, 0x3, 0xf8, 0x0, 0x7f, 0x0, 0xf, + 0xe0, 0x1, 0xfc, 0x0, 0x3f, 0x8f, 0x81, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, + 0xff, 0x80, 0x3f, 0xf8, 0xf, 0xff, 0x81, 0xff, + 0xf0, 0x3f, 0xfe, 0x0, + + /* U+F504 "" */ + 0x7, 0x6, 0xfe, 0x1f, 0xf0, 0x60, 0x87, 0xfc, + 0x6f, 0xe0, 0x7f, 0x0, 0xf0, 0x0, 0x0, 0x0, + 0x4, 0x10, 0xfb, 0xe7, 0xff, 0x7f, 0xff, 0xff, + 0xff, 0xff, + + /* U+F505 "" */ + 0x7, 0x0, 0x3, 0xe0, 0x1, 0xfc, 0x0, 0x7f, + 0x0, 0x1f, 0xc0, 0x7, 0xf0, 0x0, 0xf8, 0x0, + 0x18, 0x0, 0x0, 0x1e, 0x1, 0xbf, 0xf3, 0xef, + 0x8d, 0xfb, 0xe3, 0x7e, 0xf8, 0xff, 0xbe, 0x6f, + 0xf7, 0x9b, 0xfc, 0xfc, 0x0, 0xc, 0x0, + + /* U+F506 "" */ + 0xc0, 0x0, 0x18, 0x78, 0x3, 0x3f, 0x0, 0x7f, + 0xe0, 0xf, 0xf8, 0x1, 0xfe, 0x0, 0x3f, 0x0, + 0x7, 0xc0, 0x0, 0xc0, 0x0, 0x18, 0x0, 0x3, + 0x0, 0x1c, 0x60, 0xf, 0x8c, 0x7, 0xf3, 0x81, + 0xfe, 0x70, 0x7f, 0xce, 0x1f, 0xf9, 0xc0, 0x0, + 0x30, + + /* U+F507 "" */ + 0xf, 0x0, 0x7, 0xe0, 0x1, 0xfc, 0x0, 0x7f, + 0x0, 0x1f, 0xc0, 0x7, 0xe0, 0x0, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0x38, 0x7, 0xdf, 0x83, 0xf6, + 0xf1, 0xfd, 0xfe, 0xff, 0x7f, 0xff, 0xcf, 0xef, + 0xf9, 0xf0, 0x0, 0x38, 0x0, 0x0, 0x0, + + /* U+F508 "" */ + 0x7, 0x0, 0xfe, 0x7, 0xf0, 0x3f, 0x81, 0xfc, + 0xf, 0xe0, 0x1c, 0x0, 0x0, 0x0, 0x0, 0xba, + 0xc, 0x98, 0xe4, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xe0, + + /* U+F509 "" */ + 0x0, 0xf0, 0x0, 0x1f, 0x80, 0x39, 0xf8, 0xe7, + 0x9f, 0x9e, 0x79, 0xf9, 0xe3, 0x6, 0xe, 0x0, + 0x0, 0x0, 0xf, 0x0, 0x39, 0xf1, 0x87, 0x3e, + 0x7f, 0xf7, 0xef, 0xff, 0x7e, 0x66, 0xf7, 0xe6, + 0x7f, 0x7e, 0xff, 0x0, 0x7, 0xc0, 0x0, 0x18, + + /* U+F515 "" */ + 0x0, 0xf3, 0x80, 0xf, 0xf8, 0x1, 0xfe, 0x0, + 0x7f, 0x18, 0x1f, 0xf1, 0x81, 0xc6, 0x3c, 0x0, + 0x66, 0x41, 0x86, 0x66, 0x18, 0x6c, 0x33, 0xc6, + 0xff, 0x66, 0x6f, 0xe6, 0x66, 0x3c, 0xc3, 0x60, + 0xf, 0xf6, 0x0, 0xfe, 0x7f, 0x83, 0xc7, 0xf8, + + /* U+F516 "" */ + 0x1c, 0x60, 0x1, 0xff, 0x0, 0x7, 0xf8, 0x1, + 0x8f, 0xe0, 0x18, 0xff, 0x83, 0xc6, 0x38, 0x66, + 0x60, 0x6, 0x66, 0x18, 0xc3, 0x61, 0x8f, 0xf6, + 0x3c, 0x7e, 0x66, 0x63, 0xc6, 0x66, 0x0, 0x6c, + 0x30, 0x6, 0xff, 0x1f, 0xef, 0xe1, 0xfe, 0x3c, + + /* U+F517 "" */ + 0x7f, 0xff, 0xbf, 0xfb, 0x7f, 0x86, 0xff, 0xd, + 0xff, 0xdb, 0xff, 0x3f, 0xf8, 0x3f, 0xf0, 0xf, + 0xf8, 0x1f, 0xf0, 0x3f, 0xc0, 0x0, 0x1, 0xff, + 0x83, 0xcf, 0x7, 0x9e, 0xf, 0xfc, + + /* U+F518 "" */ + 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xc3, 0xff, 0x3, + 0xff, 0x3, 0xff, 0x3, 0xff, 0x3, 0xff, 0x3, + 0xff, 0x3, 0xff, 0x3, 0xff, 0x3, 0xff, 0x3, + 0xff, 0x3f, 0xff, 0xff, 0x3, 0xc0, + + /* U+F519 "" */ + 0x20, 0x2, 0x30, 0x1, 0xb3, 0x6, 0x7b, 0x19, + 0xbd, 0x9e, 0xde, 0xcf, 0x6f, 0x63, 0x37, 0x99, + 0xb3, 0x60, 0xc3, 0x10, 0x61, 0x0, 0x30, 0x0, + 0x18, 0x0, 0xc, 0x0, 0x6, 0x0, 0x3, 0x0, + 0x1, 0x80, + + /* U+F51A "" */ + 0x0, 0x0, 0xc0, 0x0, 0x70, 0x0, 0x38, 0x0, + 0x1c, 0x0, 0xe, 0x0, 0x37, 0x0, 0xf, 0x80, + 0x19, 0xc0, 0xf, 0x38, 0x7, 0xe6, 0x3, 0xfc, + 0x0, 0xbf, 0x80, 0x1f, 0xe0, 0xf, 0xf0, 0x7, + 0xfc, 0x3, 0xfc, 0x0, + + /* U+F51B "" */ + 0x3f, 0xff, 0x1f, 0xff, 0xe6, 0x0, 0x19, 0x80, + 0x6, 0x60, 0x1, 0x98, 0x0, 0x66, 0x0, 0x19, + 0x80, 0x6, 0x60, 0xf9, 0x98, 0x3e, 0x6f, 0xff, + 0xff, 0xff, 0xff, + + /* U+F51C "" */ + 0x7, 0xff, 0xc1, 0xff, 0xfc, 0x3f, 0xff, 0x81, + 0xff, 0xf0, 0xf, 0xfe, 0x39, 0xff, 0xcf, 0xbf, + 0xf9, 0xf7, 0xff, 0x3e, 0xf0, 0xe3, 0x80, 0x0, + 0x0, 0x0, 0x3f, 0x9f, 0xff, 0xfb, 0xfd, 0xff, + 0x0, 0x3f, 0xe0, 0x0, + + /* U+F51D "" */ + 0x0, 0x0, 0x1, 0x80, 0x7, 0xe0, 0x1, 0x80, + 0x1, 0x80, 0x3, 0xc0, 0xf, 0xf0, 0xf, 0xf0, + 0x1f, 0xf8, 0x1f, 0xf8, 0x7f, 0xfe, 0xfe, 0x7f, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0x7f, 0xfe, + + /* U+F51E "" */ + 0x3, 0xfc, 0x7, 0xfe, 0xf, 0xff, 0x0, 0x7f, + 0x0, 0x1e, 0x3f, 0xc8, 0xff, 0xf1, 0xff, 0xf6, + 0xff, 0xf0, 0x3f, 0xc7, 0x80, 0x16, 0xe0, 0x60, + 0x3f, 0xc0, 0x80, 0x10, 0xe0, 0x60, 0x3f, 0xc0, + + /* U+F51F "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x38, 0xfc, 0x73, 0xfe, + 0x6f, 0xfe, 0xcc, 0x3f, 0xd8, 0x1f, 0xd9, 0x9f, + 0xf9, 0x9f, 0xf8, 0x1f, 0xfc, 0x3f, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F520 "" */ + 0x0, 0x7, 0x0, 0x0, 0xff, 0x0, 0xd, 0xf0, + 0x0, 0xfe, 0x0, 0x1f, 0xc0, 0x3, 0xfc, 0x0, + 0xff, 0x80, 0x1f, 0xf8, 0x3, 0xff, 0x80, 0xff, + 0xf0, 0x1f, 0xfe, 0x3, 0xff, 0xc0, 0x70, 0x48, + 0x6, 0x6, 0xc0, 0x0, 0x24, 0x0, 0x2, 0x40, + + /* U+F521 "" */ + 0x1, 0xc0, 0x0, 0xe0, 0x10, 0x70, 0x5c, 0x38, + 0x7e, 0x3e, 0x31, 0x9f, 0xb0, 0xff, 0xf8, 0x7f, + 0xfc, 0x3f, 0xfe, 0x1f, 0xff, 0xf, 0xff, 0x87, + 0xff, 0x81, 0xff, 0xc0, + + /* U+F522 "" */ + 0x3c, 0x0, 0x3f, 0xc0, 0x77, 0xf0, 0x77, 0xb0, + 0x7f, 0x30, 0x79, 0xf0, 0xf9, 0xe6, 0xcf, 0xe7, + 0xee, 0x6f, 0xfe, 0x6f, 0x3f, 0xcf, 0x3, 0xcf, + 0x0, 0x1f, 0x3, 0xff, 0x3, 0xff, 0x1, 0xfe, + + /* U+F523 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0xe7, + 0x9f, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xff, 0xff, + 0x9e, 0x7e, 0x79, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F524 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0xe7, + 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x9e, 0x7e, 0x79, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F525 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F526 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0xe7, + 0x9f, 0xff, 0xfe, 0x79, 0xf9, 0xe7, 0xff, 0xff, + 0x9e, 0x7e, 0x79, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F527 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xe7, + 0xff, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xff, 0xff, + 0xfe, 0x7f, 0xf9, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F528 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xe7, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0x7f, 0xf9, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F529 "" */ + 0x3, 0x0, 0x1e, 0x0, 0x30, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x30, 0x1, 0xe0, 0x3, 0x0, + + /* U+F52A "" */ + 0x3f, 0xf1, 0xff, 0xe7, 0xff, 0x9f, 0xfe, 0x7f, + 0xf9, 0xff, 0xe7, 0xff, 0x9f, 0xe6, 0x7f, 0x99, + 0xff, 0xe7, 0xff, 0x9f, 0xfe, 0x7f, 0xf9, 0xff, + 0xef, 0xff, 0xff, 0xff, + + /* U+F52B "" */ + 0x3f, 0xf1, 0xff, 0xe7, 0xf9, 0x9f, 0xe6, 0x7f, + 0x99, 0xfe, 0x67, 0xf9, 0x9e, 0x66, 0x79, 0x99, + 0xfe, 0x67, 0xf9, 0x9f, 0xe6, 0x7f, 0x99, 0xfe, + 0x6f, 0xf9, 0xff, 0xe7, + + /* U+F52C "" */ + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, + + /* U+F52D "" */ + 0x0, 0x7c, 0x0, 0x7f, 0x0, 0x7f, 0xc0, 0x7f, + 0xe0, 0x7f, 0xf0, 0x7f, 0xf8, 0x79, 0xfc, 0x39, + 0xfc, 0x39, 0xf0, 0x19, 0xfe, 0x9, 0xfe, 0x1, + 0xf8, 0x1, 0xfe, 0x1, 0xfc, 0x1, 0x80, 0x1, + 0x80, 0x0, + + /* U+F52E "" */ + 0x0, 0x38, 0x0, 0x1f, 0x0, 0x1e, 0xe0, 0x1f, + 0xfe, 0x1f, 0xff, 0xcf, 0xff, 0xf3, 0xc7, 0xf9, + 0xee, 0xf8, 0x77, 0xdc, 0x3b, 0xf6, 0xf, 0xfd, + 0xc3, 0xfe, 0x38, 0xff, 0xf7, 0xdf, 0xfc, 0xf0, + + /* U+F52F "" */ + 0x7f, 0x80, 0x7f, 0x80, 0xe1, 0xcc, 0xe1, 0xce, + 0xe1, 0xcf, 0xe1, 0xc7, 0xff, 0xc7, 0xff, 0xc3, + 0xff, 0xf3, 0xff, 0xdb, 0xff, 0xdb, 0xff, 0xdb, + 0xff, 0xdb, 0xff, 0xce, 0xff, 0xc0, 0x7f, 0x80, + + /* U+F530 "" */ + 0x1c, 0xe, 0xf, 0x3, 0xc7, 0x0, 0x39, 0x80, + 0x6, 0x60, 0x1, 0x98, 0x0, 0x6c, 0x0, 0xf, + 0xfc, 0xff, 0xff, 0xff, 0xf0, 0xfc, 0x3c, 0x33, + 0xf, 0xc, 0xc3, 0xff, 0x3f, 0xdf, 0x87, 0xe0, + + /* U+F531 "" */ + 0xc0, 0x1, 0xe0, 0x0, 0xf0, 0x0, 0x7c, 0x0, + 0x3e, 0x0, 0x1f, 0x0, 0xf, 0x80, 0xf, 0x0, + 0xf8, 0x7, 0xc0, 0x3e, 0x1, 0xf0, 0xf, 0x80, + 0x18, 0x0, 0x0, + + /* U+F532 "" */ + 0xe0, 0x3, 0xf0, 0x3, 0xf8, 0x1, 0xfc, 0x0, + 0xfc, 0x3, 0xf0, 0x7f, 0xf, 0xe0, 0xfc, 0x3, + 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F533 "" */ + 0xf, 0xff, 0xb0, 0xc, 0xe, 0x3, 0x1, 0xff, + 0xf8, 0x7f, 0xff, 0x1f, 0xfc, 0xe0, 0x3f, 0x18, + 0xf, 0xc6, 0x1, 0xf1, 0x80, 0x3c, 0xe0, 0xf, + 0xf0, 0x1, 0xf8, 0x0, 0x0, 0xc0, 0x7f, 0xe0, + + /* U+F534 "" */ + 0x1e, 0x7, 0x87, 0xf9, 0xfe, 0x61, 0x98, 0x6c, + 0xf, 0x3, 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0, + 0xf0, 0x36, 0x19, 0x86, 0x7f, 0x9f, 0xe1, 0xe0, + 0x78, + + /* U+F535 "" */ + 0xf, 0x0, 0xf, 0xf0, 0x7, 0xff, 0xf1, 0xff, + 0xfe, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0x9f, + 0xff, 0xff, 0x7f, 0xff, 0xdf, 0xff, 0xf3, 0xfc, + 0x1c, 0x7c, 0x7, 0x13, 0x0, 0xc4, 0xc0, 0x10, + + /* U+F536 "" */ + 0x0, 0x6, 0x0, 0x3c, 0x1, 0xe0, 0x1f, 0x0, + 0xf8, 0x7, 0xc0, 0x3e, 0x0, 0x78, 0x0, 0x3e, + 0x0, 0x1f, 0x0, 0xf, 0x80, 0x7, 0xc0, 0x1, + 0xe0, 0x0, 0xc0, + + /* U+F537 "" */ + 0x0, 0x1c, 0x3, 0xf0, 0x7f, 0xf, 0xe0, 0xfc, + 0x3, 0xf0, 0x3, 0xf8, 0x1, 0xfc, 0x0, 0xfc, + 0x0, 0x70, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F538 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xe6, 0x67, 0x66, 0x66, + 0x66, 0x66, 0xe6, 0x67, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0xee, 0x77, 0x6e, 0x76, + + /* U+F539 "" */ + 0xc0, 0x0, 0x38, 0x78, 0x7, 0x3e, 0x0, 0xef, + 0xc0, 0x1f, 0xc0, 0x3, 0xfc, 0x1, 0x7c, 0x60, + 0x6f, 0x18, 0x19, 0xc6, 0x6, 0x3d, 0x80, 0xc6, + 0x40, 0x30, 0xf0, 0x6, 0x18, 0x0, 0xf3, 0x0, + 0x4, 0x60, 0x1, 0xc, 0x3, 0xf1, 0x80, 0x0, + 0x30, + + /* U+F53A "" */ + 0x0, 0x7e, 0x43, 0xff, 0xff, 0xf3, 0xff, 0xfb, + 0xce, 0x7f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, + 0xfc, 0x3f, 0xfe, 0x73, 0xdf, 0xff, 0xcf, 0xff, + 0xff, 0xc2, 0x7e, 0x0, + + /* U+F53B "" */ + 0x0, 0x7e, 0x43, 0xff, 0xff, 0xf7, 0xff, 0xf3, + 0xcc, 0x3f, 0xdb, 0x1f, 0xf9, 0x1f, 0xf9, 0x1f, + 0xfb, 0x9f, 0xfc, 0x33, 0xde, 0x7f, 0xcf, 0xff, + 0xff, 0xc2, 0x7e, 0x0, + + /* U+F53C "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7, + 0xe0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, + 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F53D "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xf7, 0xff, 0xc3, 0x3, + 0xcf, 0x3, 0xcf, 0xff, 0xf3, 0xff, 0xfb, 0x3, + 0xc3, 0x3, 0xf7, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F53E "" */ + 0x0, 0x30, 0x1, 0xc0, 0x6, 0x3f, 0xff, 0xff, + 0xfc, 0x6, 0x0, 0x38, 0x1, 0xc0, 0x6, 0x3, + 0xff, 0xff, 0xff, 0xc6, 0x0, 0x38, 0x0, 0xc0, + 0x0, + + /* U+F53F "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3e, 0x7c, 0x7e, 0x7e, + 0x67, 0xe6, 0xe7, 0xe7, 0xff, 0xff, 0xff, 0xff, + 0xcf, 0xff, 0xcf, 0xfe, 0xff, 0xc0, 0x7f, 0x80, + 0x7f, 0xc0, 0x3f, 0xc0, 0x1f, 0xc0, 0x7, 0x80, + + /* U+F540 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xf0, + 0x3f, 0xce, 0xff, 0x3b, 0xfc, 0xf, 0xf0, 0x7f, + 0xcf, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F541 "" */ + 0x78, 0xf, 0xf0, 0x7f, 0xc3, 0xbf, 0x1c, 0xfc, + 0xe1, 0xe7, 0x0, 0x38, 0x1, 0xc0, 0xe, 0x78, + 0x73, 0xf3, 0x8f, 0xdc, 0x3f, 0xe0, 0xff, 0x1, + 0xe0, + + /* U+F542 "" */ + 0xfc, 0x3f, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, + 0xfc, 0x3f, 0xfc, 0x3f, 0xe, 0x0, 0x7, 0x0, + 0x3, 0xf0, 0x3, 0xf0, 0x3, 0xf0, 0x3, 0xf0, + 0x3, 0xf0, 0x3, 0xf0, + + /* U+F543 "" */ + 0xc9, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7e, + 0x7, 0xff, 0xfe, 0x7, 0xe0, 0x7f, 0xff, 0xe0, + 0x7e, 0x7, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x93, + + /* U+F544 "" */ + 0x0, 0x60, 0x0, 0x6, 0x0, 0x0, 0x60, 0x0, + 0xff, 0xf0, 0x1f, 0xff, 0x81, 0xff, 0xf8, 0x1f, + 0xff, 0x8d, 0xc6, 0x3b, 0xdc, 0x63, 0xbd, 0xff, + 0xfb, 0xdf, 0xff, 0xbd, 0xff, 0xfb, 0x18, 0x91, + 0x81, 0xff, 0xf8, 0x1f, 0xff, 0x80, 0xff, 0xf0, + + /* U+F545 "" */ + 0x0, 0x38, 0x0, 0xe, 0x0, 0x33, 0x80, 0xc, + 0xe0, 0x33, 0xf8, 0xd, 0xfc, 0x23, 0xfc, 0x19, + 0xfc, 0x27, 0xfc, 0x19, 0xfc, 0x27, 0xfc, 0x19, + 0xfc, 0xe, 0xfc, 0x3, 0xfc, 0x0, 0xfc, 0x0, + 0x3c, 0x0, 0xc, 0x0, 0x0, + + /* U+F546 "" */ + 0xfc, 0x3, 0xf0, 0xf, 0xc0, 0x38, 0x0, 0xe0, + 0x3, 0xf0, 0xf, 0xc0, 0x38, 0x0, 0xfd, 0x9f, + 0xf6, 0x7f, 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F547 "" */ + 0xdb, 0x6c, 0xf6, 0xdb, 0x3d, 0xb6, 0xcf, 0x7d, + 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, + + /* U+F548 "" */ + 0xff, 0xff, 0xf0, 0xf0, 0xff, 0xf8, 0xf8, 0xff, + 0xf0, 0xf0, 0xff, 0xf8, 0xf8, 0xff, 0xf0, 0xf0, + 0xff, 0xff, + + /* U+F549 "" */ + 0x0, 0xc0, 0x0, 0x78, 0x0, 0x3f, 0x0, 0x1f, + 0xe0, 0x7f, 0x3f, 0xbf, 0x87, 0xfc, 0xe1, 0xcf, + 0x3c, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe1, + 0xcf, 0x38, 0x73, 0xfe, 0x1f, 0xff, 0x87, 0xff, + 0xe1, 0xfd, 0xff, 0xfe, + + /* U+F54A "" */ + 0x0, 0x3, 0x80, 0x7, 0xc0, 0x7, 0xe0, 0x3, + 0xe0, 0x1, 0xf0, 0x1, 0xf0, 0x1, 0xc0, 0x7, + 0xc0, 0xf, 0xc0, 0xf, 0xe0, 0xf, 0xf0, 0xf, + 0xf0, 0x7, 0xf8, 0x3, 0xf8, 0x1, 0xf8, 0x0, + 0x78, 0x0, 0x0, 0x0, 0x0, + + /* U+F54B "" */ + 0x0, 0xfc, 0x7, 0x7f, 0xc3, 0xdf, 0xf8, 0xf7, + 0xff, 0x1d, 0xff, 0xc0, 0x3f, 0xe0, 0x3, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x3f, + 0xe1, 0xdf, 0xfc, 0xf7, 0xff, 0x3d, 0xff, 0x87, + 0x7f, 0xc0, 0xf, 0xc0, + + /* U+F54C "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xf3, 0xcf, 0xe1, 0x87, + 0xe1, 0x87, 0xf3, 0xcf, 0x7f, 0xfe, 0x7f, 0xfe, + 0x3f, 0xfc, 0x1f, 0xf8, 0x1d, 0xb8, 0x1d, 0xb8, + + /* U+F54D "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x78, 0x8e, + 0x7c, 0xf6, 0xee, 0x17, 0xc7, 0x3, 0xdf, 0xfb, + 0xdf, 0xcb, 0xdf, 0xfb, 0xe0, 0x77, 0x60, 0x3e, + 0x70, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F54E "" */ + 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0x77, 0x6e, 0x0, 0x0, 0x0, 0x0, + 0x60, 0x6, 0x60, 0x6, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfe, 0x7f, 0xfe, + + /* U+F54F "" */ + 0x3f, 0xfe, 0x1f, 0xff, 0x1f, 0xff, 0xcf, 0xff, + 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xe1, + 0xce, 0x70, 0xe7, 0x38, 0x73, 0x9c, 0x39, 0xcf, + 0xfc, 0xe7, 0xfe, 0x71, 0xfe, 0x10, + + /* U+F550 "" */ + 0xff, 0xfc, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xff, 0x3f, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xfc, 0xff, 0xfc, + + /* U+F551 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3d, 0xbc, 0x7e, 0x7e, + 0x76, 0x6e, 0xf9, 0x9f, 0xd9, 0x9b, 0xe6, 0x67, + 0xe6, 0x67, 0xd9, 0x9b, 0xf9, 0x9f, 0x76, 0x6e, + 0x7e, 0x7e, 0x3d, 0xbc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F552 "" */ + 0xf, 0xf0, 0x8, 0x30, 0x8, 0x30, 0x3f, 0xfc, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xcf, + 0x0, 0x0, 0x0, 0x0, 0xf7, 0xcf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F553 "" */ + 0x6, 0xc, 0x1, 0xc1, 0xc0, 0x7c, 0x7c, 0x1f, + 0xff, 0xc7, 0xff, 0xfd, 0xff, 0xff, 0xdd, 0xff, + 0x71, 0x3f, 0xe4, 0x7, 0xfc, 0x0, 0xff, 0x80, + 0x1f, 0xf0, 0x3, 0xfe, 0x0, 0x7f, 0xc0, 0xf, + 0xf8, 0x1, 0xff, 0x0, + + /* U+F554 "" */ + 0xe, 0x1, 0xe0, 0xe, 0x0, 0x0, 0x1c, 0x3, + 0xf0, 0x7f, 0x8f, 0xfe, 0xde, 0xed, 0xe0, 0xde, + 0x0, 0xe0, 0x7, 0x1, 0x38, 0x39, 0x87, 0x18, + 0xe1, 0x8c, 0x8, + + /* U+F555 "" */ + 0x7f, 0xff, 0xc0, 0x0, 0xc0, 0x0, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, + 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, + + /* U+F556 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xf1, 0xcf, 0xf8, 0x9f, + 0xf9, 0xdf, 0xff, 0xff, 0xfc, 0x3f, 0x78, 0x1e, + 0x79, 0x9e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F557 "" */ + 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7c, 0x3e, + 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, 0x78, 0x1e, + 0xf8, 0x1f, 0xf8, 0x1f, + + /* U+F558 "" */ + 0x7f, 0xff, 0xff, 0xff, 0x87, 0xfc, 0xf, 0xeb, + 0x9f, 0xad, 0x7e, 0xb5, 0xfa, 0xe7, 0xf0, 0x3f, + 0xe1, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1b, 0x0, + 0x6f, 0xff, 0xdf, 0xff, + + /* U+F559 "" */ + 0x3, 0x0, 0x7f, 0x83, 0xff, 0x1f, 0xfe, 0x78, + 0x79, 0xc0, 0xef, 0x3, 0xfc, 0xf, 0x70, 0x39, + 0xe1, 0xe7, 0xff, 0x8f, 0xfc, 0x1f, 0xe0, 0xff, + 0xc3, 0xff, 0x1f, 0x3e, 0x3c, 0xf0, 0x21, 0x0, + + /* U+F55A "" */ + 0x7, 0xff, 0x83, 0xff, 0xf1, 0xff, 0xfc, 0xfc, + 0xdf, 0x7f, 0x27, 0xff, 0xe3, 0xff, 0xf8, 0xfd, + 0xfc, 0x9f, 0x3f, 0x37, 0xc7, 0xff, 0xf0, 0xff, + 0xfc, 0x1f, 0xfe, + + /* U+F55B "" */ + 0x0, 0xf0, 0xf, 0x1f, 0x8f, 0xff, 0x9f, 0xff, + 0x7f, 0xef, 0xe, 0xf7, 0x0, 0xc0, 0x30, 0x18, + 0x1, 0x81, 0x80, 0x18, 0x10, 0x0, 0x87, 0xc0, + 0x3e, 0x7c, 0x3, 0xe6, 0xc0, 0x36, 0x7c, 0x3, + 0xe7, 0x80, 0x1e, + + /* U+F55C "" */ + 0x3f, 0xc0, 0xff, 0x1, 0x98, 0x6, 0x60, 0x19, + 0x80, 0x66, 0x61, 0x99, 0xce, 0x7f, 0x70, 0xf1, + 0x81, 0x8f, 0xff, 0x3f, 0xfc, 0xff, 0xf3, 0xff, + 0xc7, 0xfe, 0x1f, 0xf8, + + /* U+F55D "" */ + 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, + 0xf7, 0xfe, 0xf, 0x0, 0xf0, 0xf, 0x0, 0x60, + + /* U+F55E "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf0, 0x3, 0xc0, + 0xf, 0x0, 0x3c, 0x0, 0xf0, 0x3, 0xff, 0xff, + 0xff, 0xfc, 0xfc, 0xf3, 0xf3, 0xff, 0xfd, 0xff, + 0xe7, 0x3, 0x8c, 0xc, + + /* U+F55F "" */ + 0x1, 0x0, 0x7, 0x0, 0xe, 0x0, 0x1c, 0xc, + 0x7c, 0x7e, 0xfb, 0xdf, 0xff, 0x3f, 0xfe, 0x7f, + 0xfc, 0x7f, 0xf3, 0xff, 0xfb, 0xff, 0xe0, 0xfe, + 0x1, 0xac, 0x0, 0x40, 0x0, 0x80, + + /* U+F560 "" */ + 0x0, 0x0, 0x30, 0x7, 0x0, 0xe0, 0xcc, 0xf, + 0x83, 0x78, 0x73, 0xe, 0x0, 0xc0, 0x1c, 0x63, + 0x87, 0x30, 0x3e, 0x1, 0xe0, 0xc, 0x0, + + /* U+F561 "" */ + 0x0, 0x1f, 0x0, 0xf, 0xe0, 0x7, 0x1c, 0x0, + 0x3, 0xff, 0xfc, 0xff, 0xff, 0x37, 0x3, 0x9c, + 0xc0, 0xce, 0x18, 0x67, 0x3, 0x30, 0x0, 0xfc, + 0x0, 0x1e, 0x0, 0x3, 0x0, 0x0, 0xc0, 0x0, + 0x30, 0x0, 0xc, 0x0, 0x1f, 0xe0, 0x7, 0xf8, + 0x0, + + /* U+F562 "" */ + 0x3, 0xc0, 0x1, 0x80, 0x7, 0xc0, 0xf, 0xf0, + 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, + + /* U+F563 "" */ + 0x0, 0x0, 0x7, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, + 0x3f, 0xfe, 0x79, 0xfe, 0x79, 0xfe, 0xff, 0xfe, + 0x7f, 0xfe, 0x7f, 0xce, 0x73, 0xce, 0x73, 0xfc, + 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xe0, 0x0, 0x80, + + /* U+F564 "" */ + 0x7, 0x0, 0x3e, 0x0, 0xfe, 0x3, 0xfe, 0x7, + 0x9e, 0x1f, 0x3e, 0x3f, 0xfe, 0x7f, 0xff, 0xff, + 0xcf, 0xe7, 0x9d, 0xcf, 0xf3, 0xff, 0xe3, 0xff, + 0x83, 0xfe, 0x1, 0xf0, 0x0, + + /* U+F565 "" */ + 0x30, 0x0, 0x30, 0x0, 0xf7, 0xf8, 0xf7, 0xfc, + 0x30, 0xc, 0x30, 0xc, 0x30, 0xc, 0x30, 0xc, + 0x30, 0xc, 0x30, 0xc, 0x30, 0xc, 0x30, 0xc, + 0x3f, 0xef, 0x1f, 0xef, 0x0, 0xc, 0x0, 0xc, + + /* U+F566 "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xfc, 0x7, 0x9f, 0x1, + 0xc7, 0xc0, 0x71, 0xff, 0xfe, 0x7c, 0xaf, 0xff, + 0x2b, 0xff, 0xff, 0xff, 0xf0, 0x30, 0x3c, 0xc, + 0xd, 0xff, 0xfe, + + /* U+F567 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x6d, 0xb6, 0xe1, 0x87, 0xf3, 0xcf, 0xe1, 0x87, + 0xed, 0xb7, 0xfe, 0x7f, 0xfc, 0x3f, 0x7c, 0x3e, + 0x7c, 0x3e, 0x3e, 0x7c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F568 "" */ + 0x3, 0xc0, 0x7, 0xe0, 0x6, 0x60, 0x6, 0x60, + 0x7, 0xe0, 0x7, 0xe0, 0xf, 0xf0, 0x7e, 0x66, + 0x7e, 0xe, 0x3c, 0x1c, 0x3f, 0xf8, 0x7f, 0xe2, + 0x70, 0xf, 0xf0, 0xf, 0xe0, 0x7, 0xc0, 0x3, + + /* U+F569 "" */ + 0x0, 0x2, 0x0, 0xe, 0x1f, 0xf8, 0x70, 0x7e, + 0xe0, 0xc3, 0xc0, 0x83, 0xe0, 0x7, 0xf8, 0x1f, + 0xff, 0xff, 0xef, 0xf7, 0xef, 0x77, 0xef, 0x77, + 0x2f, 0x74, 0xf, 0x70, + + /* U+F56A "" */ + 0xf, 0xfc, 0xf, 0xcf, 0xc7, 0xb3, 0x9b, 0x84, + 0xc3, 0xc1, 0xf0, 0xf8, 0x44, 0x7f, 0xf1, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfd, 0xff, 0xfe, 0x3f, 0xff, 0x3, 0xff, 0x0, + + /* U+F56B "" */ + 0x0, 0xf, 0x0, 0x7f, 0x3, 0xff, 0x7, 0xff, + 0xf, 0xfe, 0x1f, 0xfe, 0x1e, 0xfe, 0x3d, 0xfc, + 0x3b, 0xf0, 0x37, 0xf8, 0xf, 0xf8, 0x1f, 0xc0, + 0x3f, 0xe0, 0x7f, 0x80, 0xe0, 0x0, 0xc0, 0x0, + + /* U+F56C "" */ + 0x7f, 0xf, 0xf8, 0xc7, 0xcc, 0x6e, 0xfe, 0x7c, + 0x63, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0xe1, 0xfc, 0x83, 0xff, 0xf7, 0xfe, + + /* U+F56D "" */ + 0x3e, 0xf, 0xf0, 0xff, 0x8f, 0xcc, 0xfc, 0x6f, + 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xf9, + 0xfe, 0xa7, 0xe0, 0x7f, 0xf, 0xf9, 0xff, 0xff, + 0x7f, 0xe0, + + /* U+F56E "" */ + 0x3e, 0x0, 0x7f, 0xc0, 0x3f, 0xf0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xf1, 0x83, 0xff, 0xe1, 0xff, + 0xf4, 0xff, 0xfb, 0x7f, 0xfd, 0xff, 0x8f, 0xff, + 0xff, 0x6f, 0xff, 0xa7, 0xff, 0xc3, 0xff, 0xc0, + 0xff, 0xe0, + + /* U+F56F "" */ + 0x7f, 0xf, 0xf8, 0xff, 0xcf, 0xde, 0xfc, 0xff, + 0xc7, 0xff, 0xff, 0x3f, 0xf3, 0xf0, 0x9f, 0x0, + 0xf0, 0x1f, 0xfb, 0xff, 0x3f, 0xff, 0xf7, 0xfe, + + /* U+F570 "" */ + 0x7f, 0xf, 0xf8, 0xc7, 0xcc, 0x6e, 0xfe, 0x7c, + 0x63, 0xc7, 0xff, 0xff, 0xff, 0xfc, 0x3, 0xc0, + 0x3c, 0x3, 0xc0, 0x3f, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F571 "" */ + 0x7f, 0xf, 0xf8, 0xc6, 0xcf, 0xe6, 0xfe, 0x3c, + 0x7f, 0xc7, 0xff, 0xff, 0xf9, 0xff, 0x1f, 0xf7, + 0xff, 0x8f, 0xfe, 0xff, 0xf, 0xfd, 0xf7, 0xfe, + + /* U+F572 "" */ + 0x3e, 0xf, 0xf0, 0xff, 0x8f, 0xec, 0xfe, 0x6f, + 0xe3, 0xff, 0xfc, 0x1f, 0xd9, 0xfc, 0x1f, 0xc3, + 0xbd, 0x93, 0xdc, 0x7f, 0x83, 0xf9, 0x3f, 0xff, + 0x7f, 0xe0, + + /* U+F573 "" */ + 0x3e, 0x0, 0x3f, 0xe0, 0xf, 0xfc, 0x3, 0xfb, + 0x80, 0xfe, 0x70, 0x3f, 0x8c, 0xf, 0xff, 0x83, + 0xff, 0xe0, 0xff, 0xf9, 0xbf, 0xfc, 0xff, 0xfe, + 0x1f, 0xc7, 0x32, 0xe1, 0x9e, 0x33, 0xf, 0x8f, + 0xe7, 0xc1, 0xf9, 0xe0, 0x0, 0x70, 0x0, 0x0, + 0x0, + + /* U+F574 "" */ + 0x7f, 0xf, 0xf8, 0xfd, 0xcf, 0xce, 0xfc, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xf, 0xe0, + 0x7f, 0x9f, 0xf9, 0xff, 0x9f, 0xff, 0xf7, 0xfe, + + /* U+F575 "" */ + 0x0, 0xe0, 0x31, 0xf0, 0x3b, 0x38, 0x1e, 0x1c, + 0xe, 0xe, 0x1f, 0x7, 0x33, 0x3, 0x60, 0x3, + 0xc0, 0x6, 0xff, 0xfc, 0xff, 0xf8, 0x7f, 0xf0, + 0x3f, 0xe0, 0x1f, 0xc0, 0xf, 0x80, 0x7, 0x0, + + /* U+F576 "" */ + 0x0, 0xe0, 0x18, 0xf8, 0xe, 0xce, 0x3, 0xe3, + 0x80, 0xe0, 0xe0, 0xf8, 0x38, 0xec, 0xc, 0xe0, + 0x6, 0xe0, 0x6, 0x60, 0x7, 0x3f, 0xff, 0xf, + 0xff, 0x3, 0xff, 0x30, 0xff, 0x18, 0x3f, 0x1e, + 0xf, 0xf, 0x0, 0x3, 0x0, + + /* U+F577 "" */ + 0x7, 0xe0, 0xe, 0xc, 0xc, 0x3, 0xc, 0x78, + 0xc6, 0x83, 0x6, 0xde, 0xcb, 0x59, 0xb5, 0xab, + 0x5b, 0xd5, 0xad, 0x8a, 0xd6, 0x85, 0x6b, 0x2, + 0xb5, 0x0, 0x32, 0x0, 0x18, 0x0, 0x8, 0x0, + + /* U+F578 "" */ + 0x0, 0x20, 0x0, 0x7f, 0xc, 0x3f, 0xf3, 0xdf, + 0xfe, 0x7f, 0xff, 0x9f, 0xfc, 0xf7, 0xff, 0x3d, + 0xff, 0xfe, 0xf7, 0xff, 0x30, 0xff, 0x80, 0xf, + 0x80, + + /* U+F579 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf3, 0xcf, 0xed, 0xb7, 0xe1, 0x87, + 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0x7c, 0x3e, + 0x7c, 0x3e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F57A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xf9, 0xdf, + 0xff, 0xff, 0xfe, 0x7f, 0xfc, 0x3f, 0x78, 0x1e, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F57B "" */ + 0xff, 0xff, 0xff, 0xff, 0x70, 0xe, 0x3f, 0xfc, + 0x1f, 0xf8, 0xf, 0xf0, 0x7, 0xe0, 0x3, 0xc0, + 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, 0x1, 0x80, + 0x1, 0x80, 0xf, 0xf0, 0xf, 0xf0, + + /* U+F57C "" */ + 0x7, 0xe0, 0x1c, 0x38, 0x3c, 0xc, 0x7c, 0x6, + 0x7d, 0x82, 0xff, 0x83, 0xfc, 0x1f, 0xf8, 0x1f, + 0xf8, 0xf, 0xf8, 0xf, 0xff, 0x1f, 0x7f, 0x1e, + 0x7f, 0x3e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F57D "" */ + 0x7, 0xe0, 0x18, 0xf8, 0x30, 0xfc, 0x61, 0xfe, + 0x40, 0xfe, 0xc0, 0xf3, 0xc3, 0xf3, 0xf3, 0xf3, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0x7e, 0x3e, + 0x7e, 0x7e, 0x3e, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F57E "" */ + 0x7, 0xe0, 0x1c, 0x78, 0x30, 0x7c, 0x60, 0x7e, + 0x60, 0x5e, 0xc0, 0xdf, 0xc0, 0xff, 0xc1, 0xff, + 0xc1, 0x7f, 0xf9, 0x47, 0xff, 0x83, 0x7b, 0x86, + 0x7f, 0x86, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F57F "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xf9, 0xdf, + 0xff, 0xff, 0xfe, 0xaf, 0xf6, 0xaf, 0x76, 0xae, + 0x7e, 0xae, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F580 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xf9, 0xdf, + 0xff, 0xff, 0xe7, 0xe7, 0xf0, 0xf, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F581 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x79, 0xde, 0xf9, 0xdf, 0xf9, 0xdf, 0xf9, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F582 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x73, 0x8e, 0xe1, 0x7, 0xed, 0x67, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xf7, 0xe0, 0xf, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F583 "" */ + 0x0, 0x3, 0x3, 0xf3, 0xc7, 0xf9, 0xe7, 0xfc, + 0xf7, 0xfe, 0x33, 0x9c, 0x83, 0x84, 0x21, 0xda, + 0xde, 0xff, 0xff, 0x7f, 0xff, 0xbb, 0xff, 0xde, + 0x1, 0xe7, 0x0, 0xe3, 0xc0, 0xf0, 0xf0, 0xf0, + 0x3f, 0xf0, 0x7, 0xe0, 0x0, + + /* U+F584 "" */ + 0x3, 0xe0, 0x1f, 0xf8, 0x7f, 0xfe, 0xc0, 0x93, + 0xc0, 0x83, 0xc0, 0x83, 0xe1, 0xc7, 0xf3, 0xef, + 0xff, 0xff, 0xff, 0xff, 0xe7, 0xe7, 0x70, 0xe, + 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F585 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x77, 0xee, 0xf1, 0x8f, 0xf3, 0xcf, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xf7, 0xe0, 0xf, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F586 "" */ + 0x0, 0x0, 0x0, 0xfc, 0xe0, 0xff, 0xb8, 0x7f, + 0xee, 0x3f, 0xb8, 0xf, 0xc7, 0xc7, 0xf1, 0xf9, + 0xff, 0xee, 0x79, 0xf3, 0x9c, 0x7c, 0xe7, 0x9e, + 0x39, 0xff, 0xe, 0x3f, 0x7, 0x1, 0x83, 0xc7, + 0x7f, 0xe1, 0xdf, 0xf0, 0x73, 0xf0, 0x0, 0x0, + 0x0, + + /* U+F587 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x77, 0xee, + 0xe3, 0xc7, 0xc1, 0x83, 0xe3, 0xc7, 0xe3, 0xc7, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0x70, 0xe, + 0x70, 0xe, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F588 "" */ + 0x1, 0xf8, 0x0, 0x7f, 0xe0, 0xf, 0xff, 0x1, + 0xff, 0xf8, 0x1c, 0x63, 0x83, 0x84, 0x1c, 0x19, + 0x49, 0x80, 0xff, 0xe0, 0xe7, 0xfe, 0x7e, 0xbf, + 0xd7, 0x68, 0x3, 0x60, 0xc0, 0x30, 0x1e, 0x7, + 0x80, 0xf0, 0xf0, 0x7, 0xfe, 0x0, 0x1f, 0x80, + + /* U+F589 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xfb, 0xdf, 0xfb, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xf3, 0xcf, 0xf0, 0xf, 0x78, 0x1e, + 0x7b, 0xde, 0x3b, 0xdc, 0xb, 0xd0, 0x1, 0x80, + + /* U+F58A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x77, 0xee, 0xf9, 0x9f, 0xf1, 0x8f, 0xf7, 0xef, + 0xff, 0xff, 0xef, 0xf7, 0xe0, 0x7, 0x70, 0xe, + 0x7b, 0xde, 0x3b, 0xdc, 0x1b, 0xd8, 0x1, 0x80, + + /* U+F58B "" */ + 0x3, 0xe0, 0x7, 0xfc, 0xf, 0xff, 0xf, 0xff, + 0xc7, 0xfc, 0xf7, 0xd, 0xbb, 0xb6, 0xdf, 0xff, + 0x9f, 0xff, 0xff, 0xf7, 0xff, 0xf8, 0x1, 0xce, + 0x0, 0xe7, 0x34, 0xe1, 0x9e, 0x70, 0x4f, 0x20, + 0x3, 0x80, + + /* U+F58C "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0x87, 0xf9, 0x87, 0xf9, 0xff, + 0xff, 0xff, 0xef, 0xf7, 0xe0, 0xf, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F58D "" */ + 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, 0xf3, 0xcf, + 0x0, 0x0, 0x0, 0x0, 0xf3, 0xcf, 0xf3, 0xcf, + 0xf3, 0xcf, 0xf3, 0xcf, + + /* U+F58E "" */ + 0xf3, 0xfc, 0xff, 0x3f, 0xcf, 0x0, 0x0, 0xf, + 0x3f, 0xcf, 0xf3, 0xfc, 0xf0, 0x0, 0x0, 0xf3, + 0xfc, 0xff, 0x3f, 0xcf, + + /* U+F58F "" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0x6, 0xe0, + 0x1f, 0x0, 0x3c, 0x0, 0xf0, 0x3, 0xf8, 0x7f, + 0xe1, 0xff, 0x87, 0xfe, 0x1f, 0xf8, 0x7f, 0xe1, + 0xf7, 0x87, 0x80, + + /* U+F590 "" */ + 0xf, 0xc0, 0x7f, 0x83, 0x87, 0x18, 0xe, 0xe0, + 0x1f, 0x0, 0x7f, 0x87, 0xfe, 0x3f, 0xf8, 0xff, + 0xe3, 0xff, 0x8f, 0xde, 0x1f, 0x0, 0xc, 0x8, + 0x30, 0x71, 0x81, 0xfc, + + /* U+F591 "" */ + 0x0, 0x6, 0x0, 0xf, 0x80, 0xf, 0xe0, 0xe, + 0x70, 0x1e, 0x30, 0x1c, 0x38, 0x1c, 0x38, 0x1e, + 0x18, 0xf, 0x98, 0x7, 0xfc, 0x7, 0xfc, 0x3, + 0xfc, 0x1, 0xfc, 0x2, 0x70, 0x3, 0x80, 0x1, + 0xe0, 0x0, + + /* U+F593 "" */ + 0x2, 0x61, 0x89, 0x8e, 0x33, 0x18, 0x66, 0x0, + 0xcd, 0xc0, 0xf, 0xe0, 0x3f, 0xfe, 0xff, 0xff, + 0x77, 0x3d, 0xdc, 0xf7, 0x73, 0xdd, 0xcf, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F594 "" */ + 0xff, 0xfe, 0xff, 0xf9, 0xff, 0xf3, 0x36, 0x66, + 0x6c, 0xcf, 0xff, 0x99, 0xb3, 0x33, 0x66, 0x7f, + 0xfc, 0xf8, 0xf9, 0xe0, 0xf3, 0xc1, 0xe7, 0xef, + 0xcf, 0xdf, 0x9f, 0xbf, 0x7f, 0xff, + + /* U+F595 "" */ + 0x0, 0x12, 0x0, 0xd, 0x80, 0x1, 0x20, 0x0, + 0x6c, 0x0, 0x19, 0x80, 0x3, 0x30, 0x0, 0x6c, + 0x0, 0x1b, 0x0, 0x2, 0x40, 0x0, 0x0, 0x1c, + 0xe1, 0xe7, 0x3f, 0xfc, 0xe7, 0xdf, 0xbd, 0xf0, + 0xe7, 0x20, + + /* U+F596 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0x7f, 0x3e, + 0x7f, 0xfe, 0x3f, 0x7c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F597 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x73, 0x8e, 0xe1, 0x7, 0xed, 0x67, 0xed, 0x67, + 0xff, 0xff, 0xfe, 0x3f, 0xff, 0x3f, 0x7e, 0x7e, + 0x7f, 0x3e, 0x3e, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F598 "" */ + 0x7, 0xe0, 0x3, 0xff, 0x0, 0xff, 0xf0, 0x3f, + 0xff, 0x7, 0xff, 0xe1, 0xff, 0x9e, 0x3e, 0x61, + 0xc7, 0xfd, 0xb8, 0xff, 0xf8, 0x1f, 0xc6, 0x43, + 0xfe, 0x9c, 0x3f, 0x17, 0xe7, 0xfa, 0xfe, 0x7c, + 0x4f, 0xc7, 0xfd, 0xf0, 0x1f, 0x10, + + /* U+F599 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xe0, 0x7, 0xe0, 0x7, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F59A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x73, 0x8e, 0xed, 0x67, 0xed, 0x67, 0xff, 0xff, + 0xff, 0xff, 0xe0, 0x7, 0xe0, 0x7, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F59B "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x77, 0xee, 0xf9, 0x9f, 0xf3, 0xcf, 0xff, 0xff, + 0xff, 0xff, 0xe0, 0x7, 0xf0, 0xf, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F59C "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xce, 0xf9, 0x87, 0xf9, 0xb7, 0xff, 0xff, + 0xff, 0xff, 0xe0, 0x7, 0xe0, 0x7, 0x70, 0xe, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F59D "" */ + 0xe0, 0x70, 0x3c, 0x3e, 0x3, 0x8, 0x80, 0xdf, + 0xfc, 0x37, 0xff, 0xd, 0xff, 0xc3, 0x7f, 0xf0, + 0xdf, 0xfc, 0x37, 0xff, 0xd, 0xff, 0xc3, 0x0, + 0x0, 0xc0, 0x0, 0x3f, 0xff, 0xc7, 0xff, 0xf0, + 0xe0, 0x70, 0x30, 0x1c, + + /* U+F59F "" */ + 0x0, 0x0, 0x7, 0xc1, 0xc7, 0xff, 0xf3, 0xf3, + 0xfc, 0xfc, 0x3f, 0x3f, 0xf, 0xcf, 0xc2, 0x3, + 0xf0, 0x3c, 0xfc, 0x1f, 0xbf, 0xf, 0xff, 0xc3, + 0xff, 0xf0, 0xff, 0xff, 0x1f, 0xbf, 0xe7, 0xee, + 0xc, 0xf0, 0x0, 0x3c, 0x0, 0x6, 0x0, + + /* U+F5A0 "" */ + 0x0, 0x0, 0x7, 0xc1, 0xc7, 0xff, 0xf3, 0xf3, + 0xfc, 0xfc, 0x3f, 0x3f, 0xf, 0xcf, 0xc2, 0x3, + 0xf0, 0x3c, 0xfc, 0x1f, 0xbf, 0xe, 0x7f, 0xc3, + 0x9f, 0xf0, 0xe7, 0xff, 0x1f, 0xbf, 0xe7, 0xee, + 0xc, 0xf0, 0x0, 0x3c, 0x0, 0x6, 0x0, + + /* U+F5A1 "" */ + 0x1, 0xbe, 0x2, 0x7f, 0xc, 0xff, 0x19, 0xff, + 0x13, 0xfe, 0x3, 0xfc, 0x9, 0xf8, 0x1c, 0xf0, + 0x3e, 0x60, 0x3f, 0x0, 0x7f, 0x80, 0x7f, 0x0, + 0xfe, 0x0, 0xfc, 0x0, 0xf0, 0x0, + + /* U+F5A2 "" */ + 0x10, 0x61, 0xe1, 0xef, 0x8f, 0x9f, 0x3e, 0x7f, + 0xf0, 0xff, 0xc3, 0xfe, 0xf, 0xfc, 0x3d, 0xf1, + 0xf3, 0xc7, 0x7, 0x9e, 0x3e, 0x78, 0x70, 0xfd, + 0xc3, 0xff, 0x7, 0xf8, 0xf, 0x80, + + /* U+F5A4 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xf9, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F5A5 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xed, 0xb7, 0xe1, 0x87, + 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0x78, 0x1e, + 0x78, 0x1e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F5A6 "" */ + 0x4, 0x1, 0xc0, 0x7c, 0x1f, 0xc3, 0xf8, 0x7f, + 0xf, 0xe1, 0xfc, 0x3f, 0x87, 0xf0, 0xc6, 0x1f, + 0xc3, 0xf8, 0xff, 0x9f, 0xf7, 0xff, 0xff, 0xe0, + + /* U+F5A7 "" */ + 0x0, 0x3, 0x0, 0x7, 0x0, 0x1e, 0x0, 0x3c, + 0x0, 0x78, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfc, 0x3f, 0xfc, + 0x1f, 0xf8, 0x7, 0xe0, 0xf, 0xf0, 0xf, 0xf0, + + /* U+F5AA "" */ + 0x7f, 0xf0, 0xff, 0xf8, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xfb, 0x7f, 0xf3, 0x0, 0x3, 0x0, 0x3, + 0x1, 0xff, 0x3, 0xfe, 0x3, 0x0, 0x7, 0x80, + 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, 0x7, 0x80, + 0x7, 0x80, + + /* U+F5AB "" */ + 0x7f, 0xef, 0xff, 0xf0, 0xfe, 0x7, 0xd7, 0x3d, + 0x6b, 0xd6, 0xbd, 0x73, 0xe0, 0x7f, 0xf, 0xff, + 0xff, 0xff, 0xe0, 0x7e, 0x7, 0xff, 0xf7, 0xfe, + + /* U+F5AC "" */ + 0x0, 0xe, 0x0, 0x1f, 0x0, 0x3f, 0x0, 0x7f, + 0x0, 0xfe, 0x0, 0xfc, 0x1, 0xf8, 0x1, 0xf0, + 0x18, 0xc0, 0x3c, 0x0, 0x7e, 0x0, 0x67, 0x0, + 0x67, 0x0, 0x5e, 0x0, 0xbc, 0x0, 0x40, 0x0, + + /* U+F5AD "" */ + 0x0, 0xc, 0x0, 0x1e, 0x0, 0x3f, 0x1, 0x9f, + 0xf, 0xce, 0x1f, 0xe4, 0x1f, 0xf0, 0x3f, 0xf8, + 0x38, 0xf8, 0x38, 0xf0, 0x70, 0xf0, 0x63, 0xf0, + 0x47, 0xe0, 0x8f, 0x80, 0x1c, 0x0, 0x20, 0x0, + + /* U+F5AE "" */ + 0x18, 0x1c, 0x30, 0x3e, 0x66, 0x3f, 0xfc, 0x9f, + 0xf9, 0xcf, 0x73, 0xe6, 0x27, 0xf0, 0xf, 0xf8, + 0x1f, 0xf0, 0x3f, 0xe4, 0x7f, 0xcc, 0x7f, 0x99, + 0x7f, 0x3b, 0xfe, 0x7e, 0xfc, 0x3c, 0xe0, 0x18, + + /* U+F5AF "" */ + 0x3, 0x0, 0x0, 0xe0, 0x0, 0x3c, 0x3, 0xf, + 0x0, 0xe3, 0xe0, 0x3f, 0xf8, 0xf, 0xff, 0x1, + 0xff, 0xfe, 0x1f, 0xff, 0xc0, 0x1f, 0xf0, 0x0, + 0x18, 0xd, 0x80, 0x0, 0x60, 0x0, 0x0, 0xf, + 0xff, 0xff, 0xff, 0xff, + + /* U+F5B0 "" */ + 0xc, 0x0, 0x7, 0xc0, 0x0, 0xfc, 0x38, 0x1f, + 0xff, 0x7, 0xff, 0xe0, 0xff, 0xcf, 0xff, 0xc1, + 0xff, 0x80, 0x7f, 0x0, 0xe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, + 0xff, 0xfc, + + /* U+F5B1 "" */ + 0xfe, 0x3, 0xfc, 0xc, 0x18, 0x30, 0x60, 0xc1, + 0x83, 0xfc, 0xf, 0xe0, 0xf3, 0x87, 0xc7, 0x3b, + 0xf, 0xc0, 0x1e, 0x0, 0x78, 0x3, 0xf0, 0x1c, + 0xe0, 0xe1, 0xc3, 0x3, + + /* U+F5B3 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xe1, 0x87, 0xed, 0xb7, 0xff, 0xff, + 0xf7, 0xef, 0xf6, 0x6f, 0xf6, 0x6f, 0x76, 0x6e, + 0x76, 0x6e, 0x37, 0xec, 0x17, 0xe8, 0x7, 0xe0, + + /* U+F5B4 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xfb, 0x9f, 0xfb, 0x9f, 0xfb, 0x9f, + 0xff, 0xff, 0xff, 0xff, 0xf3, 0x1f, 0x73, 0xce, + 0x73, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F5B6 "" */ + 0x7f, 0xfe, 0x3f, 0xff, 0xcc, 0x63, 0x33, 0x18, + 0xc6, 0xc6, 0x31, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xdc, 0xfe, 0x73, 0x21, + 0x10, 0xc8, 0x6c, 0x1c, 0xe, 0x0, + + /* U+F5B7 "" */ + 0x7, 0x80, 0x0, 0xfc, 0x0, 0xc, 0xc0, 0x0, + 0xcc, 0x0, 0xc, 0xce, 0x0, 0xf, 0xe0, 0x3, + 0xfe, 0x0, 0xf8, 0xfc, 0x1d, 0x8f, 0xc1, 0x98, + 0x0, 0x7b, 0x3f, 0xef, 0xb3, 0xff, 0x1e, 0x0, + 0x0, 0xe0, 0x0, + + /* U+F5B8 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x73, 0x8e, 0xe1, 0x7, 0xed, 0x67, 0xff, 0xff, + 0xff, 0xff, 0xf7, 0xef, 0xf3, 0xcf, 0x78, 0x1e, + 0x7c, 0x3e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F5BA "" */ + 0x3f, 0xff, 0xf, 0xff, 0xc3, 0x33, 0x31, 0xcc, + 0xce, 0x62, 0x11, 0x9f, 0xff, 0xe6, 0x21, 0x19, + 0x88, 0x46, 0xc2, 0x10, 0xff, 0xff, 0xf7, 0xff, + 0xf8, 0x3, 0x0, 0x0, 0xc0, 0x1, 0xfe, 0x0, + 0x7f, 0x80, + + /* U+F5BB "" */ + 0x0, 0xc0, 0x0, 0x78, 0x0, 0x1e, 0x0, 0xf, + 0xc0, 0x3, 0xf0, 0x3c, 0x78, 0xff, 0xcc, 0xff, + 0xf8, 0x7f, 0xff, 0x3f, 0x9f, 0xff, 0xe3, 0xff, + 0xf0, 0xff, 0xfc, 0xf, 0xfc, 0x1, 0xfe, 0x0, + + /* U+F5BC "" */ + 0x0, 0xc0, 0x1, 0xe0, 0x3, 0xe0, 0xff, 0xf0, + 0xff, 0xf0, 0xff, 0xf8, 0x7f, 0xfe, 0x3f, 0xff, + 0x3f, 0xff, 0x3f, 0xfe, 0x7f, 0xf8, 0x7f, 0xf0, + 0x7f, 0xf0, 0x7f, 0xf0, 0x0, 0xf0, 0x0, 0x70, + + /* U+F5BD "" */ + 0x1c, 0x0, 0x1e, 0xdb, 0x1e, 0xdb, 0x1e, 0x0, + 0x0, 0x1b, 0x7f, 0x9b, 0xff, 0xc0, 0xff, 0xc3, + 0xf3, 0xc3, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, + 0xf3, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, + + /* U+F5BF "" */ + 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, + 0x7, 0xe0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, + 0x3f, 0xfc, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfe, + + /* U+F5C0 "" */ + 0x0, 0xc0, 0x0, 0x30, 0x0, 0x1e, 0x0, 0x7, + 0x80, 0x3, 0xb0, 0xf, 0xef, 0xcf, 0xf9, 0xfd, + 0xfe, 0xe, 0x3f, 0x87, 0x7, 0xe3, 0x80, 0xf8, + 0xc0, 0x3e, 0x30, 0xf, 0xcc, 0x3, 0xff, 0x0, + 0xf3, 0xc0, 0x70, 0x38, + + /* U+F5C1 "" */ + 0x1f, 0x1, 0x18, 0x11, 0x81, 0x18, 0x7f, 0xef, + 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xe3, 0xc, + + /* U+F5C2 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf9, 0xdf, 0xf9, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x7e, 0x7e, + 0x7e, 0x7e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F5C3 "" */ + 0xfc, 0x0, 0xfc, 0x0, 0xcc, 0x20, 0xcc, 0x70, + 0xfc, 0xf8, 0xfc, 0xfc, 0xcc, 0xfc, 0xcc, 0xf8, + 0xfc, 0xf0, 0xfc, 0xe0, 0xfc, 0xcf, 0xfc, 0x9f, + 0xcc, 0x3f, 0xcc, 0x7f, 0xfc, 0xff, 0x79, 0xff, + + /* U+F5C4 "" */ + 0x0, 0x3, 0x0, 0x70, 0x78, 0xf, 0xe7, 0x81, + 0xcf, 0x30, 0x1, 0xf8, 0x0, 0x3f, 0x80, 0x0, + 0xe0, 0x0, 0x0, 0x0, 0xf, 0x9f, 0xf, 0x8f, + 0x1f, 0x0, 0x0, 0x0, + + /* U+F5C5 "" */ + 0x3, 0xc3, 0xc0, 0x7e, 0x7e, 0x6, 0x66, 0x60, + 0x66, 0x66, 0x6, 0x6, 0x0, 0x60, 0x60, 0x7, + 0xfe, 0x0, 0x7f, 0xe0, 0x6, 0x6, 0x0, 0x40, + 0x60, 0x0, 0x0, 0x0, 0x60, 0x60, 0xf, 0x9f, + 0x7, 0x8f, 0x1f, 0x0, 0x0, 0x0, + + /* U+F5C7 "" */ + 0x0, 0x0, 0x30, 0x30, 0x6, 0x1e, 0x0, 0xc7, + 0x80, 0x1b, 0xf0, 0x3, 0xfe, 0x0, 0x7f, 0x80, + 0xf, 0xf0, 0x9, 0xfc, 0x7, 0x3f, 0x81, 0xe7, + 0xe0, 0x7c, 0xf8, 0x1f, 0x9e, 0x3, 0xf3, 0x80, + 0xfe, 0x60, 0x1f, 0xce, 0x1, 0xe1, 0xc0, 0x0, + 0x30, + + /* U+F5C8 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xf3, 0xcf, 0xf9, 0x9f, 0xf3, 0xcf, + 0xff, 0xff, 0xfc, 0x3f, 0xf8, 0x1f, 0x70, 0xe, + 0x77, 0xee, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F5C9 "" */ + 0x3c, 0xf1, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, + 0xff, 0xc3, 0xcf, 0xf, 0x3c, 0x3c, 0xf0, 0xe1, + 0xc3, 0x87, 0x6, 0x18, + + /* U+F5CA "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0x1f, 0xff, 0x7, 0xff, 0x1, 0xff, + 0x3, 0xff, 0x3, 0x1f, 0x7, 0x7, 0x6, 0x0, + 0xe, 0x0, 0xc, 0x0, 0xff, 0xff, 0xff, 0xff, + + /* U+F5CD "" */ + 0x3, 0xc0, 0x7, 0xe0, 0x6, 0x60, 0x6, 0x60, + 0x1f, 0xf8, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, + 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + + /* U+F5CE "" */ + 0x7f, 0x9f, 0xe6, 0x1b, 0x87, 0xc0, 0xf0, 0x3c, + 0xf, 0x3, 0xe1, 0xdf, 0xe3, 0xf0, 0x30, 0xc, + 0x3, 0x0, 0xc1, 0xfe, 0x7f, 0x80, + + /* U+F5D0 "" */ + 0x1e, 0x22, 0x1e, 0x77, 0x1e, 0x22, 0x0, 0x8, + 0x0, 0x1c, 0x7f, 0x88, 0xff, 0xc2, 0xff, 0xc7, + 0xf3, 0xc2, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, + 0xf3, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xc0, + + /* U+F5D1 "" */ + 0x0, 0xc0, 0x7, 0x0, 0x3c, 0x0, 0x40, 0x3c, + 0xf1, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf9, 0xff, + 0xe3, 0xff, 0x7, 0xf8, + + /* U+F5D2 "" */ + 0x7, 0x0, 0x1e, 0x0, 0xcc, 0x1f, 0xfe, 0xff, + 0xff, 0x7f, 0xbf, 0x87, 0xde, 0xde, 0x7b, 0x7b, + 0xe1, 0xfd, 0xfe, 0xff, 0xff, 0x7f, 0xf8, 0x33, + 0x0, 0x78, 0x1, 0xc0, + + /* U+F5D7 "" */ + 0x78, 0x1, 0xef, 0xc0, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, + 0x3f, 0x78, 0x1, 0xe0, + + /* U+F5DA "" */ + 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, 0x7, 0xe0, + 0x3, 0xc0, 0x0, 0x0, 0xfc, 0x3f, 0xff, 0xff, + 0xff, 0xc3, 0xff, 0x3, 0xff, 0x3, 0xff, 0x3, + 0xff, 0x3, 0xff, 0x3f, 0xff, 0xff, 0x3, 0xc0, + + /* U+F5DC "" */ + 0x7, 0x70, 0x7, 0xbc, 0x3, 0xde, 0x7, 0xef, + 0xc3, 0xf7, 0xe1, 0xfb, 0xf0, 0xfd, 0xf8, 0xfe, + 0xfe, 0xff, 0x7f, 0xbf, 0xbf, 0x9f, 0xdf, 0xcf, + 0xef, 0xe7, 0xf7, 0xf3, 0xfb, 0xf8, 0x7d, 0xf0, + 0x1e, 0xf0, + + /* U+F5DE "" */ + 0xf, 0xf0, 0x1f, 0xf8, 0x30, 0xc, 0x30, 0xc, + 0x30, 0xe, 0x7f, 0xfe, 0xff, 0xff, 0xcf, 0xf3, + 0xce, 0x73, 0xfe, 0x7f, 0xff, 0xff, 0x7f, 0xfe, + 0x70, 0xe, 0x70, 0xe, + + /* U+F5DF "" */ + 0x1c, 0x38, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xef, 0xff, 0xef, 0xc1, 0x83, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, + + /* U+F5E1 "" */ + 0x6, 0x0, 0x0, 0xc0, 0x1, 0x99, 0x80, 0x18, + 0x60, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x38, 0x3f, + 0xc0, 0x6, 0x7c, 0x1, 0x80, 0xc6, 0x78, 0x19, + 0x9f, 0xe3, 0x3, 0x3f, 0xe0, 0x67, 0xfe, 0x1f, + 0xfc, 0xc3, 0x9f, 0x98, 0x20, 0x3e, 0x0, 0x1, + 0xc0, 0x0, 0x38, 0x0, 0x2, 0x0, + + /* U+F5E4 "" */ + 0xf, 0xf8, 0x1, 0xff, 0xc0, 0x39, 0x8c, 0x3, + 0x18, 0x60, 0x31, 0x87, 0xf, 0xff, 0xfc, 0xff, + 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x73, 0xfc, 0xe3, 0x20, 0xc8, 0x32, 0xc, + 0x81, 0xc0, 0x70, + + /* U+F5E7 "" */ + 0x7f, 0x80, 0x3f, 0xc0, 0x3e, 0xf1, 0x5f, 0x78, + 0xaf, 0x3d, 0xff, 0xe, 0xff, 0xc7, 0x7f, 0xe7, + 0x9e, 0xf7, 0xc2, 0x7f, 0xe1, 0x3f, 0xfc, 0x9f, + 0xfe, 0x4f, 0xff, 0x27, 0xfe, 0xf3, 0xff, 0x1, + 0xff, 0x80, + + /* U+F5EB "" */ + 0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0xf, 0xf0, + 0x1f, 0xf8, 0x3f, 0x3c, 0x7f, 0x9e, 0xfc, 0xf, + 0xfb, 0x9f, 0x7b, 0x3e, 0x3b, 0xfc, 0x1f, 0xf8, + 0xf, 0xf0, 0x7, 0xe0, 0x3, 0xc0, 0x1, 0x80, + + /* U+F5EE "" */ + 0x60, 0x6, 0xff, 0xff, 0xff, 0xff, 0x60, 0xe, + 0x60, 0x1c, 0x60, 0x18, 0x60, 0x70, 0x60, 0xf0, + 0x60, 0xf0, 0x60, 0x70, 0x60, 0x18, 0x60, 0x1c, + 0x60, 0xe, 0xff, 0xff, 0xff, 0xff, 0x60, 0x6, + + /* U+F5FC "" */ + 0x1f, 0xff, 0x83, 0xff, 0xfc, 0x30, 0x0, 0xc3, + 0x0, 0xc, 0x30, 0x0, 0xc3, 0x19, 0x8c, 0x33, + 0xc, 0xc3, 0x30, 0xcc, 0x31, 0x98, 0xc3, 0x0, + 0xc, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xfe, + + /* U+F5FD "" */ + 0x1, 0x80, 0xf, 0xf0, 0x3f, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0xfc, 0xf, 0xf0, 0x41, 0x87, + 0xf0, 0x1f, 0x7c, 0x7c, 0xf, 0xf0, 0x43, 0x87, + 0xf0, 0x1f, 0x7c, 0x7c, 0xf, 0xf0, 0x3, 0x80, + + /* U+F601 "" */ + 0x0, 0xc0, 0x0, 0xf0, 0x1, 0xfe, 0x1, 0xc7, + 0x81, 0x80, 0xc1, 0xcf, 0x70, 0xcf, 0xd9, 0xe7, + 0xef, 0xf3, 0xf7, 0x99, 0xfb, 0xe, 0x7b, 0x83, + 0x1, 0x80, 0xe3, 0xc0, 0x3f, 0xc0, 0x7, 0x80, + 0x1, 0x80, + + /* U+F604 "" */ + 0x0, 0xc0, 0x1, 0xb6, 0x0, 0xed, 0xc0, 0x7b, + 0x78, 0x3e, 0xdf, 0xf, 0xb7, 0xc7, 0xff, 0xf9, + 0xfc, 0xfe, 0xfe, 0x1f, 0xbf, 0x87, 0xff, 0xe1, + 0xff, 0xf8, 0x7f, 0xfe, 0x1f, 0xff, 0x87, 0xff, + 0xc0, 0xfd, 0xe0, 0x1e, + + /* U+F610 "" */ + 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, 0xf, 0x80, + 0xf, 0xf8, 0xf, 0xfc, 0xf, 0x8e, 0xf, 0x87, + 0xf, 0x83, 0x0, 0x3, 0x0, 0x3, 0x1f, 0xc3, + 0x0, 0x6, 0x0, 0xe, 0xff, 0xff, 0xff, 0xff, + + /* U+F613 "" */ + 0x7, 0xe0, 0x0, 0x7e, 0x0, 0x1, 0x80, 0xf, + 0xff, 0xdf, 0xdf, 0xff, 0xed, 0xff, 0xfc, 0xff, + 0xff, 0x87, 0xff, 0xf0, 0x1f, 0xfe, 0x1, 0xff, + 0xc0, 0x7, 0xf8, 0x0, + + /* U+F619 "" */ + 0x0, 0x0, 0x0, 0xc0, 0x0, 0xe0, 0x1, 0xe0, + 0x7, 0xe0, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, + 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfc, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F61F "" */ + 0x1, 0x0, 0xe, 0x0, 0x7c, 0x1, 0xf0, 0xf, + 0xe0, 0x3f, 0x80, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0xe1, 0xe7, 0xcf, 0xff, 0xbf, 0xfe, 0xff, 0xfb, + 0xf7, 0xcf, 0xce, 0x1e, + + /* U+F621 "" */ + 0x3, 0x80, 0x7, 0x0, 0xe, 0x3, 0x1c, 0x6f, + 0x39, 0xff, 0xff, 0xcf, 0xfe, 0x7, 0xf0, 0xf, + 0xe0, 0x7f, 0xf3, 0xff, 0xff, 0x9c, 0xf6, 0x38, + 0xc0, 0x70, 0x0, 0xe0, 0x1, 0xc0, + + /* U+F624 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7e, 0x7e, + 0x76, 0x6e, 0xfe, 0x7f, 0xfe, 0x7f, 0xde, 0x7b, + 0xde, 0x7b, 0xfe, 0x7f, 0xfc, 0x3f, 0x7c, 0x3e, + 0x7e, 0x7e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F625 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3e, 0x7c, 0x7e, 0x7e, + 0x77, 0xfe, 0xff, 0xcf, 0xff, 0x9f, 0xcf, 0x93, + 0xcf, 0x33, 0xfe, 0x3f, 0xfc, 0x3f, 0x7c, 0x3e, + 0x7e, 0x7e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F629 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7e, 0x7e, + 0x7e, 0x7e, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, + 0xfe, 0x7f, 0xfe, 0x7f, 0xfc, 0x3f, 0x7c, 0x3e, + 0x7e, 0x7e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F62A "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xcf, 0xff, 0x9f, 0xff, 0x9f, + 0xff, 0x3f, 0xfe, 0x3f, 0xfc, 0x3f, 0x7c, 0x3e, + 0x7e, 0x7e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F62E "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf8, 0x8f, 0xc8, 0x8b, 0xc8, 0x8b, 0xff, 0xff, + 0xc8, 0x8b, 0xc8, 0x8b, 0xf8, 0x8f, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, + + /* U+F62F "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xf8, 0x8f, 0xc8, 0x8b, + 0xc8, 0x8b, 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xfe, 0xc8, 0x8b, 0xc8, 0x8b, + 0xf8, 0x8f, 0x7f, 0xfe, + + /* U+F630 "" */ + 0xf, 0xc0, 0xf, 0xc0, 0x7, 0xc7, 0xf3, 0xf7, + 0xfe, 0xfd, 0xff, 0xd8, 0x7f, 0xf6, 0xdc, 0xcd, + 0xf7, 0x33, 0x7d, 0xff, 0xde, 0x7f, 0xf3, 0x1d, + 0xec, 0xf7, 0x3, 0xc, 0xe1, 0x80, 0x3f, 0xe0, + 0x7, 0xf0, 0x0, 0x70, + + /* U+F637 "" */ + 0x7f, 0xbf, 0xff, 0x3f, 0x87, 0xe1, 0xfc, 0xff, + 0xff, 0xcf, 0xe1, 0xf8, 0x7f, 0x3f, 0xff, 0xf3, + 0xf8, 0x7e, 0x1d, 0xce, 0x7f, 0x87, 0x80, + + /* U+F63B "" */ + 0x3, 0xf0, 0x0, 0xfe, 0x0, 0x31, 0x80, 0xc, + 0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xff, 0x99, 0x86, 0x6e, 0x73, + 0x9f, 0x9c, 0xe7, 0x66, 0x19, 0x9f, 0x87, 0xe1, + 0x80, 0x60, + + /* U+F63C "" */ + 0x1, 0xf8, 0x0, 0x1f, 0x80, 0x1, 0x8c, 0x0, + 0x18, 0xe0, 0x1, 0x86, 0x7, 0xff, 0xfe, 0x7f, + 0xff, 0xe7, 0xff, 0xfe, 0x7f, 0xff, 0xef, 0xff, + 0xff, 0xf3, 0xfc, 0xf3, 0x20, 0xcc, 0x32, 0x4, + 0xc1, 0xc0, 0x38, + + /* U+F641 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf7, + 0xe1, 0xc7, 0xed, 0x7, 0xe1, 0x37, 0xed, 0x37, + 0xed, 0x87, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F644 "" */ + 0x1e, 0xf, 0xc7, 0x39, 0x86, 0x61, 0x98, 0x63, + 0x30, 0xfc, 0xff, 0xff, 0xf0, 0xc0, 0x30, 0xc, + 0x3, 0x0, 0xc0, 0x30, + + /* U+F647 "" */ + 0x7f, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xf0, + 0x3f, 0xc0, 0xff, 0xcf, 0xff, 0x3f, 0xfc, 0xff, + 0xf3, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1b, 0x0, + 0x6f, 0xff, 0xdf, 0xff, + + /* U+F64A "" */ + 0x7, 0xe0, 0x1, 0x8, 0x0, 0xc3, 0x1, 0xff, + 0xf8, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xfe, 0x3, + 0xff, 0x0, 0x0, 0x1f, 0x3f, 0xf, 0xef, 0xc7, + 0xbf, 0xfd, 0xef, 0xff, 0x79, 0xff, 0xdf, 0xf7, + 0xf7, 0xfc, 0x0, 0xfe, 0x0, 0x1f, 0x0, + + /* U+F64F "" */ + 0x24, 0x78, 0x19, 0xbf, 0x6, 0x6f, 0xc1, 0xff, + 0x30, 0xff, 0xcc, 0x3f, 0xff, 0xc, 0xcc, 0xfb, + 0x33, 0x3f, 0xff, 0xff, 0xf3, 0x33, 0x3c, 0xcc, + 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfd, 0xff, 0xfe, + + /* U+F651 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0x7e, 0xfc, 0x7f, 0xfd, 0xff, 0xfc, 0x3f, + 0xff, 0xbf, 0xfc, 0x3f, 0x7f, 0x7e, 0x7f, 0xfe, + 0x7f, 0xfc, 0x7f, 0xf8, 0xff, 0xe0, 0xc0, 0x0, + + /* U+F653 "" */ + 0x1f, 0x0, 0xf, 0xf0, 0x7, 0xde, 0x3, 0xc7, + 0xc0, 0xf7, 0xf0, 0x3c, 0x3c, 0xf, 0xef, 0x43, + 0xc3, 0xdc, 0x7d, 0xe7, 0x9f, 0xf3, 0xff, 0xf8, + 0xff, 0x0, 0xff, 0x0, 0x7f, 0xc0, 0xff, 0xf0, + 0x1f, 0xf8, 0x3, 0xfe, 0x0, 0x7f, 0xc0, 0x0, + 0x30, + + /* U+F654 "" */ + 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf, 0x0, 0xf0, 0xf, + 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0x0, 0xf0, + + /* U+F655 "" */ + 0x1, 0x80, 0x7, 0xe0, 0x3f, 0xfc, 0x3d, 0xbc, + 0x3d, 0xbc, 0x7f, 0xfe, 0x67, 0xe6, 0xfe, 0x7f, + 0xfe, 0x7f, 0x67, 0xe6, 0x7f, 0xfe, 0x3d, 0xbc, + 0x3d, 0xbc, 0x3f, 0xfc, 0x7, 0xe0, 0x1, 0x80, + + /* U+F658 "" */ + 0x1, 0x80, 0x3, 0xf0, 0x3, 0x9c, 0x3, 0x87, + 0x7, 0x81, 0xc7, 0x0, 0x3b, 0x0, 0x1, 0xc0, + 0xff, 0xf8, 0x7f, 0xfe, 0x30, 0xff, 0x98, 0x7f, + 0xef, 0xff, 0xf6, 0x3f, 0xfb, 0x1f, 0xfd, 0xfe, + 0xfe, 0xff, 0x0, 0x7f, 0x80, + + /* U+F65D "" */ + 0x3c, 0x0, 0xff, 0x0, 0xff, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, + + /* U+F65E "" */ + 0x7f, 0x0, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0x7f, 0xfe, 0x7f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, + + /* U+F662 "" */ + 0xff, 0xff, 0x3f, 0xff, 0xc7, 0xff, 0xf0, 0xff, + 0xf8, 0x1f, 0xfc, 0x3, 0xf8, 0x0, 0x3d, 0xf0, + 0xe, 0xfe, 0x3, 0x73, 0xc0, 0xdc, 0xf0, 0x37, + 0xfc, 0xd, 0xff, 0x1, 0x71, 0xc0, 0x4f, 0xe0, + 0x1, 0xf0, + + /* U+F664 "" */ + 0x16, 0xd8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1e, 0xf8, + 0x1c, 0xf8, 0x37, 0xcc, 0x76, 0xce, 0x74, 0xce, + 0x74, 0xce, 0xef, 0xe7, 0xef, 0xe7, 0xec, 0x67, + 0xec, 0x67, 0xec, 0x67, 0xef, 0xe7, 0xef, 0xe7, + + /* U+F665 "" */ + 0x1, 0x80, 0x19, 0x98, 0x1d, 0xb8, 0x1d, 0xb8, + 0x1d, 0xb8, 0x1d, 0xb8, 0x1d, 0xb8, 0x1f, 0xf8, + 0x1f, 0xf8, 0xfe, 0x7f, 0xf9, 0x9f, 0x79, 0x9e, + 0x3e, 0x7c, 0x1f, 0xf8, 0xf, 0xf0, 0x7, 0xc0, + + /* U+F666 "" */ + 0x0, 0x80, 0x0, 0xe0, 0x7, 0x77, 0x3, 0xff, + 0x81, 0xf7, 0xc0, 0xe0, 0xe3, 0xf0, 0x7f, 0xe0, + 0xf, 0x38, 0xe, 0xc, 0x6, 0xf, 0x7, 0x8f, + 0xd7, 0xe7, 0xff, 0xf0, 0x3f, 0x80, 0x1d, 0xc0, + 0xc, 0x60, + + /* U+F669 "" */ + 0x18, 0x86, 0xc, 0x20, 0xc3, 0x8, 0x31, 0xc2, + 0x1e, 0x78, 0x87, 0x9f, 0x23, 0xe7, 0xc8, 0xf1, + 0xe2, 0x1e, 0x79, 0xa7, 0x9e, 0x31, 0xe3, 0xbf, + 0x70, 0xe7, 0x9c, 0x3c, 0xcf, 0x7, 0xff, 0x0, + 0x7f, 0x80, + + /* U+F66A "" */ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf5, + 0xbf, 0xd6, 0x7e, 0x49, 0xfd, 0xa7, 0xf0, 0x3f, + 0xe1, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1b, 0x0, + 0x6f, 0xff, 0xdf, 0xff, + + /* U+F66B "" */ + 0x1, 0x80, 0xf, 0xf0, 0x7c, 0x3e, 0xe0, 0x7, + 0xfc, 0x1f, 0x7f, 0xfe, 0x1f, 0xf8, 0xc3, 0xc3, + 0xf8, 0xf, 0x1e, 0x78, 0x8f, 0xf1, 0xfc, 0x3f, + 0xfe, 0x3f, 0x7f, 0xfe, 0xf, 0xf0, 0x3, 0xc0, + + /* U+F66D "" */ + 0x1, 0x80, 0x3, 0xc0, 0x13, 0xc4, 0x67, 0xe6, + 0x6d, 0xb6, 0xed, 0xb7, 0xed, 0xb7, 0xe7, 0xe7, + 0xf3, 0xcf, 0x7b, 0xde, 0x7d, 0xbe, 0x3f, 0xfc, + 0x19, 0x98, 0x7, 0xe0, 0x5, 0xa0, 0x1, 0x80, + + /* U+F66F "" */ + 0x1, 0x80, 0x7, 0xe0, 0xf, 0xf0, 0x3f, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0x36, 0x6c, 0x36, 0x6c, + 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, + 0x36, 0x6c, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + + /* U+F674 "" */ + 0x3f, 0xfc, 0xf, 0xff, 0x3, 0xc0, 0x0, 0xe0, + 0x0, 0x33, 0xff, 0xcd, 0xff, 0xf3, 0x7f, 0x8c, + 0x0, 0xe3, 0xff, 0xd8, 0xff, 0xf7, 0xf7, 0xf9, + 0xfc, 0x78, 0x7f, 0xc0, 0xdf, 0xfc, 0xf0, 0xf, + 0xfc, 0x3, 0xff, 0x0, + + /* U+F676 "" */ + 0x2, 0x8, 0x2d, 0xb6, 0xdb, 0xdb, 0x6d, 0xb0, + 0x0, 0x0, 0xdb, 0x6d, 0xbd, 0xb6, 0xdb, 0xdb, + 0x6d, 0xbd, 0xb6, 0xdb, 0xdb, 0x6d, 0xbc, 0x6, + 0x3, 0xff, 0xff, 0xf7, 0xff, 0xfe, 0x0, 0x60, + 0x0, 0x6, 0x0, 0xf, 0xff, 0x0, 0xff, 0xf0, + + /* U+F678 "" */ + 0x0, 0xc0, 0x0, 0x78, 0x0, 0x7f, 0x80, 0x3f, + 0xf0, 0x1f, 0xfe, 0x7, 0xff, 0x81, 0xff, 0xe0, + 0x3f, 0xf0, 0xc0, 0x0, 0xf0, 0x0, 0x3f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xcf, 0xff, + 0xf3, 0xff, 0xfc, 0xff, 0x7f, 0xff, 0x80, + + /* U+F679 "" */ + 0x0, 0x10, 0x0, 0x10, 0x0, 0xc6, 0x1c, 0xfe, + 0x3e, 0x38, 0x3, 0x0, 0x3, 0x1e, 0x3, 0x3f, + 0x1f, 0xf3, 0x1f, 0xe3, 0x3, 0x83, 0xc1, 0xb3, + 0xc1, 0xb3, 0xe3, 0xbf, 0x7f, 0x1e, 0x3e, 0x0, + + /* U+F67B "" */ + 0x6, 0x6, 0x0, 0xf0, 0xf0, 0xf, 0xf, 0x0, + 0x70, 0xe0, 0x3, 0xfc, 0x0, 0x3f, 0xc0, 0xc7, + 0xfe, 0x3e, 0xff, 0xf6, 0x3f, 0xff, 0xc0, 0x7f, + 0xe0, 0xc7, 0xfe, 0xe, 0xdf, 0xb7, 0x38, 0x91, + 0xc0, 0x19, 0x80, 0x1, 0x8, 0x0, 0x60, 0x60, + + /* U+F67C "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3d, 0xbc, 0x71, 0x8e, + 0x61, 0x86, 0xe1, 0x87, 0xc1, 0x83, 0xc1, 0x83, + 0xc3, 0xc3, 0xc7, 0xe3, 0xff, 0xff, 0x79, 0x9e, + 0x71, 0x8e, 0x3d, 0xbc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F67F "" */ + 0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, 0x7, 0xe0, + 0x7, 0xe0, 0x7, 0xe0, 0x1f, 0xf8, 0x1f, 0xf8, + 0x1f, 0xf8, 0x7f, 0xfe, 0xfe, 0x7f, 0xfc, 0x3f, + 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0x7f, 0xfe, + + /* U+F681 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, + 0xff, 0xf3, 0xfe, 0xcf, 0xfb, 0x3f, 0xec, 0xdf, + 0xb3, 0x7e, 0xcd, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F682 "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, + 0xff, 0xff, 0xfe, 0x1, 0xf8, 0x7, 0xff, 0xff, + 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F683 "" */ + 0x1, 0x80, 0x3c, 0x3, 0xc0, 0x18, 0x0, 0x0, + 0xe0, 0x1f, 0x73, 0xff, 0x3f, 0xe7, 0xd8, 0x78, + 0x7, 0x80, 0x3c, 0x1, 0xf0, 0xff, 0x8f, 0xf8, + + /* U+F684 "" */ + 0x1, 0x8c, 0x0, 0x38, 0xe0, 0x7, 0x7, 0x0, + 0x70, 0x70, 0xe, 0x3, 0x81, 0xc0, 0x1c, 0x1d, + 0x99, 0xc1, 0xd9, 0x9c, 0x1d, 0x99, 0xc1, 0xd9, + 0x9c, 0x1f, 0x9f, 0xcf, 0xf9, 0xff, 0xff, 0x9f, + 0xff, 0xf0, 0xff, 0xfc, 0x3, 0xfe, 0x0, 0x7, + + /* U+F687 "" */ + 0xff, 0xfb, 0xff, 0xff, 0x87, 0xfc, 0x1f, 0xe1, + 0xff, 0x8d, 0xfe, 0x33, 0xf8, 0xcf, 0xf1, 0xff, + 0xe1, 0xff, 0xff, 0xff, 0xff, 0x60, 0xd, 0x80, + 0x3f, 0xff, 0xff, 0xfe, + + /* U+F688 "" */ + 0xf, 0x80, 0x3f, 0xe0, 0x7f, 0xf0, 0x7c, 0xf0, + 0xf0, 0xf8, 0xf3, 0xf8, 0xf0, 0x78, 0xfe, 0x78, + 0xf0, 0x78, 0x7c, 0xf0, 0x7f, 0xf0, 0x3f, 0xf8, + 0xf, 0x9c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, + + /* U+F689 "" */ + 0xf, 0x80, 0x3f, 0xe0, 0x7f, 0xf0, 0x78, 0xf0, + 0xf0, 0x78, 0xf6, 0x78, 0xf6, 0x78, 0xf8, 0xf8, + 0xf8, 0xf8, 0x7d, 0xf0, 0x7f, 0xf0, 0x3f, 0xf8, + 0xf, 0x9c, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, + + /* U+F696 "" */ + 0x7, 0x7e, 0x1e, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0xf7, 0xe1, 0xef, 0xc3, 0xdf, 0x87, 0xbf, 0xe, + 0x7e, 0x39, 0xfc, 0xe7, 0xfb, 0x9f, 0xff, 0x7f, + 0xde, 0xff, 0x3c, 0xf8, 0x3c, 0xe0, + + /* U+F698 "" */ + 0x0, 0x7f, 0xc0, 0x1f, 0xf0, 0x6, 0x0, 0x3, + 0x0, 0x0, 0xc0, 0x0, 0x30, 0xf, 0x1c, 0xcf, + 0xe6, 0x3f, 0x19, 0x87, 0x87, 0x61, 0xe0, 0xf0, + 0xfc, 0x1c, 0x33, 0x7, 0x0, 0x0, 0x80, 0x0, + + /* U+F699 "" */ + 0x7, 0xe0, 0x1f, 0x0, 0x3e, 0x0, 0x7c, 0x0, + 0x78, 0x8, 0xf0, 0x18, 0xf0, 0x3e, 0xf0, 0x7f, + 0xf0, 0x3e, 0xf0, 0x3c, 0xf0, 0x3e, 0x78, 0x2, + 0x7c, 0x0, 0x3c, 0x0, 0x1f, 0x0, 0x7, 0xe0, + + /* U+F69A "" */ + 0x1, 0x80, 0x3, 0xc0, 0x3, 0xc0, 0x6, 0x60, + 0xff, 0xff, 0xff, 0xff, 0x4c, 0x32, 0x78, 0x1e, + 0x30, 0xc, 0x30, 0xc, 0x78, 0x1e, 0x4c, 0x32, + 0xff, 0xff, 0xff, 0xff, 0x6, 0x60, 0x3, 0xc0, + 0x3, 0xc0, 0x1, 0x80, + + /* U+F69B "" */ + 0x60, 0x3, 0x78, 0x3, 0xfc, 0x21, 0xe0, 0x78, + 0x0, 0x77, 0x7, 0xfb, 0xff, 0xfd, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, + 0xc7, 0xff, 0xe3, 0xff, 0xf1, 0xff, 0xf8, 0xfe, + 0xff, 0xfe, + + /* U+F6A0 "" */ + 0xe0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xc0, 0xff, + 0xf8, 0x7f, 0xfe, 0x1f, 0xff, 0x3, 0xff, 0xf3, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x80, 0x7, + + /* U+F6A1 "" */ + 0x0, 0x3, 0x0, 0x3f, 0xff, 0xff, 0xff, 0x7f, + 0xf8, 0xcc, 0xc3, 0x33, 0x1f, 0xfe, 0x7f, 0xf8, + 0xc0, 0xc3, 0x3, 0xc, 0xc, 0x30, 0x30, 0xc0, + 0xc3, 0x3, 0xc, 0xc, + + /* U+F6A7 "" */ + 0x0, 0xc0, 0x0, 0x78, 0x0, 0x7f, 0x80, 0x3f, + 0xf0, 0x1f, 0xfe, 0x3, 0x3, 0x0, 0xc0, 0xc0, + 0x7f, 0xf8, 0x3f, 0xff, 0x1f, 0xff, 0xe3, 0x0, + 0x30, 0xc0, 0xc, 0x3f, 0xff, 0x3f, 0xff, 0xf3, + 0xc, 0x30, 0xc3, 0xc, + + /* U+F6A9 "" */ + 0x1, 0x80, 0x1, 0xc0, 0x1, 0xe0, 0x1, 0xf0, + 0xf, 0xf9, 0xf, 0xfc, 0xff, 0xfe, 0x3d, 0xff, + 0x1e, 0xff, 0x9f, 0xff, 0xc8, 0x43, 0xe0, 0x0, + 0xf0, 0x0, 0x38, 0x0, 0xc, 0x0, + + /* U+F6AD "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3c, 0x3c, 0x70, 0x1e, + 0x61, 0x9e, 0xe1, 0x9f, 0xc0, 0x1f, 0xc0, 0x3f, + 0xc3, 0xff, 0xc7, 0xff, 0xe6, 0x7f, 0x66, 0x7e, + 0x77, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F6B6 "" */ + 0x39, 0xff, 0xcf, 0x7f, 0xe7, 0x9f, 0xc1, 0x87, + 0xf0, 0x61, 0xff, 0xb8, 0x7f, 0xce, 0xf, 0xc1, + 0x83, 0xf0, 0x78, 0xff, 0x1e, 0x3f, 0xc3, 0xcf, + 0xe0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x7b, 0xc0, + 0x1e, 0xf0, 0x7, 0xfc, + + /* U+F6B7 "" */ + 0x7f, 0xff, 0xe3, 0xff, 0x87, 0xfe, 0xdf, 0xf8, + 0x7f, 0xf3, 0xff, 0xff, 0xfc, 0xcf, 0xfc, 0xff, + 0xcc, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1b, 0x0, + 0x6f, 0xff, 0xdf, 0xff, + + /* U+F6BB "" */ + 0x6, 0x60, 0x7, 0xe0, 0x3, 0xc0, 0x1, 0x80, + 0x3, 0xc0, 0x7, 0xe0, 0xf, 0xf0, 0x1f, 0xf8, + 0x1f, 0xf8, 0x3f, 0xfc, 0x7e, 0x7e, 0xfc, 0x3f, + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, + + /* U+F6BE "" */ + 0x0, 0x21, 0x0, 0x33, 0x0, 0x3f, 0x40, 0x3f, + 0xe0, 0x2d, 0x70, 0x3f, 0x30, 0x1e, 0x37, 0x9c, + 0x3f, 0xe0, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xec, + 0x3f, 0xcc, 0x3f, 0x8c, 0x3f, 0xcc, 0x1f, 0xcc, + + /* U+F6C0 "" */ + 0x7, 0x80, 0x73, 0x81, 0x4a, 0xd, 0x2c, 0x34, + 0xb0, 0xd2, 0xc3, 0x4b, 0xd, 0x2c, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x60, 0x19, 0x80, + 0x66, 0x1, 0x98, 0x6, + + /* U+F6C3 "" */ + 0x0, 0xf, 0x0, 0xf, 0x80, 0x7, 0xc0, 0x1, + 0xe0, 0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x80, + 0x38, 0x30, 0x1f, 0xe6, 0x7, 0xfd, 0xf7, 0xff, + 0x3f, 0xff, 0xe4, 0xff, 0xfc, 0x3f, 0xff, 0xf, + 0xff, 0xc1, 0xff, 0xe0, + + /* U+F6C4 "" */ + 0x0, 0x44, 0x0, 0x3b, 0x80, 0xf, 0xe0, 0xf, + 0xfe, 0x7, 0x83, 0xc0, 0x2e, 0xe0, 0x0, 0xb8, + 0x38, 0xe, 0x1f, 0x73, 0x8f, 0xfe, 0xf3, 0xff, + 0x81, 0xff, 0xf8, 0xff, 0xff, 0x3f, 0xff, 0xcf, + 0xff, 0xf3, 0xff, 0xfc, 0x7f, 0xfe, 0x0, + + /* U+F6C8 "" */ + 0x1f, 0xfe, 0x3, 0xff, 0xf0, 0x78, 0xf, 0x87, + 0xc1, 0xff, 0x7e, 0x3f, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xfd, 0xff, 0xdf, 0x1d, 0xfd, 0xd1, 0xcb, + 0xdf, 0x1c, 0x1c, 0xf1, 0xc1, 0xc6, + + /* U+F6CF "" */ + 0x1, 0x80, 0x7, 0xe0, 0x1e, 0x78, 0x3e, 0x7c, + 0xfd, 0x3f, 0x9d, 0xb9, 0xc0, 0x3, 0xf0, 0xf, + 0xf0, 0xf, 0xe3, 0xc7, 0xed, 0xb7, 0xcd, 0xb3, + 0xce, 0x73, 0xe0, 0x7, 0x3c, 0x3c, 0x1e, 0x78, + 0x6, 0x60, 0x1, 0x80, + + /* U+F6D1 "" */ + 0x3, 0x80, 0x1f, 0xc0, 0xff, 0xe3, 0xff, 0xef, + 0xff, 0xf9, 0xfc, 0xf8, 0xe3, 0xfc, 0x9f, 0xfe, + 0xff, 0xfd, 0xff, 0xfb, 0xff, 0xf7, 0xf7, 0xef, + 0xc3, 0xde, 0x3, 0xf8, 0x1, 0xc0, + + /* U+F6D3 "" */ + 0x0, 0x30, 0x0, 0xf, 0x80, 0x3, 0xdc, 0x0, + 0xf7, 0x0, 0x3f, 0xf0, 0xf, 0xef, 0xf8, 0x81, + 0xff, 0x80, 0x3f, 0xf8, 0xf, 0xfe, 0x3, 0xff, + 0x80, 0xff, 0xe0, 0x39, 0x38, 0xe, 0xe, 0x3, + 0x83, 0x80, 0xe0, 0xe0, 0x38, 0x38, 0x0, + + /* U+F6D5 "" */ + 0x0, 0x7f, 0x0, 0x3, 0xf8, 0x0, 0x7e, 0xc0, + 0xc7, 0xfe, 0x1e, 0x1f, 0xe3, 0xf9, 0xde, 0x7f, + 0xdc, 0xf, 0x7d, 0xe0, 0xf, 0xdf, 0x81, 0xfc, + 0xfc, 0x0, 0xf, 0xe0, 0x0, 0x7f, 0x0, 0x3, + 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xef, 0xff, 0xfc, + + /* U+F6D7 "" */ + 0x0, 0xf8, 0x1, 0xfc, 0x3, 0xfe, 0x3, 0xff, + 0x7, 0xff, 0x7, 0xf8, 0x7, 0xf0, 0x7, 0xe0, + 0x7, 0xe0, 0xf, 0xe0, 0xff, 0xf0, 0xfe, 0x0, + 0xfc, 0x0, 0x7c, 0x0, 0x3c, 0x0, 0x1c, 0x0, + + /* U+F6D9 "" */ + 0x3, 0xc0, 0x13, 0xc8, 0x39, 0x9c, 0x78, 0x1e, + 0x38, 0x1c, 0x41, 0x82, 0xe5, 0xa7, 0xf5, 0xaf, + 0xf5, 0xaf, 0x5, 0xa0, 0x5, 0xa0, 0xf5, 0xaf, + 0xf5, 0xaf, 0xf5, 0xaf, 0xf5, 0xaf, 0xf5, 0xaf, + + /* U+F6DD "" */ + 0x3e, 0x0, 0x7f, 0xc0, 0x3f, 0xf0, 0x1f, 0xdc, + 0xf, 0xe7, 0x7, 0xf1, 0x83, 0xff, 0xe1, 0xff, + 0xf0, 0xff, 0xf8, 0x7f, 0xfc, 0x3f, 0xfe, 0x1f, + 0x80, 0xf, 0x9b, 0xaf, 0xd5, 0x17, 0xe8, 0xea, + 0xf5, 0x17, 0x1, 0xb9, 0x0, + + /* U+F6DE "" */ + 0x4, 0x6, 0xf8, 0x7f, 0x87, 0xfb, 0x1, 0xb0, + 0x1b, 0x7c, 0x3f, 0xdc, 0xe3, 0xff, 0xff, 0x7f, + 0xe3, 0xfe, 0x1f, 0xc1, 0xfc, 0x1f, 0xc0, 0xfc, + + /* U+F6E2 "" */ + 0xf, 0x3, 0xfc, 0x7f, 0xe7, 0xfe, 0xff, 0xfe, + 0x67, 0xe6, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xd1, 0x98, + + /* U+F6E3 "" */ + 0x0, 0x0, 0x0, 0x3f, 0x0, 0x7, 0xf0, 0x0, + 0x3f, 0x0, 0x7, 0xf0, 0x0, 0xfe, 0x0, 0xf, + 0xc0, 0xc, 0xff, 0x3, 0xc7, 0xe0, 0xfc, 0x78, + 0x3f, 0xe, 0xf, 0xc0, 0x3, 0xf0, 0x0, 0xfc, + 0x0, 0x1f, 0x0, 0x3, 0xc0, 0x0, 0x70, 0x0, + 0x0, + + /* U+F6E6 "" */ + 0x0, 0x40, 0x1, 0x56, 0xa8, 0xd5, 0xa, 0xbd, + 0x50, 0xab, 0x0, 0x60, 0xd, 0x56, 0xab, 0xd5, + 0x6a, 0xbd, 0x56, 0xab, 0xd5, 0x6a, 0xbc, 0x6, + 0x3, 0xff, 0xff, 0xf7, 0xff, 0xfe, 0x0, 0x60, + 0x0, 0x6, 0x0, 0xf, 0xff, 0x0, 0xff, 0xf0, + + /* U+F6E8 "" */ + 0x0, 0x18, 0x0, 0x70, 0x1, 0xf0, 0x3, 0xf0, + 0x6, 0x30, 0x7, 0x70, 0xf, 0xf0, 0xf, 0xf0, + 0x1c, 0xf8, 0x18, 0x78, 0x18, 0x78, 0x3c, 0xfc, + 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + + /* U+F6EC "" */ + 0x7, 0x0, 0x78, 0x3, 0xc0, 0x0, 0x6, 0x1, + 0xf7, 0x8f, 0xbe, 0x7d, 0xff, 0xef, 0xff, 0x78, + 0xc3, 0xc6, 0xe, 0x30, 0x39, 0x84, 0xec, 0x73, + 0x67, 0x1b, 0x70, 0xdb, 0x2, 0xc0, + + /* U+F6ED "" */ + 0x0, 0x4, 0x40, 0x7f, 0x7c, 0x1f, 0xff, 0xc3, + 0xff, 0xd4, 0x3f, 0xff, 0xe7, 0xff, 0xff, 0x7f, + 0xdd, 0xb7, 0xfd, 0xff, 0x7f, 0xef, 0xef, 0xff, + 0x66, 0xbf, 0xf0, 0x3, 0xc3, 0xc0, 0x3c, 0x3c, + 0x3, 0xc3, 0xc0, + + /* U+F6F0 "" */ + 0x0, 0xf, 0xc0, 0x7, 0xf0, 0x3, 0xec, 0x0, + 0xff, 0x1f, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xeb, + 0x7f, 0xf8, 0xdf, 0xfc, 0x33, 0xff, 0x0, 0xe7, + 0x80, 0x78, 0xe0, 0x1c, 0x38, 0x7, 0x8e, 0x0, + 0xe3, 0x80, 0x38, 0xe0, + + /* U+F6F1 "" */ + 0x0, 0x80, 0x0, 0xe0, 0x0, 0xfb, 0x80, 0xff, + 0xc0, 0xff, 0xe0, 0xff, 0xf1, 0xff, 0xfc, 0xff, + 0xfe, 0x7f, 0xff, 0x1f, 0x3f, 0xf, 0xcf, 0x87, + 0xe3, 0xc3, 0xe3, 0xe1, 0xe3, 0xf0, 0xf1, 0xf8, + 0x38, 0xf8, + + /* U+F6F2 "" */ + 0x3, 0x81, 0xfc, 0x1c, 0xe0, 0x6, 0x0, 0x6f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x0, 0x30, + 0x3, 0xbe, 0x1f, 0xe0, 0xc0, + + /* U+F6FA "" */ + 0x7, 0xf8, 0xf, 0xff, 0xc7, 0xff, 0xf9, 0xff, + 0xfe, 0xf3, 0xf3, 0xf8, 0x78, 0x7e, 0x1e, 0x1f, + 0xcf, 0xcf, 0xff, 0xff, 0xdf, 0xcf, 0xe3, 0xf3, + 0xf0, 0x78, 0x78, + + /* U+F6FC "" */ + 0x1, 0x80, 0x1, 0x80, 0x3, 0xc0, 0x7, 0xe0, + 0x6, 0x60, 0xe, 0x70, 0xc, 0x30, 0x1c, 0xf8, + 0x1d, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + + /* U+F6FF "" */ + 0x3, 0xf0, 0x0, 0xfc, 0x0, 0x33, 0x0, 0xf, + 0xc0, 0x3, 0xf0, 0x0, 0x30, 0xf, 0xff, 0xff, + 0xff, 0xff, 0xc, 0xc, 0xf, 0xcf, 0xc3, 0xf3, + 0xf0, 0xcc, 0xcc, 0x3f, 0x3f, 0xf, 0xcf, 0xc0, + + /* U+F700 "" */ + 0x1f, 0x0, 0x1, 0x8c, 0xc, 0x18, 0x30, 0x38, + 0xeb, 0x80, 0xe6, 0x6f, 0x3, 0x3f, 0xf8, 0xdc, + 0xff, 0x86, 0xe6, 0x1e, 0x77, 0x30, 0x77, 0xb9, + 0xf8, 0x3f, 0xc7, 0xc1, 0xfc, 0x3f, 0xff, 0xc0, + 0xff, 0xfc, 0x1, 0xff, 0x80, + + /* U+F70B "" */ + 0xf, 0xf0, 0x3f, 0xfc, 0x70, 0xe, 0xc0, 0x3, + 0xcf, 0xf3, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfc, 0xf, 0xf0, + + /* U+F70C "" */ + 0x1, 0x80, 0x1e, 0x0, 0x60, 0x0, 0x0, 0x0, + 0x1f, 0x81, 0xfe, 0xc, 0xf8, 0x6f, 0xf8, 0x7b, + 0xc3, 0x80, 0x1f, 0x80, 0x3e, 0xc, 0x30, 0xe3, + 0xe, 0x18, 0xe1, 0x86, 0xc, 0x0, + + /* U+F70E "" */ + 0x7f, 0xf8, 0x33, 0xff, 0xc, 0xff, 0xe3, 0x3f, + 0xf8, 0xff, 0xfe, 0x3, 0xff, 0x80, 0xff, 0xe0, + 0x3f, 0xf8, 0xf, 0x0, 0x3, 0x80, 0x0, 0xe7, + 0xfc, 0x3b, 0xff, 0xe, 0xff, 0xc3, 0xbf, 0xe0, + + /* U+F714 "" */ + 0x7, 0x80, 0x7f, 0x81, 0xfe, 0xf, 0xfc, 0x33, + 0x30, 0xcc, 0xc1, 0xfe, 0x7, 0xf8, 0xf, 0xc0, + 0x3f, 0xc, 0x0, 0xfe, 0x1f, 0x3f, 0xf0, 0x3f, + 0x3, 0xff, 0x3e, 0x1f, 0xc0, 0xc, + + /* U+F715 "" */ + 0xc0, 0x0, 0x38, 0x0, 0x7, 0x0, 0x0, 0xe0, + 0x0, 0x1c, 0x0, 0x3, 0x80, 0x0, 0x70, 0x0, + 0xe, 0x0, 0x1, 0xc0, 0x0, 0x38, 0x0, 0x7, + 0x0, 0x0, 0xe0, 0x0, 0x1c, 0x0, 0x3, 0x80, + 0x0, 0x70, 0x0, 0xe, 0x0, 0x1, 0xc0, 0x0, + 0x30, + + /* U+F717 "" */ + 0x8, 0x10, 0x18, 0x18, 0x18, 0x8, 0x10, 0x8, + 0x33, 0xcc, 0xfb, 0xdf, 0xdf, 0xfb, 0x7f, 0xfe, + 0x3f, 0xfc, 0x3f, 0xfc, 0x7f, 0xfe, 0xdf, 0xfb, + 0xff, 0xff, 0x37, 0xec, 0x13, 0xc8, 0x18, 0x8, + 0x18, 0x18, 0x8, 0x18, + + /* U+F71E "" */ + 0x3f, 0xcc, 0x7f, 0xde, 0x7f, 0x9e, 0xff, 0xbf, + 0xff, 0xb3, 0xff, 0xb3, 0xff, 0xb3, 0xff, 0xb3, + 0xff, 0xbf, 0xff, 0x9e, 0xff, 0x9e, 0xff, 0x8c, + 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0x7f, 0x0, + + /* U+F71F "" */ + 0x3f, 0xcc, 0x7f, 0xde, 0x7f, 0x9e, 0xff, 0xbf, + 0xff, 0xb3, 0xff, 0xb3, 0xff, 0xb3, 0xff, 0xb3, + 0xff, 0xbf, 0xff, 0x9e, 0xff, 0x9e, 0xff, 0x8c, + 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0x7f, 0x0, + + /* U+F722 "" */ + 0x1f, 0x80, 0x7, 0xe0, 0x1, 0x8c, 0x20, 0x63, + 0x8, 0x18, 0x62, 0x7, 0xff, 0xf7, 0xff, 0xfd, + 0xff, 0xff, 0x73, 0xff, 0xf8, 0x7f, 0xee, 0x1f, + 0xf9, 0xce, 0x33, 0x7f, 0x8c, 0xdf, 0xc3, 0xf0, + 0xc0, 0x78, + + /* U+F728 "" */ + 0x6, 0x0, 0xec, 0x0, 0x0, 0x0, 0x1, 0xfc, + 0xf, 0xe0, 0x3e, 0x0, 0xe0, 0x0, 0x0, 0x0, + 0x3, 0xf0, 0x4f, 0xc7, 0x7, 0x78, 0x1f, 0xee, + 0xff, 0x37, + + /* U+F729 "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xff, 0x3f, 0xbf, 0x87, + 0xc7, 0xe1, 0xf1, 0xf8, 0x7c, 0x7f, 0x3f, 0xbf, + 0xff, 0xff, 0xff, 0x3f, 0xdf, 0x87, 0xe0, + + /* U+F72B "" */ + 0x2, 0x3, 0x7, 0x7, 0x22, 0xe, 0x20, 0x1c, + 0xf8, 0x38, 0x20, 0x78, 0x21, 0xe0, 0x3, 0xc0, + 0xf, 0xc0, 0xf, 0x84, 0x1f, 0x4, 0x3e, 0x1f, + 0x7c, 0x4, 0xf8, 0x4, 0xf0, 0x0, 0x60, 0x0, + + /* U+F72E "" */ + 0x0, 0x78, 0x0, 0x7c, 0x0, 0xc, 0x0, 0xc, + 0xff, 0xfc, 0xff, 0xf8, 0x0, 0x0, 0xff, 0xfe, + 0xff, 0xff, 0x0, 0x3, 0x78, 0x3, 0xfe, 0x1f, + 0x7f, 0x1e, 0x3, 0x0, 0x1f, 0x0, 0x1e, 0x0, + + /* U+F72F "" */ + 0x1e, 0x7, 0x81, 0xe0, 0x78, 0x1e, 0x7, 0x81, + 0xe1, 0xfe, 0x7f, 0xbf, 0xff, 0xff, 0x3, 0xc0, + 0xf0, 0x3c, 0xf, 0x3, 0xc0, 0xff, 0xff, 0xfd, + 0xfe, + + /* U+F73B "" */ + 0xe, 0x0, 0x1f, 0x70, 0x3f, 0xf8, 0x3f, 0xf8, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf8, 0x1f, 0x71, 0x8e, 0x7, 0xe0, 0xe7, 0xe7, + 0xef, 0xf7, 0xe7, 0xe7, 0x7, 0xe0, 0x1, 0x80, + + /* U+F73C "" */ + 0x0, 0xe, 0x0, 0xf, 0x0, 0x3, 0xc0, 0xf0, + 0xe0, 0x3f, 0x38, 0x1f, 0xe6, 0x7, 0xfc, 0xc3, + 0xff, 0xb8, 0xff, 0xef, 0xff, 0xfb, 0xc7, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x19, 0x10, 0x4, + 0xcc, 0x1, 0x32, 0x0, + + /* U+F73D "" */ + 0xe, 0x0, 0x1f, 0x70, 0x3f, 0xf8, 0x3f, 0xf8, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x10, 0x8, 0x31, 0x8c, 0x31, 0x8c, 0x31, 0x8c, + + /* U+F740 "" */ + 0xe, 0x0, 0x1f, 0x70, 0x3f, 0xf8, 0x3f, 0xf8, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x26, 0x44, 0x66, 0x4c, 0x64, 0xcc, 0x44, 0x88, + + /* U+F743 "" */ + 0x0, 0x0, 0x7, 0x70, 0x1, 0xfc, 0x0, 0x7f, + 0x0, 0xf8, 0x6, 0x1c, 0x9f, 0xc7, 0x67, 0xf9, + 0xd3, 0xfe, 0x71, 0xff, 0xfe, 0x7f, 0xf1, 0xdf, + 0xfc, 0x73, 0xfe, 0x1c, 0x0, 0x0, 0x0, 0x0, + 0x8, 0x98, 0x6, 0x66, 0x1, 0x91, 0x0, + + /* U+F747 "" */ + 0x24, 0x0, 0x3, 0xc0, 0x0, 0x18, 0x0, 0x3, + 0xc0, 0x0, 0x7e, 0x0, 0xf, 0xff, 0xfc, 0xff, + 0xff, 0xee, 0x66, 0xdf, 0x6, 0x6d, 0xa0, 0x3f, + 0xf8, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x3, 0xff, + 0x80, 0x38, 0x38, 0x3, 0x83, 0x80, 0x38, 0x38, + + /* U+F74D "" */ + 0xc0, 0x3, 0xfc, 0x3f, 0x7f, 0xff, 0x3e, 0xff, + 0x7, 0xff, 0xfc, 0xf, 0xbf, 0xc1, 0xff, 0xff, + 0x3, 0xef, 0xf0, 0x7f, 0xff, 0xc0, 0xfb, 0x0, + 0xc, 0x0, 0x30, 0x0, + + /* U+F751 "" */ + 0xc, 0x3, 0xc0, 0x7c, 0x7, 0xf0, 0xff, 0xcf, + 0xe, 0xe0, 0x6e, 0x67, 0xe6, 0x76, 0x7, 0x70, + 0xf3, 0xff, 0xf, 0xe0, 0x3e, 0x3, 0xc0, 0x30, + + /* U+F752 "" */ + 0x1, 0x80, 0x3, 0xc0, 0xf, 0xf0, 0x1f, 0xf8, + 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, + 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, 0x36, 0x6c, + 0x36, 0x6c, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, + + /* U+F753 "" */ + 0x0, 0x3, 0x0, 0x8f, 0x3, 0xfe, 0xf, 0xfe, + 0x1f, 0xfc, 0x3f, 0xfc, 0x70, 0xfc, 0xe0, 0x7e, + 0xcc, 0x3c, 0xcc, 0x3c, 0xc0, 0x38, 0xc2, 0x38, + 0x60, 0x70, 0x70, 0xe0, 0x3f, 0xc0, 0xf, 0x80, + + /* U+F756 "" */ + 0x70, 0x0, 0x78, 0xff, 0xdc, 0x7f, 0xe0, 0x3f, + 0xf0, 0x1f, 0xfb, 0x8f, 0xff, 0xc6, 0xff, 0xf0, + 0x7f, 0xff, 0x1f, 0xff, 0x8f, 0xfc, 0xf, 0xee, + 0x7, 0xf3, 0x9b, 0xfc, 0xed, 0xff, 0x36, 0xff, + 0x9b, 0x3, 0xcd, 0x81, 0xe2, 0xc0, 0xc0, + + /* U+F75A "" */ + 0x0, 0x0, 0x0, 0xc0, 0x0, 0xe0, 0x1, 0xe0, + 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, + 0x7e, 0x1e, 0xfc, 0x9f, 0xf9, 0x9f, 0xf3, 0x9f, + 0x67, 0x8e, 0xf, 0xe0, 0x3, 0xc0, 0x3, 0x80, + 0x3, 0x0, 0x6, 0x0, + + /* U+F75B "" */ + 0x1, 0xf8, 0x0, 0x7f, 0xe0, 0x1e, 0x7, 0x83, + 0x80, 0x1c, 0x31, 0xf0, 0xc6, 0x7f, 0xc6, 0x6e, + 0xe, 0x6c, 0xcf, 0x63, 0xd9, 0xfb, 0x3d, 0x99, + 0xb3, 0xd9, 0x9b, 0x3d, 0x99, 0xb3, 0xd9, 0x9b, + 0x30, + + /* U+F75E "" */ + 0x1f, 0xfc, 0x7, 0xff, 0xf0, 0x7f, 0xff, 0xe, + 0xee, 0x78, 0xee, 0xe7, 0x8f, 0xff, 0xf8, 0xff, + 0xff, 0x80, 0x0, 0x0, 0xff, 0xff, 0x8f, 0xff, + 0xfb, 0xff, 0xfd, 0xbf, 0x7, 0xdb, 0xf0, 0x7d, + 0xfe, 0x3, 0xce, + + /* U+F75F "" */ + 0x1f, 0xf0, 0xf, 0xfe, 0x7, 0xff, 0xe1, 0xff, + 0xfc, 0x7f, 0xff, 0x9f, 0xff, 0xe7, 0xff, 0xf8, + 0xff, 0xfc, 0x1f, 0xfe, 0x0, 0x1e, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf7, 0xff, + + /* U+F769 "" */ + 0x1e, 0x3c, 0x7e, 0xfc, 0xcd, 0x99, 0x9b, 0x33, + 0x33, 0xc6, 0x60, 0xc, 0xc0, 0x19, 0x80, 0x33, + 0x0, 0xe6, 0x3, 0xc6, 0x7, 0xc, 0xe, 0x18, + 0x1e, 0x60, 0x1f, 0xc0, 0x1e, 0x0, + + /* U+F76B "" */ + 0x1c, 0x3c, 0x7c, 0xfc, 0xf9, 0x99, 0xf3, 0xf3, + 0xe3, 0xc7, 0xc0, 0xf, 0x80, 0x1f, 0x0, 0x77, + 0x0, 0xee, 0x3, 0x8e, 0x7, 0x1c, 0xe, 0x38, + 0x1e, 0xf0, 0x1f, 0xc0, 0x1f, 0x0, + + /* U+F76C "" */ + 0xe, 0x0, 0x1f, 0x70, 0x3f, 0xf8, 0x3f, 0xf8, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0x1f, 0xfe, 0x1f, + 0xfc, 0xcf, 0x79, 0xde, 0x3, 0x80, 0x7, 0xe0, + 0x7, 0xe0, 0x1, 0xc0, 0x3, 0x80, 0x3, 0x0, + 0x0, 0x0, + + /* U+F76F "" */ + 0xff, 0xfb, 0xff, 0xef, 0xff, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x83, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xf0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x1, + 0xe0, 0x7, 0x0, 0x18, + + /* U+F770 "" */ + 0x1, 0x80, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, + 0x3, 0xc0, 0x1, 0x80, 0x0, 0x0, 0x3, 0xc0, + 0x4, 0x20, 0xc, 0x30, 0x1f, 0x18, 0x3f, 0xdc, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + + /* U+F772 "" */ + 0xf, 0xfc, 0x7, 0xff, 0x81, 0xff, 0xe0, 0x7f, + 0x38, 0x1f, 0xce, 0x7, 0x67, 0x81, 0xc3, 0xe0, + 0x78, 0xf8, 0x1f, 0x7e, 0x37, 0xff, 0xbc, 0xff, + 0xcf, 0x0, 0x3, 0xc0, 0x0, 0xdf, 0xff, 0xe0, + + /* U+F773 "" */ + 0x0, 0x0, 0x3e, 0x7c, 0xe3, 0xc7, 0x0, 0x0, + 0x0, 0x0, 0x3e, 0x7c, 0xe3, 0xc7, 0x0, 0x0, + 0x0, 0x0, 0x1c, 0x38, 0x3e, 0x7c, 0xe3, 0xc7, + + /* U+F77C "" */ + 0x6, 0x0, 0xf0, 0xf, 0xc, 0xe3, 0xf0, 0xf7, + 0xfe, 0x3f, 0xc1, 0xf8, 0x0, 0x0, 0x0, 0x30, + 0xc7, 0x9e, 0x79, 0xe3, 0x9c, 0x19, 0x80, + + /* U+F77D "" */ + 0x1e, 0x1, 0xf8, 0x7, 0xe0, 0x3f, 0x80, 0xfe, + 0x1c, 0x0, 0xc0, 0x3, 0x3f, 0xfc, 0xff, 0xf3, + 0xff, 0xcf, 0xff, 0x1f, 0xf8, 0x0, 0x3, 0x81, + 0xce, 0x7, 0x38, 0x1c, + + /* U+F780 "" */ + 0x2, 0x20, 0x2, 0x8, 0x3, 0x76, 0x1, 0xbb, + 0x0, 0xc1, 0x80, 0x71, 0xc0, 0x7f, 0xf0, 0x7e, + 0xfe, 0x66, 0x33, 0x65, 0xf6, 0xe3, 0x76, 0x31, + 0xbb, 0x10, 0x1c, 0x0, 0x1b, 0x0, 0xf8, 0xf8, + 0x0, 0x0, + + /* U+F781 "" */ + 0x3, 0xc0, 0x0, 0xe0, 0x0, 0x67, 0x1c, 0x6e, + 0xe, 0xdc, 0xc, 0xf8, 0xd, 0xf7, 0x1b, 0xef, + 0x1, 0xdf, 0x3, 0x8e, 0x7, 0x1c, 0xe, 0x38, + 0x1f, 0xf0, 0x1f, 0xc0, 0x1f, 0x0, + + /* U+F783 "" */ + 0x18, 0x60, 0x61, 0x87, 0xff, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, + 0x87, 0xfe, 0x1f, 0xf8, 0x7f, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F784 "" */ + 0x18, 0x60, 0x61, 0x87, 0xff, 0xbf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, + 0x80, 0x7e, 0x1, 0xf8, 0x7, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0x80, + + /* U+F786 "" */ + 0x3, 0xc0, 0x7e, 0x7, 0xe0, 0x3e, 0x31, 0xe3, + 0x86, 0x3c, 0x3, 0xe0, 0x0, 0x0, 0x0, 0x3e, + 0x3, 0xe0, 0x0, 0x0, 0x0, 0x7e, 0x3, 0xe0, + 0x1e, 0x0, 0x60, 0x0, + + /* U+F787 "" */ + 0x0, 0x8, 0x0, 0xe, 0x0, 0x7, 0x0, 0x1, + 0xe0, 0x3c, 0x78, 0x3f, 0x98, 0xf, 0xc0, 0x13, + 0xf0, 0x1f, 0xf8, 0xf, 0xfc, 0xf, 0xfe, 0x7, + 0xfe, 0x3, 0x3e, 0x3, 0xcc, 0x1, 0xf0, 0x1, + 0xe0, 0x0, 0xc0, 0x0, 0x0, + + /* U+F788 "" */ + 0x3f, 0x80, 0x60, 0x40, 0x60, 0x40, 0x3f, 0x80, + 0xe, 0x0, 0x7f, 0xfe, 0x7f, 0xfe, 0x6d, 0xb6, + 0xff, 0xff, 0xff, 0xff, 0xf2, 0x4f, 0xff, 0xff, + 0xff, 0xff, 0xc0, 0x3, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F78C "" */ + 0x60, 0x6, 0xf6, 0x6f, 0xfe, 0x7f, 0x7e, 0x7e, + 0x3e, 0x7c, 0x7e, 0x7e, 0x7e, 0x7e, 0x0, 0x0, + 0x0, 0x0, 0x7e, 0x7e, 0x7e, 0x7e, 0x3e, 0x7c, + 0x7e, 0x7e, 0xfe, 0x7f, 0xf6, 0x6f, 0x60, 0x6, + + /* U+F793 "" */ + 0x77, 0x3b, 0xbd, 0xce, 0xff, 0x73, 0xbf, 0x9c, + 0xe7, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xf9, + 0xff, 0xfe, 0x7f, 0xff, 0x9f, 0xff, 0xe3, 0xff, + 0xf0, 0xff, 0xfc, 0x30, 0x3, 0x0, 0x0, 0x0, + + /* U+F794 "" */ + 0x77, 0x33, 0x9e, 0xe7, 0x7b, 0xdc, 0xef, 0x73, + 0x90, 0x20, 0x0, 0x0, 0x0, 0x1a, 0x1f, 0xe7, + 0xe3, 0xf9, 0xfe, 0x7f, 0x7f, 0xef, 0xcf, 0x3d, + 0xf9, 0xc3, 0x9f, 0x38, 0x73, 0x3, 0xc, 0x0, + 0x73, 0x80, 0x3, 0xc0, + + /* U+F796 "" */ + 0xf, 0xe0, 0x1f, 0xf0, 0x3f, 0xfc, 0x3f, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xd9, 0xb3, 0xd9, 0xb3, 0xd9, 0xb3, 0xd9, 0xb3, + + /* U+F79C "" */ + 0xa, 0x0, 0xb, 0xe0, 0x3, 0xf0, 0x3, 0xff, + 0x0, 0xff, 0xe0, 0x3f, 0xe0, 0xf, 0xf7, 0x3b, + 0xfd, 0xfe, 0xff, 0x6e, 0xff, 0x9f, 0xef, 0xef, + 0xff, 0xfb, 0xcf, 0xfe, 0xf3, 0xff, 0xbc, 0xff, + 0xef, 0x3f, 0xfb, 0xcf, 0xfe, 0x73, 0x80, + + /* U+F79F "" */ + 0x6, 0x6, 0x0, 0xff, 0xf0, 0xd, 0xfb, 0x1, + 0xcf, 0x38, 0x1e, 0xf7, 0x83, 0xff, 0xfc, 0x3f, + 0xff, 0xc3, 0xff, 0xfc, 0x3f, 0x9f, 0xc1, 0xf9, + 0xf8, 0x1f, 0xf, 0x81, 0x80, 0x18, 0x58, 0x1, + 0xaf, 0x80, 0x1f, 0x7c, 0x3, 0xe0, 0xc0, 0x30, + + /* U+F7A0 "" */ + 0xff, 0xff, 0xff, 0xfc, 0x0, 0xf0, 0x3, 0xc0, + 0xf, 0x0, 0x3c, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, + 0xc0, + + /* U+F7A2 "" */ + 0x7, 0xe0, 0x1e, 0x38, 0x3e, 0xc, 0x77, 0x6, + 0x77, 0x6, 0xfe, 0x1b, 0xfc, 0xf3, 0xff, 0xf3, + 0xf8, 0x33, 0xf8, 0x3b, 0xf8, 0xf, 0x78, 0x6, + 0x78, 0x6, 0x3c, 0xc, 0x1f, 0x18, 0x7, 0xe0, + + /* U+F7A4 "" */ + 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, + 0xff, 0xff, 0xf0, + + /* U+F7A5 "" */ + 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, 0xf3, 0xcf, 0x3c, + 0xf3, 0xcf, 0x30, + + /* U+F7A6 "" */ + 0x0, 0x4, 0x0, 0xe, 0x0, 0xf, 0x0, 0x1e, + 0x0, 0x38, 0x7, 0x70, 0xf, 0xe0, 0xf, 0xc0, + 0x78, 0xe0, 0xf8, 0xe0, 0xf8, 0xe0, 0xff, 0xc0, + 0xff, 0x0, 0x7f, 0x0, 0x3f, 0x0, 0x1e, 0x0, + + /* U+F7A9 "" */ + 0x3c, 0x3c, 0x7c, 0x7e, 0xfe, 0x3f, 0xfe, 0x3f, + 0xfc, 0xff, 0xf9, 0xff, 0xfc, 0xfe, 0x7e, 0xfe, + 0x3f, 0x7c, 0x3f, 0xfc, 0x1f, 0xf8, 0xf, 0xf0, + 0x7, 0xe0, 0x1, 0x80, + + /* U+F7AA "" */ + 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0x31, 0x80, + 0xf7, 0x0, 0xc6, 0x0, 0x0, 0xd, 0xa4, 0x1f, + 0x78, 0x3e, 0xf0, 0x7d, 0xe3, 0xfb, 0xf7, 0xc3, + 0xef, 0x3, 0xde, 0x7, 0xa4, 0x9, + + /* U+F7AB "" */ + 0x0, 0x0, 0x0, 0xf0, 0x7, 0xe0, 0x1f, 0xf0, + 0x3f, 0xf8, 0x7f, 0xdc, 0x7f, 0xdc, 0xff, 0xfe, + 0xff, 0xfe, 0xfb, 0xfe, 0xf9, 0xff, 0xfc, 0x3e, + 0xff, 0x9c, 0xff, 0x80, 0xff, 0xc0, 0xff, 0xc0, + + /* U+F7AD "" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, + 0x7f, 0xfe, 0x7f, 0xde, 0x36, 0xde, 0x36, 0xde, + 0x36, 0xde, 0x36, 0xde, 0x6, 0x1c, 0x6, 0xc, + 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, 0x0, 0xc, + + /* U+F7AE "" */ + 0x3, 0xc0, 0x3, 0xf3, 0x1, 0xfc, 0xe0, 0xff, + 0x3c, 0x0, 0x0, 0x0, 0x0, 0xe, 0xff, 0xdf, + 0xbf, 0xf7, 0xef, 0x3d, 0xc1, 0x86, 0x0, 0x61, + 0x83, 0xf8, 0x7f, 0xfe, 0x1f, 0xff, 0xff, 0xf0, + + /* U+F7B5 "" */ + 0x3c, 0x1, 0xfc, 0xf, 0xf0, 0x3f, 0xe0, 0xff, + 0x83, 0xfe, 0xf, 0xfc, 0x1f, 0xff, 0x7f, 0xfd, + 0xff, 0xf3, 0xff, 0x8f, 0xfc, 0x0, 0x0, 0x0, + 0x7, 0xff, 0x1f, 0xfc, + + /* U+F7B6 "" */ + 0x0, 0x0, 0x36, 0x0, 0x33, 0x0, 0x19, 0x80, + 0x9, 0x80, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfc, + 0xff, 0xfe, 0xff, 0xf7, 0xff, 0xf3, 0xff, 0xf3, + 0xff, 0xf7, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xf0, + 0x7f, 0xe0, + + /* U+F7B9 "" */ + 0x0, 0x0, 0x1c, 0x6, 0xf, 0x7, 0x8f, 0x83, + 0xe7, 0xe3, 0xf7, 0xe0, 0xff, 0xf7, 0x7e, 0xfb, + 0xbe, 0x1, 0xc0, 0x0, 0x0, 0x0, 0xf8, 0x0, + 0x7c, 0x0, 0x7f, 0x0, 0x7f, 0xc0, 0xf, 0xc0, + + /* U+F7BA "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x73, 0xce, + 0x63, 0xc6, 0xe3, 0xc7, 0xc6, 0x63, 0xc6, 0x63, + 0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0x7c, 0x3e, + 0x78, 0x1e, 0x3c, 0x3c, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F7BD "" */ + 0x18, 0x61, 0x81, 0xc6, 0x1c, 0x18, 0x61, 0x80, + 0x6, 0x0, 0x1c, 0x61, 0xc3, 0xe6, 0x3e, 0x7e, + 0x67, 0xe7, 0xe6, 0x7f, 0x7f, 0x67, 0xff, 0xf6, + 0xff, 0x3c, 0x67, 0xe3, 0xc6, 0x7f, 0x3c, 0x63, + 0xe3, 0xc6, 0x3e, 0x3c, 0x63, 0xe3, 0x46, 0x34, + + /* U+F7BF "" */ + 0x3, 0x0, 0x7, 0x88, 0xd, 0xdc, 0x18, 0xfe, + 0x1c, 0x7c, 0xe, 0xf8, 0x7, 0xfc, 0x7b, 0xee, + 0xff, 0xc7, 0x7f, 0xe3, 0x3f, 0x76, 0x1f, 0xbc, + 0x3f, 0x98, 0x77, 0x80, 0x63, 0x80, 0x1, 0x0, + + /* U+F7C0 "" */ + 0x3, 0xc0, 0x0, 0x70, 0x0, 0x18, 0x3, 0x8c, + 0x60, 0x66, 0xe0, 0x36, 0xf0, 0x1b, 0xf9, 0x9b, + 0xff, 0x1b, 0xff, 0x0, 0xff, 0x80, 0x7f, 0xc0, + 0x7f, 0xc0, 0x3f, 0xe0, 0x1f, 0xf0, 0x7, 0xc0, + + /* U+F7C2 "" */ + 0x1f, 0xe3, 0xff, 0x74, 0xbf, 0x4b, 0xf4, 0xbf, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, + + /* U+F7C4 "" */ + 0x7f, 0x8f, 0xfc, 0xff, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xc3, 0x3c, 0x33, 0xff, + 0xfc, 0xc3, 0xcc, 0x3c, 0xc3, 0xff, 0xf7, 0xfe, + + /* U+F7C5 "" */ + 0x0, 0xc, 0x0, 0x1c, 0x0, 0x38, 0x7f, 0x0, + 0xfe, 0x0, 0x1c, 0x0, 0x70, 0x1, 0xc0, 0x3, + 0xc0, 0x13, 0xe0, 0x30, 0xc0, 0xc1, 0x89, 0x3, + 0x8, 0x6, 0xe, 0x1, 0x0, 0x3c, + + /* U+F7C9 "" */ + 0x0, 0x3, 0xc, 0x3, 0xc7, 0x1c, 0xc2, 0x7f, + 0x0, 0xf, 0x80, 0x10, 0xf0, 0x6, 0x3c, 0x1, + 0x80, 0x0, 0xe0, 0x60, 0x30, 0x38, 0x18, 0x7, + 0x18, 0x0, 0xfc, 0x0, 0x1c, 0x0, 0x3, 0x80, + 0x0, 0x70, 0x0, 0xf, 0x0, + + /* U+F7CA "" */ + 0x0, 0x6, 0x0, 0x1, 0xe0, 0x7, 0x18, 0x1, + 0xf8, 0x0, 0x37, 0xc0, 0x5, 0xfb, 0x1, 0x3f, + 0xe0, 0x27, 0x3c, 0x8, 0xe0, 0x82, 0x1e, 0x10, + 0x44, 0xe2, 0x11, 0x9c, 0x46, 0x73, 0x8, 0x1c, + 0x60, 0x3f, 0xff, 0xf0, + + /* U+F7CC "" */ + 0xf8, 0x0, 0x1f, 0xc0, 0x1, 0xf8, 0x7, 0x3f, + 0x80, 0xe7, 0xf0, 0x18, 0xff, 0x87, 0x1f, 0xff, + 0xe3, 0xff, 0xfc, 0x7f, 0xff, 0x87, 0xff, 0xe0, + 0x60, 0x30, 0x8c, 0x6, 0x3f, 0xff, 0xfc, + + /* U+F7CD "" */ + 0xf, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7f, 0xfe, 0xe5, 0x47, 0xfd, 0x5f, 0xe4, 0x47, + 0xfc, 0x77, 0xe5, 0x47, 0x7f, 0xfe, 0x7f, 0xfe, + 0x7f, 0xfc, 0x7f, 0xf8, 0xf7, 0xe0, 0xc0, 0x0, + + /* U+F7CE "" */ + 0x6, 0xe, 0x7, 0x1e, 0x3, 0xce, 0x0, 0xe0, + 0x1, 0xf8, 0x3, 0xfc, 0x7, 0xce, 0x7, 0x86, + 0x7, 0xc0, 0x6, 0xe0, 0xc6, 0x60, 0x76, 0x60, + 0x3f, 0xe0, 0x3, 0xff, 0x0, 0x1f, + + /* U+F7D0 "" */ + 0x0, 0xf0, 0x0, 0x1f, 0x80, 0x3, 0xfc, 0x0, + 0x36, 0xc0, 0x3, 0xfc, 0x0, 0x39, 0xc0, 0x1, + 0x98, 0x3, 0x1f, 0x8c, 0xf3, 0xfc, 0xf7, 0xff, + 0xfe, 0x1f, 0x9f, 0x80, 0x79, 0xe0, 0x7, 0xfe, + 0x0, 0x79, 0xe0, 0x7, 0x9e, 0x0, 0x7f, 0xe0, + 0x3, 0xfc, 0x0, 0x1f, 0x80, + + /* U+F7D2 "" */ + 0xf, 0xc0, 0x3, 0xf8, 0x0, 0x61, 0x80, 0xc, + 0x30, 0x1, 0x83, 0xe, 0x78, 0x63, 0x1f, 0x86, + 0x63, 0xff, 0xcc, 0x7f, 0xf9, 0x8f, 0xff, 0xf1, + 0xff, 0xfe, 0x60, 0x6, 0xcd, 0xb6, 0xd9, 0x80, + 0x1b, 0x1f, 0xfe, 0x71, 0xff, 0x87, + + /* U+F7D7 "" */ + 0xff, 0xff, 0xff, 0x0, 0xf, 0xff, 0xff, 0xf0, + 0x60, 0x6, 0x0, 0x60, 0x6, 0x0, 0x60, 0x6, + 0x0, 0x60, 0x6, 0x0, 0x60, + + /* U+F7D8 "" */ + 0xff, 0xfd, 0xff, 0xe6, 0x7f, 0x9f, 0xfe, 0x7f, + 0xf9, 0xff, 0xe7, 0xff, 0xf8, 0x7, 0xe0, 0x1f, + 0xff, 0xf7, 0xff, 0x9f, 0xfe, 0x3f, 0xf0, 0xff, + 0xc3, 0xff, 0xf, 0xfc, + + /* U+F7D9 "" */ + 0x60, 0x78, 0x7c, 0x7c, 0x1f, 0x3c, 0xf, 0x9c, + 0x23, 0xce, 0x30, 0xf1, 0xf8, 0xc, 0x1c, 0x3, + 0xe6, 0x4, 0xf8, 0x6, 0x7e, 0x7, 0x3f, 0x8f, + 0xdf, 0xe7, 0xe7, 0xff, 0xe1, 0xff, 0xe0, 0x7c, + 0xe0, 0x8, + + /* U+F7DA "" */ + 0x0, 0xc0, 0x6, 0xc0, 0x6, 0x1f, 0x0, 0xf8, + 0xf, 0xc0, 0x7d, 0x80, 0xc1, 0x80, 0x1, 0x80, + 0x3f, 0xfc, 0x7f, 0xfe, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, + 0x3f, 0xfc, + + /* U+F7E4 "" */ + 0x4, 0x0, 0xe0, 0xe, 0x0, 0xf0, 0xf, 0x80, + 0x7c, 0x67, 0xee, 0x3e, 0xe1, 0xfe, 0x1f, 0xf3, + 0xff, 0xff, 0x7f, 0xf7, 0xfe, 0x3f, 0xc0, 0xf8, + + /* U+F7E5 "" */ + 0x0, 0xc, 0x0, 0x7, 0x80, 0x7, 0xc0, 0x3, + 0xc6, 0x1, 0xe3, 0xc0, 0x73, 0xe0, 0x39, 0xf0, + 0xc, 0xf8, 0x7, 0x3c, 0x3, 0x9e, 0x1, 0xe7, + 0x0, 0xf3, 0xc0, 0x79, 0xe0, 0x3c, 0xf8, 0x6, + 0x7c, 0x0, 0x3e, 0x0, 0x1e, 0x0, 0x3, 0x0, + 0x0, + + /* U+F7E6 "" */ + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, + 0xff, 0xc0, 0xff, 0x3, 0xff, 0x3f, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x1b, 0x0, + 0x6f, 0xff, 0xdf, 0xff, + + /* U+F7EC "" */ + 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xfc, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0xfe, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, + 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, + + /* U+F7EF "" */ + 0x0, 0xf0, 0x1, 0xfc, 0x7, 0xfe, 0xf, 0xfe, + 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, + + /* U+F7F2 "" */ + 0x0, 0x80, 0x1, 0xe0, 0x1, 0xfb, 0x81, 0xff, + 0xc1, 0xff, 0xe1, 0xff, 0xf1, 0xff, 0xfd, 0xfe, + 0xff, 0x3f, 0x7e, 0x1e, 0xf, 0xf, 0x7, 0x87, + 0xef, 0xc3, 0xf7, 0xe1, 0xff, 0xf0, 0xff, 0xf8, + 0x3f, 0xf8, + + /* U+F7F3 "" */ + 0x1f, 0x87, 0xfe, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x9f, 0xf9, 0xff, 0x9f, 0xf9, + 0xff, 0xff, 0xf0, 0xfe, 0x7, 0xff, 0xf7, 0xfe, + + /* U+F7F5 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, + 0x7e, 0x7e, 0xfe, 0x7f, 0xf8, 0x1f, 0xf8, 0x1f, + 0xf8, 0x1f, 0xfe, 0x7f, 0x7e, 0x7e, 0x7f, 0xfe, + 0x3f, 0xfc, 0x7f, 0xf8, 0xff, 0xe0, 0xc0, 0x0, + + /* U+F7F7 "" */ + 0x0, 0x20, 0x0, 0x38, 0x0, 0xe, 0x0, 0xf, + 0x80, 0xc, 0xe0, 0xc, 0x38, 0xe, 0x1e, 0xf, + 0x9a, 0xc, 0xf8, 0x6, 0x38, 0x3, 0x18, 0x1, + 0xf8, 0x1, 0xf8, 0x1, 0xc0, 0x1, 0xc0, 0x1, + 0xc0, 0x0, 0x40, 0x0, 0x0, + + /* U+F7FA "" */ + 0x0, 0xc0, 0x1, 0xe0, 0x3, 0xe0, 0x7f, 0xf0, + 0xff, 0xf0, 0xff, 0x3c, 0x73, 0x3f, 0x73, 0xff, + 0x3f, 0xff, 0x3f, 0x3e, 0x7f, 0x38, 0xff, 0xf0, + 0xff, 0xf0, 0x41, 0xf0, 0x0, 0xf0, 0x0, 0x70, + + /* U+F7FB "" */ + 0xf, 0x1, 0xf8, 0x3f, 0xc7, 0x7e, 0x6f, 0xee, + 0xff, 0xdf, 0xfd, 0xff, 0xdf, 0xff, 0xff, 0xff, + 0xf7, 0xfe, 0x7f, 0xe3, 0xfc, 0xf, 0x0, + + /* U+F802 "" */ + 0xc0, 0x78, 0x30, 0x1f, 0xfc, 0x7, 0xff, 0xfd, + 0xff, 0xff, 0x7f, 0xf0, 0x1f, 0xfc, 0x7, 0xff, + 0x0, 0x0, 0xc0, 0x0, 0x30, 0x1e, 0xc, 0x7, + 0xff, 0x1, 0xff, 0xff, 0x7f, 0xdf, 0xdf, 0xf0, + 0x7, 0xfc, 0x1, 0xff, + + /* U+F805 "" */ + 0x7, 0xe0, 0x1e, 0x78, 0x36, 0x6c, 0x77, 0xec, + 0x7f, 0xfe, 0x7f, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x7f, 0xfe, + 0x7f, 0xfe, 0x3f, 0xfc, + + /* U+F806 "" */ + 0x2, 0x0, 0x38, 0x1, 0xc0, 0xe, 0x0, 0x70, + 0x3, 0x80, 0x1c, 0x3, 0xf8, 0x3f, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xc3, 0xfc, + + /* U+F807 "" */ + 0x1, 0xe0, 0x1, 0x7a, 0x0, 0xde, 0xc0, 0x77, + 0xb8, 0x3d, 0xef, 0x1f, 0x7b, 0xe7, 0xde, 0xf9, + 0xf7, 0xbe, 0x7f, 0xff, 0x9f, 0xff, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf0, + + /* U+F80A "" */ + 0x0, 0x80, 0x0, 0xe0, 0x1, 0xfc, 0x1, 0xff, + 0x1, 0xff, 0xc1, 0xff, 0xf1, 0xff, 0xfd, 0xff, + 0xff, 0x7f, 0xff, 0x1f, 0xff, 0xf, 0x8f, 0x87, + 0xc7, 0xc3, 0xe3, 0xe1, 0xf1, 0xf0, 0xf8, 0xf8, + 0x3f, 0xf8, + + /* U+F80B "" */ + 0x1, 0x80, 0x1, 0xe0, 0x1, 0xfb, 0x81, 0xff, + 0xc1, 0xff, 0xe1, 0xff, 0xf1, 0xff, 0xfd, 0xff, + 0xfe, 0x7f, 0xff, 0x1f, 0xff, 0xf, 0x8f, 0x87, + 0xc7, 0xc3, 0xe3, 0xe1, 0xf1, 0xf0, 0xf8, 0xf8, + 0x3f, 0xf8, + + /* U+F80C "" */ + 0x0, 0x80, 0x0, 0xe0, 0x1, 0xfc, 0x1, 0xff, + 0x1, 0xff, 0xc1, 0xff, 0xf1, 0xff, 0xfd, 0xff, + 0xff, 0x7f, 0xff, 0x1f, 0xff, 0xf, 0x8f, 0x87, + 0xc7, 0xc3, 0xe3, 0xe1, 0xf1, 0xf0, 0xf8, 0xf8, + 0x3f, 0xf8, + + /* U+F80D "" */ + 0x7f, 0xe0, 0x3f, 0xfc, 0xf, 0xff, 0x3, 0xff, + 0xc0, 0xff, 0xf0, 0x3c, 0x3c, 0xf, 0xfe, 0x3, + 0xff, 0x38, 0xff, 0xdf, 0x3f, 0xf7, 0xcf, 0xfd, + 0xf3, 0xe7, 0x38, 0xf9, 0x80, 0x3e, 0x4f, 0xef, + 0xf7, 0xfd, 0xfd, 0xff, 0x0, 0x7f, 0xc0, + + /* U+F80F "" */ + 0x0, 0xc0, 0x3, 0x9c, 0x7, 0x3e, 0xe, 0x7e, + 0x1c, 0xfe, 0x39, 0xfc, 0x73, 0xf9, 0x67, 0xf3, + 0xcf, 0xe6, 0x9f, 0xce, 0x3f, 0x9c, 0x7f, 0x38, + 0x7e, 0x70, 0x7c, 0xe0, 0x39, 0xc0, 0x3, 0x0, + + /* U+F810 "" */ + 0xf, 0x1, 0xf8, 0x3f, 0xc3, 0xfc, 0x7f, 0xcf, + 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x3f, + 0xc1, 0xf8, 0x1f, 0x80, 0xf0, 0xf, 0x0, 0x60, + 0x6, 0x0, + + /* U+F812 "" */ + 0x1f, 0xff, 0x83, 0xff, 0xfc, 0x30, 0x0, 0xc3, + 0x0, 0xc, 0x30, 0x60, 0xc3, 0x6, 0xc, 0x31, + 0xf8, 0xc3, 0x6, 0xc, 0x30, 0x60, 0xc3, 0x0, + 0xc, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xfe, + + /* U+F815 "" */ + 0x7f, 0xfe, 0xff, 0xff, 0xc0, 0x3, 0xc0, 0x3, + 0xc0, 0x3, 0xc0, 0x3, 0xff, 0xff, 0xff, 0xff, + 0xc4, 0x7f, 0xc4, 0x7f, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F816 "" */ + 0x0, 0x3d, 0x80, 0x3f, 0xc0, 0x7, 0xc0, 0x1b, + 0xf0, 0xd, 0xf8, 0xe, 0xfc, 0xf, 0x6, 0xf, + 0xfa, 0x7, 0xfc, 0x7, 0xf8, 0x7, 0xf8, 0xf, + 0xf8, 0xf, 0xf0, 0x3, 0xe0, 0x0, + + /* U+F818 "" */ + 0xf, 0x0, 0x3f, 0x80, 0xf, 0x80, 0x7, 0x81, + 0xc7, 0x87, 0xe7, 0x8f, 0xe7, 0x19, 0xe6, 0x33, + 0xee, 0xff, 0xdd, 0xf9, 0xdb, 0xf3, 0xb6, 0xff, + 0x5f, 0xfe, 0x3f, 0xc0, 0x78, 0x0, 0x0, 0x0, + + /* U+F81D "" */ + 0xf, 0xe0, 0xf, 0xc0, 0x1f, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xfc, 0x7, 0xfc, 0x1f, 0x3c, 0x7c, + 0x7c, 0xfb, 0xfb, 0xf0, 0xff, 0xfd, 0xff, 0xc3, + 0xff, 0xcf, 0xff, 0xff, 0xbf, 0xfe, + + /* U+F827 "" */ + 0xff, 0xfb, 0xff, 0xff, 0xcf, 0xff, 0x3f, 0xf0, + 0x3f, 0xc0, 0xff, 0x3, 0xfc, 0xf, 0xfc, 0xff, + 0xf3, 0xff, 0xff, 0xff, 0xff, 0x60, 0xd, 0x80, + 0x3f, 0xff, 0xff, 0xfe, + + /* U+F828 "" */ + 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xe3, 0xff, + 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xff, + 0xff, 0xff, 0x80, 0xfe, 0x3, 0xff, 0xff, 0xff, + 0xf0, + + /* U+F829 "" */ + 0x7, 0x80, 0x3f, 0xf, 0xff, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x9f, 0xfe, 0x7c, 0xf9, + 0xe1, 0xe7, 0x3, 0x9f, 0x3e, 0x7c, 0xf9, 0xf3, + 0xe7, 0xff, 0x9f, 0xfe, 0x3f, 0xf0, + + /* U+F82A "" */ + 0x7, 0x80, 0x3f, 0xf, 0xff, 0xff, 0xff, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x9f, 0xfe, 0x7c, 0xf9, + 0xe1, 0xe7, 0x3, 0x9f, 0x3e, 0x7c, 0xf9, 0xf3, + 0xe7, 0xff, 0x9f, 0xfe, 0x3f, 0xf0, + + /* U+F82F "" */ + 0x7, 0x0, 0xee, 0xf, 0x78, 0x7f, 0xc3, 0x6, + 0x8, 0x20, 0x63, 0x1, 0xf0, 0x2, 0x0, 0x0, + 0x4, 0x10, 0xfb, 0xe7, 0xff, 0x7f, 0xff, 0xff, + 0xff, 0xff, + + /* U+F83E "" */ + 0x3f, 0x80, 0x3f, 0x80, 0x31, 0x80, 0x31, 0x80, + 0x31, 0x80, 0xf1, 0x8f, 0xf1, 0x8f, 0x1, 0x8c, + 0x1, 0x8c, 0x1, 0x8c, 0x1, 0xfc, 0x1, 0xfc, + + /* U+F84A "" */ + 0x0, 0x38, 0x0, 0xe, 0x0, 0x3, 0x80, 0x1, + 0x0, 0x1, 0xf0, 0x0, 0xff, 0x80, 0x79, 0xe0, + 0x1e, 0x0, 0x3, 0xc0, 0xe, 0x31, 0xc7, 0xcc, + 0xfb, 0xfb, 0x7f, 0xfe, 0xdf, 0xff, 0xb7, 0xf7, + 0xc0, 0xf8, 0xe0, 0x1c, + + /* U+F84C "" */ + 0x7f, 0xfb, 0xff, 0xfc, 0x30, 0xf0, 0xc3, 0xc3, + 0xf, 0xc, 0x3f, 0xff, 0xff, 0xff, 0xc3, 0xf, + 0xc, 0x3c, 0x30, 0xf0, 0xc3, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F850 "" */ + 0xcc, 0xcf, 0x33, 0x30, 0x0, 0x0, 0x0, 0xc0, + 0xf, 0x0, 0x30, 0x0, 0x0, 0x0, 0xc0, 0xf, + 0x0, 0x30, 0x0, 0x0, 0x0, 0xcc, 0xcf, 0x33, + 0x30, + + /* U+F853 "" */ + 0x7f, 0xff, 0xff, 0xfc, 0x0, 0x30, 0x0, 0xc0, + 0xf, 0x0, 0x3c, 0x0, 0x30, 0x0, 0xc0, 0xf, + 0x0, 0x3c, 0x0, 0x30, 0x0, 0xcc, 0xcf, 0x33, + 0x30, + + /* U+F85E "" */ + 0x1, 0xc0, 0x0, 0xf0, 0x0, 0x1c, 0x0, 0x10, + 0x0, 0x1f, 0x0, 0x1f, 0xc0, 0xf, 0xf8, 0x0, + 0xfe, 0x0, 0xf, 0x80, 0x0, 0xf1, 0x87, 0x8f, + 0x61, 0xf8, 0xfc, 0x6e, 0x1f, 0xb9, 0x87, 0xec, + 0x63, 0xff, 0x18, 0xff, + + /* U+F863 "" */ + 0x1, 0xc0, 0x3, 0xc0, 0x7, 0xc0, 0x7, 0xc0, + 0x7, 0xc0, 0x7, 0xfc, 0xff, 0xfe, 0xfe, 0x7f, + 0xfe, 0x7f, 0x7f, 0xff, 0x3f, 0xe0, 0x3, 0xe0, + 0x3, 0xe0, 0x3, 0xe0, 0x3, 0xc0, 0x3, 0x80, + + /* U+F86D "" */ + 0x0, 0x0, 0xff, 0x7, 0xff, 0x3f, 0xff, 0x7b, + 0xff, 0x63, 0x7e, 0x6f, 0x3c, 0x7f, 0x19, 0xee, + 0x1, 0xc0, 0x1c, 0x4, 0x7f, 0xc, 0xff, 0x9c, + 0xe3, 0xbe, 0xe3, 0x8e, 0xe3, 0x9c, 0xff, 0x98, + 0xff, 0x90, + + /* U+F879 "" */ + 0x0, 0x1c, 0x0, 0x1e, 0x0, 0x3f, 0x0, 0x3f, + 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x1f, 0x0, 0x1e, + 0x0, 0x3e, 0x0, 0x7c, 0x3c, 0xf8, 0xfd, 0xf8, + 0xff, 0xf0, 0xff, 0xc0, 0x7f, 0x80, 0x3c, 0x0, + + /* U+F87B "" */ + 0x7f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, + 0x1f, 0xfc, 0x7f, 0xf9, 0xff, 0xcf, 0xe2, 0x7f, + 0x83, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xfd, 0xff, + 0xe0, + + /* U+F87C "" */ + 0x1, 0xff, 0xe0, 0x3f, 0xff, 0x3, 0x3f, 0xf0, + 0x33, 0xdf, 0x7b, 0xf8, 0xfc, 0xbc, 0x7, 0xcb, + 0x80, 0x7f, 0xb8, 0x3, 0xcb, 0xff, 0xfc, 0xbf, + 0xff, 0xf8, 0xff, 0xcc, 0xc0, 0x0, 0xce, 0x0, + 0xc, 0xff, 0xc0, 0x7f, 0xfc, 0x0, + + /* U+F87D "" */ + 0xc0, 0x0, 0x38, 0x0, 0x7, 0xff, 0xf0, 0xff, + 0xfe, 0x1c, 0x61, 0x83, 0x98, 0x40, 0x76, 0x0, + 0xf, 0x80, 0x1, 0xc0, 0x0, 0x38, 0x0, 0x7, + 0x0, 0x4, 0xe0, 0x1, 0x9c, 0x0, 0x63, 0x80, + 0xfe, 0x70, 0x3f, 0x8e, 0x0, 0x1, 0xc0, 0x0, + 0x30, + + /* U+F881 "" */ + 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x1c, 0x18, 0x38, + 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x0, 0x18, 0x18, + 0x18, 0x18, 0x5a, 0x3c, 0x7f, 0x3c, 0x7e, 0x7e, + 0x3c, 0x7e, 0x18, 0x42, + + /* U+F882 "" */ + 0x18, 0x7e, 0x3c, 0x7e, 0x7e, 0x1c, 0x7f, 0x38, + 0x5a, 0x7e, 0x18, 0x7e, 0x18, 0x0, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x7e, + 0x18, 0x7e, 0x18, 0x42, + + /* U+F884 "" */ + 0x18, 0x70, 0x6, 0x1c, 0x1, 0x80, 0x0, 0x60, + 0x0, 0x18, 0x7c, 0x6, 0x1f, 0x1, 0x80, 0x0, + 0x60, 0x0, 0x18, 0x7f, 0x36, 0xdf, 0xcf, 0xf0, + 0x1, 0xf8, 0x0, 0x3c, 0x7f, 0xc6, 0x1f, 0xf0, + + /* U+F885 "" */ + 0x18, 0x70, 0xf, 0x1c, 0x7, 0xe0, 0x3, 0xfc, + 0x0, 0xdb, 0x7c, 0x6, 0x1f, 0x1, 0x80, 0x0, + 0x60, 0x0, 0x18, 0x7f, 0x6, 0x1f, 0xc1, 0x80, + 0x0, 0x60, 0x0, 0x18, 0x7f, 0xc6, 0x1f, 0xf0, + + /* U+F886 "" */ + 0x18, 0x1c, 0x30, 0x7c, 0x60, 0xd8, 0xc1, 0xf1, + 0x81, 0xc3, 0x3, 0x86, 0x6, 0xc, 0x0, 0x18, + 0x18, 0xb4, 0x79, 0xfc, 0x73, 0xf0, 0xe3, 0xc3, + 0xe3, 0x7, 0xc0, + + /* U+F887 "" */ + 0x18, 0x1c, 0x78, 0x7d, 0xf8, 0xdf, 0xf9, 0xfd, + 0xb1, 0xc3, 0x3, 0x86, 0x6, 0xc, 0x0, 0x18, + 0x18, 0x30, 0x78, 0x60, 0x70, 0xc0, 0xe1, 0x83, + 0xe3, 0x7, 0xc0, + + /* U+F891 "" */ + 0x79, 0xf0, 0x7e, 0xfc, 0x33, 0x66, 0x19, 0xbf, + 0xf, 0xdf, 0x87, 0xef, 0xc3, 0x36, 0x61, 0x9b, + 0xf0, 0xcd, 0xf1, 0x80, 0x1, 0xc0, 0x1, 0xc0, + 0xd, 0xc0, 0x7, 0xc0, 0x1, 0xc0, 0x0, 0x60, + + /* U+F897 "" */ + 0x3e, 0x7, 0xc7, 0xf0, 0xfe, 0xe3, 0x9c, 0x7c, + 0x19, 0x83, 0xc1, 0x98, 0x3c, 0x19, 0x83, 0xe3, + 0x9c, 0x77, 0xff, 0xfe, 0x3f, 0xff, 0xc0, + + /* U+F8C0 "" */ + 0x3, 0x9c, 0x0, 0x3f, 0xc0, 0x7, 0xfe, 0x0, + 0x7f, 0xe0, 0x7, 0xfe, 0x0, 0x7f, 0xe0, 0xcf, + 0xff, 0x3c, 0xff, 0xf3, 0xcf, 0xff, 0x36, 0x0, + 0x6, 0x70, 0x0, 0xe3, 0xff, 0xfc, 0xf, 0xff, + 0x0, + + /* U+F8C1 "" */ + 0x3, 0x9c, 0x0, 0x3f, 0xc0, 0x7, 0xfe, 0x0, + 0x7f, 0xe0, 0x0, 0xfe, 0x0, 0x3, 0xe0, 0x1f, + 0x1f, 0xc3, 0xf8, 0x7e, 0x7f, 0xe3, 0xff, 0xff, + 0xf, 0xff, 0xfc, 0x7f, 0xff, 0xe1, 0xff, 0xff, + 0x80, + + /* U+F8CC "" */ + 0x19, 0x87, 0x9e, 0x79, 0xef, 0x9f, 0xf9, 0xff, + 0x9f, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x7f, 0xe1, 0xf8, + + /* U+F8D7 "" */ + 0x0, 0x7, 0x0, 0x3e, 0x1, 0xf0, 0x1f, 0x80, + 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, + 0xc1, 0x83, 0xc1, 0x83, 0xff, 0x83, 0xc1, 0x83, + 0xc1, 0xc7, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + + /* U+F8D9 "" */ + 0x7, 0xe0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7c, 0x3e, + 0x78, 0x1e, 0xfb, 0xdf, 0xf7, 0xef, 0xf6, 0x6f, + 0xf6, 0x6f, 0xf7, 0xef, 0xfb, 0xdf, 0x78, 0x1e, + 0x7c, 0x3e, 0x3f, 0xfc, 0x1f, 0xf8, 0x7, 0xe0, + + /* U+F8E5 "" */ + 0x7f, 0xff, 0xbf, 0xff, 0xfc, 0x0, 0xf, 0x0, + 0x3, 0xc0, 0x0, 0xf0, 0x0, 0x3c, 0x0, 0xf, + 0x0, 0x3, 0xc0, 0x0, 0xf0, 0x0, 0x3f, 0xff, + 0xfd, 0xff, 0xfe, 0x0, 0x0, 0x3, 0xff, 0x0, + 0xff, 0xc0, + + /* U+F8EF "" */ + 0x20, 0x3, 0x0, 0x36, 0xcf, 0xff, 0xff, 0xfe, + 0x7, 0xe0, 0x7f, 0xff, 0xe0, 0x7e, 0x7, 0xff, + 0xf7, 0xfe, 0x7f, 0xe7, 0xfe, 0x7f, 0xe7, 0xfe, + 0x3f, 0xc0, + + /* U+F8FF "" */ + 0x7f, 0xfc, 0x1f, 0xff, 0xc3, 0xff, 0xfc, 0x70, + 0xc3, 0x8e, 0x18, 0x71, 0xc3, 0xe, 0x3c, 0xe7, + 0xc7, 0xfc, 0x38, 0xff, 0x87, 0x1f, 0xf0, 0xe3, + 0xff, 0xff, 0xbc, 0xff, 0xf1, 0x98, 0x0, 0x12, + 0x0, 0x3, 0xc0, 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 = 128, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1, .adv_w = 64, .box_w = 2, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 5, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 6, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38, .adv_w = 160, .box_w = 9, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 56, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 81, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 82, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 83, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 84, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 85, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 113, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 138, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 139, .adv_w = 160, .box_w = 10, .box_h = 2, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 142, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 143, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 144, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 162, .adv_w = 128, .box_w = 8, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 176, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 194, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 212, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 233, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 251, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 271, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 289, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 307, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 327, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 328, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 329, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 356, .adv_w = 224, .box_w = 14, .box_h = 8, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 370, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 397, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 417, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 449, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 470, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 488, .adv_w = 192, .box_w = 13, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 513, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 534, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 552, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 570, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 595, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 616, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 634, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 652, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 670, .adv_w = 160, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 686, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 711, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 732, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 757, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 775, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 802, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 820, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 838, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 859, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 880, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 901, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 933, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 954, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 975, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 996, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 997, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 998, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 999, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1000, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1001, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1002, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1023, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1041, .adv_w = 192, .box_w = 13, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 1066, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1087, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1105, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1123, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1148, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1169, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1187, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1205, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1223, .adv_w = 160, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 1239, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1264, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1285, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1310, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1328, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1355, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1373, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1391, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1412, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1433, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1454, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1486, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1507, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1528, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1549, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1550, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1551, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1552, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1553, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1554, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1555, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1556, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1557, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1558, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1559, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1560, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1561, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1562, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1563, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1564, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1565, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1566, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1567, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1568, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1569, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1570, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1571, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1572, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1573, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1574, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1575, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1576, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1577, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1578, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1579, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1580, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1581, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1582, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1583, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1584, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1585, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1586, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1587, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1588, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1589, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 1607, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1608, .adv_w = 192, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1631, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1632, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1633, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1634, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1666, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1667, .adv_w = 224, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1687, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1688, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1689, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1721, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1722, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1723, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1724, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1725, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1726, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1727, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1728, .adv_w = 224, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1758, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1759, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1760, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1761, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1762, .adv_w = 224, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1782, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1783, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1784, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1785, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1786, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1787, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1788, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1789, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1790, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1791, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1792, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1793, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1794, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1795, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1796, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1797, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1798, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1799, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1800, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1801, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1802, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1803, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1804, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1805, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1806, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1807, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1808, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1809, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1827, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1828, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1829, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1830, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1831, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1832, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1833, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1834, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1835, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1836, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1837, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1838, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1839, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1840, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1841, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1842, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1843, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1844, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1845, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1846, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1847, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1848, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1849, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1850, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1851, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1852, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1853, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1854, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1855, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1856, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1857, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1858, .adv_w = 224, .box_w = 14, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1881, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1882, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1883, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1884, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1885, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1886, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1887, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1888, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1889, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1890, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1891, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1892, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1893, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1894, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1895, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1896, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1897, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1898, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1899, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1900, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1901, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1902, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1903, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1904, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1905, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1906, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1907, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1908, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1909, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1910, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1911, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1912, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1913, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1914, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1915, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1916, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1917, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1918, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1919, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1920, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1921, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1922, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1923, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1924, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1925, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1926, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1927, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1928, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1929, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1930, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1931, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1932, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1933, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1934, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1935, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1936, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1937, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1938, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1939, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1940, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1941, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1942, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1943, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1944, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1945, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1946, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1947, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1948, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1949, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1950, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1951, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1952, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1953, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1954, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1955, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1956, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1957, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1958, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1959, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1960, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1961, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1962, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1963, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1964, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1965, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1966, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1967, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1968, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1969, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1970, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1971, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1972, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1973, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1974, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1975, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1976, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1977, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1978, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1979, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1980, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1981, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1982, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1983, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1984, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1985, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1986, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1987, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1988, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1989, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1990, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1991, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1992, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1993, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1994, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1995, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1996, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1997, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1998, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1999, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2000, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2001, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2002, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2003, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2004, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2005, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2006, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2007, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2008, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2009, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2010, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2011, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2012, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2013, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2014, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2015, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2016, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2017, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2018, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2019, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2020, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2021, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2022, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2023, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2024, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2025, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2026, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2027, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2028, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2029, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2030, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2031, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2032, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2033, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2034, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2035, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2036, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2037, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2038, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2039, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2040, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2041, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2042, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2043, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2044, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2045, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2046, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2047, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2048, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2049, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2050, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2051, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2052, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2053, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2054, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2055, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2056, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2057, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2058, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2059, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2060, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2061, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2062, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2063, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2064, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2065, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2066, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2067, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2068, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2069, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2070, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2071, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2072, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2073, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2074, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2075, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2076, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2077, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2078, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2079, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2080, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2081, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2082, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2083, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2084, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2085, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2086, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2087, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2088, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2089, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2090, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2091, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2092, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2093, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2094, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2095, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2096, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2097, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2098, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2099, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2100, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2101, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2102, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2103, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2104, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2105, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2106, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2107, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2108, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2109, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2110, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2111, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2112, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2113, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2114, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2115, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2116, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2117, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2118, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2119, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2120, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2121, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2122, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2123, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2124, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2125, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2126, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2127, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2128, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2129, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2130, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2131, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2132, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2133, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2134, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2135, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2136, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2137, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2138, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2139, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2140, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2141, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2142, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2143, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2144, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2145, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2146, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2147, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2148, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2149, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2150, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2151, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2152, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2153, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2154, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2155, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2156, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2157, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2158, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2159, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2160, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2161, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2162, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2163, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2164, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2165, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2166, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2167, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2168, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2169, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2170, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2171, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2172, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2173, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2174, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2175, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2176, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2177, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2178, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2179, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2180, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2181, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2182, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2183, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2184, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2185, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2186, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2187, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2188, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2189, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2190, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2191, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2192, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2193, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2194, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2195, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2196, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2197, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2198, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2199, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2200, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2201, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2202, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2203, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2204, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2205, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2206, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2207, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2208, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2209, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2210, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2211, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2212, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2213, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2214, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2215, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2216, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2217, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2218, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2219, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2220, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2221, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2222, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2223, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2224, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2225, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2226, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2227, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2228, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2229, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2230, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2231, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2232, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2233, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2234, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2235, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2236, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2237, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2238, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2239, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2240, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2241, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2242, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2243, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2244, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2245, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2246, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2247, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2248, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2249, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2250, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2251, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2252, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2253, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2254, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2255, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2256, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2257, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2258, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2259, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2260, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2261, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2262, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2263, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2264, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2265, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2266, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2267, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2268, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2269, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2270, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2271, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2272, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2273, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2274, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2275, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2276, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2277, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2278, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2279, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2280, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2281, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2282, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2283, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2284, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2285, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2286, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2287, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2288, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2289, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2290, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2291, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2292, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2293, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2294, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2295, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2296, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2297, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2298, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2299, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2300, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2301, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2302, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2303, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2304, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2305, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2306, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2307, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2308, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2309, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2310, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2311, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2312, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2313, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2314, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2315, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2316, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2317, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2318, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2319, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2320, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2321, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2322, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2323, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2324, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2325, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2326, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2327, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2328, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2329, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2330, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2331, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2332, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2333, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2334, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2335, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2336, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2337, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2338, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2339, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2340, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2341, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2342, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2343, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2344, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2345, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2346, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2347, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2348, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2349, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2350, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2351, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2352, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2353, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2354, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2355, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2356, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2357, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2358, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2359, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2360, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2361, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2362, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2363, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2364, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2365, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2366, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2367, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2368, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2369, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2370, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2371, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2372, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2373, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2374, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2375, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2376, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2377, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2378, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2379, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2380, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2381, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2382, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2383, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2384, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2385, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2386, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2387, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2388, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2389, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2390, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2391, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2392, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2393, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2394, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2395, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2396, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2397, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2398, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2399, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2400, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2401, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2402, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2403, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2404, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2405, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2406, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2407, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2408, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2409, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2410, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2411, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2412, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2413, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2414, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2415, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2416, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2417, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2418, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2419, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2420, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2421, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2422, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2423, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2424, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2425, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2426, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2427, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2428, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2429, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2430, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2431, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2432, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2433, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2434, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2435, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2436, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2437, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2438, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2439, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2440, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2441, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2442, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2443, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2444, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2445, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2446, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2447, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2448, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2449, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2450, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2451, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2452, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2453, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2454, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2455, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2456, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2457, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2458, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2459, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2460, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2461, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2462, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2463, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2464, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2465, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2466, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2467, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2468, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2469, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2470, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2471, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2472, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2473, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2474, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2475, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2476, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2477, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2478, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2479, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2480, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2481, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2482, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2483, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2484, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2485, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2486, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2487, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2488, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2489, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2490, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2491, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2492, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2493, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2494, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2495, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2496, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2497, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2498, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2499, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2500, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2501, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2502, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2503, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2504, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2505, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2506, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2507, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2508, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2509, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2510, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2511, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2512, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2513, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2514, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2515, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2516, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2517, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2518, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2519, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2520, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2521, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2522, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2523, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2524, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2525, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2526, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2527, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2528, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2529, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2530, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2531, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2532, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2533, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2534, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2535, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2536, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2537, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2538, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2539, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2540, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2541, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2542, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2543, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2544, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2545, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2546, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2547, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2548, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2549, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2550, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2551, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2552, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2553, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2554, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2555, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2556, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2557, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2558, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2559, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2560, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2561, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2562, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2563, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2564, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2565, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2566, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2567, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2568, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2569, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2570, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2571, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2572, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2573, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2574, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2575, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2576, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2577, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2578, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2579, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2580, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2581, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2582, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2583, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2584, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2585, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2586, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2587, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2588, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2589, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2590, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2591, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2592, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2593, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2594, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2595, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2596, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2597, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2598, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2599, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2600, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2601, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2602, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2603, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2604, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2605, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2606, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2607, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2608, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2609, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2610, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2611, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2612, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2613, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2614, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2615, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2616, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2617, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2618, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2619, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2620, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2621, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2622, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2623, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2624, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2625, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2626, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2627, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2628, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2629, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2630, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2631, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2632, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2633, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2634, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2635, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2636, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2637, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2638, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2639, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2640, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2641, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2642, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2643, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2644, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2645, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2646, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2647, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2648, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2649, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2650, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2651, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2652, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2653, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2654, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2655, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2656, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2657, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2658, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2659, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2660, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2661, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2662, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2663, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2664, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2665, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2666, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2667, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2668, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2669, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2670, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2671, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2672, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2673, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2674, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2675, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2676, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2677, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2678, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2679, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2680, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2681, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2682, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2683, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2684, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2685, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2686, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2687, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2688, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2689, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2690, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2691, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2692, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2693, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2694, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2695, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2696, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2697, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2698, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2699, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2700, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2701, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2702, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2703, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2704, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2705, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2706, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2707, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2708, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2709, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2710, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2711, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2712, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2713, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2714, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2715, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2716, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2717, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2718, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2719, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2720, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2721, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2722, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2723, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2724, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2725, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2726, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2727, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2728, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2729, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2730, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2731, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2732, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2733, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2734, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2735, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2736, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2737, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2738, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2739, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2740, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2741, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2742, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2743, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2744, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2745, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2746, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2747, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2748, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2749, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2750, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2751, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2752, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2753, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2754, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2755, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2756, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2757, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2758, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2759, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2760, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2761, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2762, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2763, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2764, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2765, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2766, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2767, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2768, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2769, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2770, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2771, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2772, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2773, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2774, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2775, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2776, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2777, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2778, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2779, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2780, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2781, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2782, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2783, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2784, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2785, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2786, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2787, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2788, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2789, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2790, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2791, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2792, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2793, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2794, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2795, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2796, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2797, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2798, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2799, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2800, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2801, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2802, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2803, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2804, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2805, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2806, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2807, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2808, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2809, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2810, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2811, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2812, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2813, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2814, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2815, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2816, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2817, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2818, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2819, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2820, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2821, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2822, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2823, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2824, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2825, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2826, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2827, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2828, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2829, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2830, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2831, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2832, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2833, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2834, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2835, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2836, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2837, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2838, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2839, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2840, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2841, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2842, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2843, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2844, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2845, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2846, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2847, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2848, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2849, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2850, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2851, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2852, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2853, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2854, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2855, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2856, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2857, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2858, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2859, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2860, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2861, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2862, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2863, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2864, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2865, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2866, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2867, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2868, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2869, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2870, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2871, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2872, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2873, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2874, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2875, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2876, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2877, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2878, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2879, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2880, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2881, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2882, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2883, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2884, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2885, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2886, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2887, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2888, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2889, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2890, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2891, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2892, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2893, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2894, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2895, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2896, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2897, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2898, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2899, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2900, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2901, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2902, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2903, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2904, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2905, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2906, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2907, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2908, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2909, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2910, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2911, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2912, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2913, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2914, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2915, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2916, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2917, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2918, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2919, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2920, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2921, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2922, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2923, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2924, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2925, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2926, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2927, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2928, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2929, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2930, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2931, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2932, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2933, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2934, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2935, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2936, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2937, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2938, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2939, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2940, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2941, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2942, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2943, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2944, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2945, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2946, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2947, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2948, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2949, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2950, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2951, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2952, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2953, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2954, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2955, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2956, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2957, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2958, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2959, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2960, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2961, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2962, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2963, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2964, .adv_w = 224, .box_w = 14, .box_h = 2, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 2968, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2969, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2970, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2971, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 2989, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3007, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3008, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3009, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3010, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3011, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3012, .adv_w = 0, .box_w = 1, .box_h = 1, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3013, .adv_w = 128, .box_w = 7, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3024, .adv_w = 128, .box_w = 7, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3035, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3055, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3080, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 3110, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3135, .adv_w = 224, .box_w = 12, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 3156, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3177, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3198, .adv_w = 224, .box_w = 12, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 3219, .adv_w = 320, .box_w = 19, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3243, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3267, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3291, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3315, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3339, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3371, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3403, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3428, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3460, .adv_w = 256, .box_w = 17, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 3499, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3531, .adv_w = 224, .box_w = 14, .box_h = 2, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 3535, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3560, .adv_w = 192, .box_w = 12, .box_h = 7, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 3571, .adv_w = 192, .box_w = 12, .box_h = 7, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 3582, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3606, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3633, .adv_w = 160, .box_w = 8, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3647, .adv_w = 160, .box_w = 8, .box_h = 14, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 3661, .adv_w = 320, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3688, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3720, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3745, .adv_w = 288, .box_w = 16, .box_h = 14, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 3773, .adv_w = 288, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3801, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3829, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3857, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3889, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3915, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3939, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3960, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3985, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4019, .adv_w = 256, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4046, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4078, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 4103, .adv_w = 224, .box_w = 13, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 4126, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4158, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4190, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 4215, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 4240, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4277, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 4309, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4354, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4386, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 4411, .adv_w = 288, .box_w = 16, .box_h = 17, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 4445, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4469, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4499, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4531, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4565, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4585, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4617, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4649, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4681, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4713, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4745, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4777, .adv_w = 192, .box_w = 11, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4802, .adv_w = 192, .box_w = 11, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4826, .adv_w = 256, .box_w = 15, .box_h = 15, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 4855, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4885, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4917, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4941, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4961, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4987, .adv_w = 192, .box_w = 11, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 5011, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5039, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 5071, .adv_w = 256, .box_w = 18, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 5110, .adv_w = 256, .box_w = 18, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 5149, .adv_w = 256, .box_w = 18, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 5188, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 5213, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5238, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5263, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5288, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5313, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5338, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5363, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 5397, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 5437, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 5471, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 5499, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5529, .adv_w = 224, .box_w = 14, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 5561, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 5602, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 5640, .adv_w = 320, .box_w = 19, .box_h = 19, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 5686, .adv_w = 256, .box_w = 14, .box_h = 19, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 5720, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 5752, .adv_w = 288, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 5795, .adv_w = 192, .box_w = 11, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 5820, .adv_w = 320, .box_w = 18, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5847, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 5879, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 5911, .adv_w = 192, .box_w = 10, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 5933, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 5965, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 5997, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 6042, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6081, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6113, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6147, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6175, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6209, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 6246, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 6276, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6308, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6340, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6372, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6404, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 6429, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 6453, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6477, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6507, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6533, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6565, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6597, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6629, .adv_w = 224, .box_w = 14, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 6652, .adv_w = 224, .box_w = 14, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 6675, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 6693, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 6711, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6735, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 6771, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6799, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 6835, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 6871, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 6889, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 6914, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6934, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 6954, .adv_w = 64, .box_w = 2, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 6958, .adv_w = 64, .box_w = 2, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 6962, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 6990, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 7015, .adv_w = 224, .box_w = 14, .box_h = 2, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 7019, .adv_w = 224, .box_w = 14, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 7042, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7064, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7086, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7118, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7150, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7182, .adv_w = 288, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7214, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7246, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 7282, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 7306, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 7338, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 7372, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 7411, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7443, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7475, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 7513, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 7558, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 7590, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 7618, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7654, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7694, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7726, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 7767, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 7808, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7840, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 7881, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7913, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 7945, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 7979, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 8022, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 8061, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8093, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 8134, .adv_w = 160, .box_w = 10, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8156, .adv_w = 160, .box_w = 10, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8178, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8208, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8240, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 8272, .adv_w = 224, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 8297, .adv_w = 288, .box_w = 19, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 8340, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 8381, .adv_w = 288, .box_w = 19, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 8424, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 8469, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8501, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 8542, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 8585, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8613, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8641, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 8664, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 8687, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8715, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 8740, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8760, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8780, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8804, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8832, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8866, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 8894, .adv_w = 192, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 8915, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 8943, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 8971, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 8995, .adv_w = 256, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9024, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9054, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9082, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9112, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9134, .adv_w = 224, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9155, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9185, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9209, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9243, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 9277, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9298, .adv_w = 256, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 9324, .adv_w = 160, .box_w = 11, .box_h = 14, .ofs_x = -1, .ofs_y = -1}, + {.bitmap_index = 9344, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9368, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9400, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9432, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 9466, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9484, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9505, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 9526, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9547, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9568, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 9598, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 9624, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9656, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9681, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9705, .adv_w = 288, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9735, .adv_w = 224, .box_w = 13, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 9758, .adv_w = 224, .box_w = 13, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 9781, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 9817, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 9849, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 9881, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9917, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9944, .adv_w = 224, .box_w = 11, .box_h = 14, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 9964, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 9994, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10026, .adv_w = 288, .box_w = 17, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 10065, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10099, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10127, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 10148, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 10176, .adv_w = 256, .box_w = 16, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 10196, .adv_w = 192, .box_w = 10, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 10219, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 10253, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10287, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 10321, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10343, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10367, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10399, .adv_w = 128, .box_w = 8, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10415, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 10443, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10475, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 10503, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 10528, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 10553, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 10578, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10610, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 10651, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 10688, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 10728, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10760, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 10801, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 10842, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 10883, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 10924, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 10965, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 10997, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11036, .adv_w = 320, .box_w = 19, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 11074, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11117, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11157, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 11184, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11216, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11250, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 11273, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11307, .adv_w = 256, .box_w = 15, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11339, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11371, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11403, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 11435, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 11463, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11493, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11521, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11553, .adv_w = 160, .box_w = 10, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11576, .adv_w = 160, .box_w = 9, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11597, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 11625, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11657, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 11685, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11721, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11757, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11793, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 11829, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11864, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11892, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 11929, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 11966, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12003, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12040, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12077, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12117, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12154, .adv_w = 288, .box_w = 16, .box_h = 17, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 12188, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12225, .adv_w = 256, .box_w = 15, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12257, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 12296, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12337, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12369, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12399, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12431, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12465, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12505, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12535, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12559, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12591, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 12623, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12655, .adv_w = 320, .box_w = 18, .box_h = 14, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 12687, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 12721, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 12764, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12801, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12838, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12875, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12912, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 12949, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 12979, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 13011, .adv_w = 320, .box_w = 19, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13049, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13073, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13097, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13129, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13163, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13204, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13240, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13283, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13323, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13359, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13395, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13431, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13467, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13503, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13539, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13569, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13601, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13635, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13669, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13712, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13755, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13798, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 13841, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 13881, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 13926, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 13974, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 14017, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 14060, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 14103, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 14144, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14184, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 14232, .adv_w = 160, .box_w = 10, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14254, .adv_w = 160, .box_w = 10, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14276, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 14312, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14336, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14370, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14406, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14440, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14474, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 14495, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 14529, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14563, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14595, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14627, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 14675, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14713, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 14740, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14762, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 14798, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14830, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14864, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14898, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 14941, .adv_w = 256, .box_w = 16, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 14961, .adv_w = 320, .box_w = 19, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 14999, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 15033, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15069, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15101, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15137, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15173, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15207, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 15243, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 15284, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 15325, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 15353, .adv_w = 320, .box_w = 16, .box_h = 20, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 15393, .adv_w = 224, .box_w = 13, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 15423, .adv_w = 320, .box_w = 19, .box_h = 19, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 15469, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 15512, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 15553, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 15594, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 15635, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 15678, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 15719, .adv_w = 320, .box_w = 16, .box_h = 19, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 15757, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 15792, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 15822, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15856, .adv_w = 192, .box_w = 11, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 15881, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15917, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15949, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 15977, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 16009, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 16045, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 16075, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 16107, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 16152, .adv_w = 288, .box_w = 19, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 16193, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 16238, .adv_w = 256, .box_w = 17, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 16277, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 16320, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 16363, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 16406, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 16449, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 16477, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16518, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16559, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16600, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16641, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16682, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16723, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 16757, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 16792, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 16824, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16860, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16896, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 16932, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 16966, .adv_w = 320, .box_w = 20, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 16994, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 17021, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 17051, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 17094, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 17137, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 17180, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17219, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 17262, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17286, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17316, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17346, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17376, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 17403, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 17428, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 17453, .adv_w = 224, .box_w = 13, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 17483, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17523, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 17547, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 17575, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 17603, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17639, .adv_w = 256, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 17671, .adv_w = 256, .box_w = 17, .box_h = 15, .ofs_x = -1, .ofs_y = -1}, + {.bitmap_index = 17703, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17735, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17771, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17791, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17823, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17859, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17887, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17927, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 17964, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 17996, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18030, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18064, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 18099, .adv_w = 320, .box_w = 19, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 18133, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18173, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18207, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 18234, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 18277, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 18309, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18345, .adv_w = 256, .box_w = 15, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 18377, .adv_w = 288, .box_w = 16, .box_h = 17, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 18411, .adv_w = 320, .box_w = 19, .box_h = 18, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 18454, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18482, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 18517, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18537, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18559, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 18596, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 18633, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 18673, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 18709, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 18744, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 18770, .adv_w = 320, .box_w = 18, .box_h = 15, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 18804, .adv_w = 320, .box_w = 18, .box_h = 15, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 18838, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 18876, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 18917, .adv_w = 320, .box_w = 18, .box_h = 15, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 18951, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 18979, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 19020, .adv_w = 192, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19046, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19070, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19098, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19134, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19159, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19195, .adv_w = 192, .box_w = 10, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 19218, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19250, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19286, .adv_w = 96, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 19294, .adv_w = 96, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 19302, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19342, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19381, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19411, .adv_w = 256, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19440, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19472, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 19496, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19524, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19560, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19596, .adv_w = 224, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19621, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19646, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19671, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19696, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19721, .adv_w = 224, .box_w = 14, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19744, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 19762, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19794, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19826, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19860, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 19887, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 19921, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 19951, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 19985, .adv_w = 192, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20011, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20043, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20071, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20098, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20130, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20162, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20190, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20222, .adv_w = 256, .box_w = 17, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 20261, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20293, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 20317, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20343, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20371, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20398, .adv_w = 160, .box_w = 9, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20414, .adv_w = 224, .box_w = 13, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20437, .adv_w = 320, .box_w = 19, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 20471, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20496, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20521, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 20548, .adv_w = 288, .box_w = 17, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 20576, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20604, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20628, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 20660, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20688, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20715, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20736, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20757, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20789, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 20819, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20844, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20869, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20894, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20919, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20946, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20971, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 20996, .adv_w = 288, .box_w = 17, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 21022, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21047, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21079, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21103, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21135, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21159, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21191, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 21225, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21250, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21282, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21303, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21331, .adv_w = 288, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21359, .adv_w = 224, .box_w = 13, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 21382, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21403, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21428, .adv_w = 288, .box_w = 16, .box_h = 14, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 21456, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21484, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21505, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21530, .adv_w = 160, .box_w = 8, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 21544, .adv_w = 160, .box_w = 8, .box_h = 14, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 21558, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21590, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21622, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21654, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21686, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21718, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21750, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 21787, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21819, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21851, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21883, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 21907, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 21931, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21955, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 21979, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22009, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22034, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22059, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22084, .adv_w = 224, .box_w = 14, .box_h = 2, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 22088, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22116, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22148, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22178, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22208, .adv_w = 224, .box_w = 15, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22240, .adv_w = 288, .box_w = 19, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22274, .adv_w = 288, .box_w = 19, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 22317, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22347, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22383, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22410, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22438, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22470, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22497, .adv_w = 224, .box_w = 14, .box_h = 8, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 22511, .adv_w = 224, .box_w = 14, .box_h = 8, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 22525, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22557, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22596, .adv_w = 256, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 22622, .adv_w = 288, .box_w = 17, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 22650, .adv_w = 128, .box_w = 8, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 22668, .adv_w = 288, .box_w = 18, .box_h = 8, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 22686, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22714, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22742, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22774, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 22822, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 22863, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22893, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 22923, .adv_w = 288, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22943, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22971, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 22999, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 23025, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23057, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23085, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23117, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23144, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23169, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23201, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23226, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23250, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23275, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23301, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 23325, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23350, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23375, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23405, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23433, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 23472, .adv_w = 256, .box_w = 17, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 23498, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 23522, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23546, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23570, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23602, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23634, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23666, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23698, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23730, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 23762, .adv_w = 256, .box_w = 15, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 23787, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23815, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23845, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 23877, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23912, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23944, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 23976, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24004, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24036, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24064, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 24100, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24125, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24150, .adv_w = 224, .box_w = 14, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 24171, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24199, .adv_w = 256, .box_w = 17, .box_h = 13, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 24227, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24255, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24279, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24304, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24336, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24370, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 24394, .adv_w = 160, .box_w = 10, .box_h = 6, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 24402, .adv_w = 160, .box_w = 10, .box_h = 6, .ofs_x = 0, .ofs_y = 4}, + {.bitmap_index = 24410, .adv_w = 128, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 24418, .adv_w = 128, .box_w = 6, .box_h = 10, .ofs_x = 2, .ofs_y = 1}, + {.bitmap_index = 24426, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24451, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24475, .adv_w = 192, .box_w = 12, .box_h = 7, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24486, .adv_w = 192, .box_w = 12, .box_h = 7, .ofs_x = 0, .ofs_y = 7}, + {.bitmap_index = 24497, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 24521, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24553, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 24590, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24622, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24654, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 24695, .adv_w = 224, .box_w = 14, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 24727, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24755, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24789, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24821, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 24847, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24879, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24911, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 24943, .adv_w = 224, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 24968, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 25005, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 25035, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25063, .adv_w = 288, .box_w = 17, .box_h = 15, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 25095, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25125, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25149, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25173, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25209, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25243, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 25273, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25309, .adv_w = 288, .box_w = 16, .box_h = 14, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 25337, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 25362, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 25387, .adv_w = 224, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 25407, .adv_w = 224, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 25427, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 25447, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 25467, .adv_w = 128, .box_w = 7, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 25478, .adv_w = 128, .box_w = 7, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 25489, .adv_w = 192, .box_w = 12, .box_h = 7, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 25500, .adv_w = 192, .box_w = 12, .box_h = 7, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 25511, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25541, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 25576, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25604, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25626, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25658, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 25676, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 25694, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25726, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25758, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 25788, .adv_w = 256, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 25814, .adv_w = 288, .box_w = 17, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 25842, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25874, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25906, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 25938, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 25968, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 25995, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26023, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26051, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 26075, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26111, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 26143, .adv_w = 288, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 26163, .adv_w = 256, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26192, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26224, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26252, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 26293, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26313, .adv_w = 96, .box_w = 6, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26325, .adv_w = 64, .box_w = 2, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 26329, .adv_w = 288, .box_w = 16, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 26357, .adv_w = 288, .box_w = 16, .box_h = 14, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 26385, .adv_w = 288, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 26417, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26449, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26473, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 26514, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26544, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 26571, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26603, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 26635, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26667, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26699, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26731, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26763, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 26797, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26823, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26855, .adv_w = 224, .box_w = 14, .box_h = 3, .ofs_x = 0, .ofs_y = 4}, + {.bitmap_index = 26861, .adv_w = 64, .box_w = 4, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 26868, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 26893, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 26925, .adv_w = 288, .box_w = 19, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 26954, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 26979, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27004, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 27026, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 27048, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27073, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27098, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27123, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 27157, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 27189, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27214, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27239, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27264, .adv_w = 224, .box_w = 12, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 27285, .adv_w = 192, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 27303, .adv_w = 160, .box_w = 9, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 27321, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27346, .adv_w = 192, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27369, .adv_w = 224, .box_w = 12, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 27390, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 27420, .adv_w = 192, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 27446, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 27470, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27498, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27526, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27558, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27590, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27617, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27644, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27674, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 27704, .adv_w = 160, .box_w = 10, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 27727, .adv_w = 160, .box_w = 10, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 27750, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 27773, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 27796, .adv_w = 192, .box_w = 11, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 27821, .adv_w = 192, .box_w = 11, .box_h = 19, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 27848, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 27885, .adv_w = 256, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 27912, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 27940, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 27976, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28008, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28040, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28065, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28097, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28129, .adv_w = 192, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28149, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28174, .adv_w = 288, .box_w = 17, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28204, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28229, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28259, .adv_w = 288, .box_w = 19, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28293, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28329, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28359, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28383, .adv_w = 160, .box_w = 11, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 28405, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28433, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28465, .adv_w = 256, .box_w = 15, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 28497, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28529, .adv_w = 256, .box_w = 18, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 28568, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28596, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 28626, .adv_w = 224, .box_w = 14, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 28658, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28686, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 28723, .adv_w = 192, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28749, .adv_w = 192, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28775, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28799, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28823, .adv_w = 192, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28849, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28873, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28897, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28921, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28953, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 28985, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 29026, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 29067, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29099, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29131, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = -1, .ofs_y = -1}, + {.bitmap_index = 29158, .adv_w = 224, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29188, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29220, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29250, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 29275, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 29312, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29344, .adv_w = 256, .box_w = 17, .box_h = 14, .ofs_x = -1, .ofs_y = -1}, + {.bitmap_index = 29374, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 29402, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29432, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 29460, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 29492, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29516, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 29557, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 29598, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29628, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29660, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29692, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29724, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29760, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29788, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 29816, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 29850, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 29878, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 29905, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 29932, .adv_w = 320, .box_w = 19, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 29966, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 29994, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 30018, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 30043, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 30079, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 30115, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 30147, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30190, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 30216, .adv_w = 320, .box_w = 19, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 30250, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 30282, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 30310, .adv_w = 192, .box_w = 11, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30334, .adv_w = 256, .box_w = 15, .box_h = 15, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 30363, .adv_w = 192, .box_w = 11, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30388, .adv_w = 256, .box_w = 14, .box_h = 19, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 30422, .adv_w = 288, .box_w = 18, .box_h = 19, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 30465, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30506, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 30544, .adv_w = 320, .box_w = 19, .box_h = 19, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30590, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 30622, .adv_w = 192, .box_w = 11, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30647, .adv_w = 320, .box_w = 18, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 30674, .adv_w = 192, .box_w = 10, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30696, .adv_w = 192, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 30714, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 30739, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 30775, .adv_w = 320, .box_w = 18, .box_h = 15, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 30809, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 30841, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30867, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 30893, .adv_w = 320, .box_w = 19, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 30922, .adv_w = 320, .box_w = 19, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 30951, .adv_w = 320, .box_w = 19, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 30980, .adv_w = 320, .box_w = 19, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 31009, .adv_w = 320, .box_w = 19, .box_h = 12, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 31038, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 31062, .adv_w = 128, .box_w = 8, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31078, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31114, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31154, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 31181, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 31208, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31240, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31280, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31304, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31328, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31352, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31376, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31400, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31424, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31454, .adv_w = 256, .box_w = 17, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 31480, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 31504, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31536, .adv_w = 224, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31566, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31592, .adv_w = 320, .box_w = 19, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 31616, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31648, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31682, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 31709, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 31736, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 31763, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 31790, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 31818, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31838, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31870, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31902, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31934, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 31966, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 31998, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 32022, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32054, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32086, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32118, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32150, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 32178, .adv_w = 288, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 32210, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32242, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 32267, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32299, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32331, .adv_w = 288, .box_w = 16, .box_h = 18, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 32367, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 32391, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 32428, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 32454, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32486, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32526, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32558, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32590, .adv_w = 288, .box_w = 19, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 32633, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32663, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 32695, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 32727, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 32759, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 32789, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 32819, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 32851, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 32883, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32915, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32947, .adv_w = 224, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32972, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 32996, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33028, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33060, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33080, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33100, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33120, .adv_w = 160, .box_w = 9, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33138, .adv_w = 160, .box_w = 9, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33156, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33184, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33216, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33244, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33268, .adv_w = 256, .box_w = 16, .box_h = 2, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33272, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33304, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33329, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 33353, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33385, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 33421, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33453, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33483, .adv_w = 256, .box_w = 17, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 33522, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33552, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33584, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33610, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33638, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 33666, .adv_w = 256, .box_w = 17, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 33705, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33737, .adv_w = 288, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33769, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33801, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33833, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33865, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 33897, .adv_w = 160, .box_w = 10, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 33920, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 33943, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 33966, .adv_w = 160, .box_w = 10, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 33989, .adv_w = 288, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34021, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 34060, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34085, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34109, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34137, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34169, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34201, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34233, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34265, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34297, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34329, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34361, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34393, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34418, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34450, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34482, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34514, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34546, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 34569, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34597, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34627, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34652, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34680, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34702, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34724, .adv_w = 288, .box_w = 15, .box_h = 17, .ofs_x = 3, .ofs_y = -2}, + {.bitmap_index = 34756, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34780, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34804, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34826, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34848, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34870, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 34894, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 34935, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 34959, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 34989, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35019, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35047, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35075, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35107, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 35134, .adv_w = 224, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35159, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 35183, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35217, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35249, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35279, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 35320, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35352, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35384, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35416, .adv_w = 256, .box_w = 15, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 35448, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35468, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 35493, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35523, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35549, .adv_w = 192, .box_w = 11, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35573, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35605, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35629, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 35659, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35691, .adv_w = 192, .box_w = 13, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 35719, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 35743, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 35782, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35814, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 35848, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35880, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35910, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 35933, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 35958, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 35990, .adv_w = 256, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 36022, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36046, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 36083, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36107, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36131, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36163, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36187, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36223, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36259, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36283, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36307, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 36331, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36367, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36399, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 36435, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36467, .adv_w = 288, .box_w = 18, .box_h = 6, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36481, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36513, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36537, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36561, .adv_w = 320, .box_w = 19, .box_h = 16, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 36599, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36637, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36673, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 36707, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36739, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36771, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36803, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36835, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36871, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 36898, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 36926, .adv_w = 320, .box_w = 19, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36964, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 36996, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37028, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 37069, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 37099, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37133, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37167, .adv_w = 288, .box_w = 18, .box_h = 6, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37181, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37217, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37253, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37289, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37324, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 37363, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 37395, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37429, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 37470, .adv_w = 288, .box_w = 16, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 37504, .adv_w = 192, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37526, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37558, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37590, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37622, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37654, .adv_w = 288, .box_w = 17, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 37684, .adv_w = 288, .box_w = 19, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 37720, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37758, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 37799, .adv_w = 160, .box_w = 10, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 37821, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37851, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 37892, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 37922, .adv_w = 320, .box_w = 18, .box_h = 15, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 37956, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 37995, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 38034, .adv_w = 320, .box_w = 19, .box_h = 16, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 38072, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38108, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38136, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 38173, .adv_w = 320, .box_w = 19, .box_h = 15, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 38209, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38235, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 38274, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 38315, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 38354, .adv_w = 224, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38379, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 38419, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38459, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38499, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38529, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38559, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38593, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38629, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 38656, .adv_w = 320, .box_w = 19, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38692, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38726, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38758, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38790, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38830, .adv_w = 288, .box_w = 17, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 38858, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 38890, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 38915, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 38940, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 38965, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 38990, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39015, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39040, .adv_w = 224, .box_w = 14, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 39063, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 39091, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 39119, .adv_w = 224, .box_w = 14, .box_h = 8, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 39133, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 39167, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39199, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 39231, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39263, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 39290, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39315, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39347, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 39372, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39404, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39431, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39456, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 39480, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 39521, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39549, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39577, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 39601, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 39625, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39650, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 39682, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39707, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39732, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39760, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 39784, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39824, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 39861, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 39886, .adv_w = 288, .box_w = 18, .box_h = 8, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 39904, .adv_w = 128, .box_w = 8, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 39922, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 39958, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 39995, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40031, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40063, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40095, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40123, .adv_w = 288, .box_w = 17, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40153, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 40177, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40209, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40239, .adv_w = 320, .box_w = 19, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40275, .adv_w = 192, .box_w = 12, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 40302, .adv_w = 256, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 40328, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40360, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40388, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40416, .adv_w = 224, .box_w = 14, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 40448, .adv_w = 320, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 40475, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40510, .adv_w = 256, .box_w = 14, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 40538, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40562, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40590, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40620, .adv_w = 192, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40643, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 40684, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 40708, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40740, .adv_w = 256, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40769, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40801, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 40828, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40860, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40892, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40920, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 40952, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 40984, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41008, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41034, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 41068, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41092, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41116, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41140, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41166, .adv_w = 320, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 41207, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41231, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41263, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 41300, .adv_w = 256, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 41332, .adv_w = 288, .box_w = 18, .box_h = 11, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 41357, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41389, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41421, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41451, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41483, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41515, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41547, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41579, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41611, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41643, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41675, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 41712, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41744, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41776, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 41817, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41849, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41889, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41921, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41953, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 41987, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42019, .adv_w = 256, .box_w = 16, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 42039, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42059, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 42086, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42114, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42148, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42175, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42205, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 42239, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42271, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42303, .adv_w = 320, .box_w = 19, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 42341, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42373, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42405, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42437, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42469, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42505, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 42544, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 42583, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42613, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42643, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42675, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42707, .adv_w = 192, .box_w = 11, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42731, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42763, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 42797, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42821, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42853, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42885, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42917, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42953, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 42987, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43015, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43047, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43079, .adv_w = 288, .box_w = 18, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 43109, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 43144, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43176, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43210, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 43242, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43274, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 43306, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43338, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 43374, .adv_w = 192, .box_w = 12, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 43401, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43433, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43465, .adv_w = 320, .box_w = 20, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 43493, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43531, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 43572, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43604, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43632, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43664, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43696, .adv_w = 160, .box_w = 10, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 43718, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 43750, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43778, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43806, .adv_w = 320, .box_w = 20, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 43834, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 43866, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 43900, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 43928, .adv_w = 256, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 43954, .adv_w = 320, .box_w = 19, .box_h = 19, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 44000, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 44035, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 44069, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44101, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44133, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 44168, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44200, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44234, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44270, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44302, .adv_w = 320, .box_w = 20, .box_h = 11, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 44330, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44362, .adv_w = 256, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44390, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 44420, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44452, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44484, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44516, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44548, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 44576, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 44604, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 44640, .adv_w = 160, .box_w = 10, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 44663, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44697, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 44732, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 44756, .adv_w = 160, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44776, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44804, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 44843, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44879, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44911, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 44952, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 44976, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45008, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 45045, .adv_w = 256, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 45071, .adv_w = 256, .box_w = 16, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 45097, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 45131, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45163, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45195, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45229, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45263, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45291, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45323, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45355, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45387, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45423, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45463, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45502, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 45534, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45574, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45606, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45638, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 45663, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 45688, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45712, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 45752, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45780, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45812, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45844, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45874, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 45906, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 45938, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 45974, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46008, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46044, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46072, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46108, .adv_w = 288, .box_w = 17, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 46138, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46170, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 46206, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46234, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 46264, .adv_w = 288, .box_w = 16, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 46296, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46324, .adv_w = 320, .box_w = 18, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 46360, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46399, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 46429, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 46465, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46495, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46534, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46574, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46606, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46638, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 46675, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46699, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46723, .adv_w = 320, .box_w = 19, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46764, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46804, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46834, .adv_w = 224, .box_w = 13, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 46864, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 46899, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 46935, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 46969, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 46990, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 47017, .adv_w = 256, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 47047, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 47079, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = -1, .ofs_y = -1}, + {.bitmap_index = 47116, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 47140, .adv_w = 224, .box_w = 13, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 47170, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 47202, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 47232, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 47273, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 47309, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 47341, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 47373, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47407, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47433, .adv_w = 288, .box_w = 18, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 47456, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47488, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47520, .adv_w = 160, .box_w = 10, .box_h = 20, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 47545, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47577, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47613, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47645, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47677, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47716, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47756, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47784, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47808, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47840, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 47872, .adv_w = 288, .box_w = 17, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 47911, .adv_w = 256, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 47947, .adv_w = 320, .box_w = 20, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 47980, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 48015, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48051, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 48081, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 48111, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 48145, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48173, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48205, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 48237, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 48261, .adv_w = 192, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48284, .adv_w = 256, .box_w = 14, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 48312, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 48346, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 48376, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 48403, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 48430, .adv_w = 224, .box_w = 13, .box_h = 17, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 48458, .adv_w = 320, .box_w = 17, .box_h = 17, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 48495, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48527, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48559, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48591, .adv_w = 320, .box_w = 19, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 48627, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 48651, .adv_w = 288, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48690, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48730, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 48755, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48787, .adv_w = 224, .box_w = 14, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 48798, .adv_w = 96, .box_w = 6, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 48809, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48841, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 48869, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48899, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48931, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 48963, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 48995, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49023, .adv_w = 288, .box_w = 16, .box_h = 17, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 49057, .adv_w = 288, .box_w = 17, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49089, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49121, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49161, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49193, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49225, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49249, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49273, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49303, .adv_w = 288, .box_w = 17, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 49340, .adv_w = 288, .box_w = 19, .box_h = 15, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 49376, .adv_w = 320, .box_w = 19, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 49407, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49439, .adv_w = 288, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49469, .adv_w = 320, .box_w = 20, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 49514, .adv_w = 320, .box_w = 19, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 49552, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49573, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49601, .adv_w = 288, .box_w = 17, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 49635, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49669, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49693, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 49734, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49762, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49794, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 49822, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 49856, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49880, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49912, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 49949, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 49981, .adv_w = 192, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50004, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50040, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50068, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 50094, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50126, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 50160, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 50194, .adv_w = 256, .box_w = 17, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 50228, .adv_w = 320, .box_w = 18, .box_h = 17, .ofs_x = 2, .ofs_y = -3}, + {.bitmap_index = 50267, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50299, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 50325, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50360, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 50384, .adv_w = 288, .box_w = 17, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50414, .adv_w = 256, .box_w = 15, .box_h = 17, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 50446, .adv_w = 256, .box_w = 15, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50476, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50504, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50529, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50559, .adv_w = 224, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50589, .adv_w = 224, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50615, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 50639, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50675, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50700, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50725, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50750, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50786, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50818, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50852, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 50884, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50909, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 50947, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 50988, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 51016, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 51044, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 51076, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 51108, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 51135, .adv_w = 256, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 51162, .adv_w = 288, .box_w = 17, .box_h = 15, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 51194, .adv_w = 320, .box_w = 20, .box_h = 9, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 51217, .adv_w = 320, .box_w = 20, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 51250, .adv_w = 320, .box_w = 20, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 51283, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51307, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 51339, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51371, .adv_w = 288, .box_w = 18, .box_h = 15, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51405, .adv_w = 192, .box_w = 12, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 51431, .adv_w = 320, .box_w = 19, .box_h = 15, .ofs_x = 1, .ofs_y = -2} +}; + +/*--------------------- + * CHARACTER MAPPING + *--------------------*/ + +static const uint16_t unicode_list_6[] = { + 0x0, 0x5, 0x6, 0x8, 0x9, 0xd, 0xe, 0x11, + 0x12, 0x15, 0x16, 0x1b, 0x25, 0x27, 0x28, 0x2e, + 0x2f, 0x99, 0x9d, 0x9e, 0x9f, 0xa1, 0xa9, 0xad, + 0xb2, 0x117, 0x185, 0x186, 0x187, 0x188, 0x189, 0x18a, + 0x18c, 0x1af, 0x1b0, 0x1b9, 0x207, 0x213, 0x2f8, 0x2f9, + 0x310, 0x31d, 0x31e, 0x31f, 0x320, 0x38e, 0x3c4, 0x3de, + 0x3df, 0x3e2, 0x3e3, 0x3e5, 0x3e6, 0x3e8, 0x3ed, 0x3ee, + 0x3f0, 0x3f3, 0x4b2, 0x595, 0x5ab, 0x5c4, 0x5c5, 0x5f0, + 0x5f1, 0x5f5, 0x5f6, 0x5f8, 0x5f9, 0x606, 0x60a, 0x612, + 0x615, 0x617, 0x618, 0x61a, 0x61f, 0x621, 0x623, 0x624, + 0x62d, 0x62e, 0x634, 0x635, 0x637, 0x64f, 0x650, 0x651, + 0x652, 0x653, 0x654, 0x65a, 0x65b, 0x667, 0x66f, 0x670, + 0x673, 0x675, 0x676, 0x677, 0x678, 0x679, 0x67a, 0x688, + 0x68b, 0x68e, 0x690, 0x695, 0x696, 0x697, 0x698, 0x699, + 0x69a, 0x69b, 0x69c, 0x69d, 0x69e, 0x69f, 0x6a0, 0x6a7, + 0x6b2, 0x6b3, 0x6b9, 0x6ba, 0x6bb, 0x6d4, 0x6de, 0x6df, + 0x6ec, 0x6ef, 0x6f2, 0x6f5, 0x6f7, 0x6f9, 0x6fa, 0x6fe, + 0x6ff, 0x700, 0x701, 0x704, 0x706, 0x707, 0x708, 0x709, + 0x70a, 0x70b, 0x712, 0x716, 0x726, 0x739, 0x73b, 0x741, + 0x743, 0x748, 0x749, 0x74a, 0x74c, 0x759, 0x78a, 0x78b, + 0x78c, 0x929, 0x92a, 0xb02, 0xb10, 0xb11, 0xb18, 0xb19, + 0xb45, 0xbffa, 0xbffb, 0xc002, 0xc007, 0xc034, 0xc035, 0xc036 +}; + +static const uint16_t unicode_list_8[] = { + 0x0, 0x1, 0x12, 0x13, 0x15, 0x24, 0x27, 0x2f, + 0x32, 0x36, 0x4a, 0x53, 0x5a, 0x5e, 0x5f, 0xac, + 0xb4, 0xb5, 0xb6, 0xb7, 0xbb, 0xcd, 0xde, 0xe4, + 0xe8, 0xf6, 0xff, 0x100, 0x10a, 0x115, 0x116, 0x123, + 0x12b, 0x137, 0x13f, 0x143, 0x14e, 0x150, 0x152, 0x168, + 0x16e, 0x171, 0x179, 0x184, 0x19c, 0x19d, 0x1a8, 0x1b8, + 0x204, 0x217, 0x232, 0x236, 0x240, 0x242, 0x245, 0x248, + 0x249, 0x261, 0x266, 0x282, 0x299, 0x32a, 0x32c, 0x32d, + 0x370, 0x3b7, 0x3c0, 0x3c2, 0x3c3, 0x3e7, 0x3ee, 0x3f1, + 0x3f2, 0x3f5, 0x3f6, 0x40b, 0x40f, 0x420, 0x423, 0x424, + 0x425, 0x426, 0x427, 0x428, 0x42a, 0x42b, 0x42e +}; + +static const uint8_t glyph_id_ofs_list_11[] = { + 0, 1, 2, 3, 4, 5, 6, 0, + 7, 8, 9, 10 +}; + +static const uint8_t glyph_id_ofs_list_16[] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 0, + 30, 31, 32, 33, 0, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 0, + 52, 53, 54, 55, 56, 57, 58, 0, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 0, 69, 70 +}; + +static const uint16_t unicode_list_17[] = { + 0x0, 0x1, 0x9, 0xa, 0xf, 0x14, 0xd8, 0xda, + 0xe2, 0xef, 0xf1, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + 0xfa, 0xfb, 0x1f0, 0x267, 0x26a, 0x276, 0x27b, 0x27c, + 0x27d, 0x280 +}; + +static const uint8_t glyph_id_ofs_list_24[] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 0, + 15, 0, 0, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 0, 25, 26, 0, + 27, 28, 0, 29, 30, 31, 32, 33, + 34, 0, 0, 0, 35, 36, 37, 0, + 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 0, + 53, 54, 55, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 0, + 71, 72, 0, 0, 0, 0, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 0, + 82, 0, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 0, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 0, + 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 0, + 126, 127, 128, 0, 129, 130, 0, 0, + 131, 132, 133, 134, 135, 136, 137, 0, + 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 0, + 153, 154, 155, 156, 157, 158, 0, 159, + 160, 161, 162, 0, 0, 163, 164, 0, + 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 179, 0, + 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 0, 190, 191, 192, 193, 0, + 194, 195, 196, 197, 198, 199 +}; + +static const uint8_t glyph_id_ofs_list_25[] = { + 0, 1, 2, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 5, 0, + 6, 7, 8, 9, 0, 0, 0, 0, + 0, 10, 0, 11, 12, 13, 14, 0, + 15, 16, 17, 0, 18, 0, 0, 19, + 20, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21, 22, + 23, 24, 0, 25, 26, 27, 28, 0, + 0, 0, 0, 29, 30, 31, 32, 0, + 0, 0, 0, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 0, 0, 0, + 43, 44, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 45, 46, 47, 48, 49, + 50, 51, 0, 52, 53, 54, 55, 56, + 57, 58, 0, 0, 0, 59, 60, 61, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 0, 71, 72, 0, 0, 73, + 74, 75, 76, 0, 0, 77, 78, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 79, 80, 81, 82, 83, 84, + 85, 86, 0, 0, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, + 99, 0, 0, 0, 0, 0, 100, 101, + 102, 103, 0, 104, 105, 0, 0, 0, + 0, 0, 0, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 0, 0, + 117, 118, 0, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, + 132 +}; + +static const uint16_t unicode_list_26[] = { + 0x0, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, + 0xc, 0xd, 0xe, 0xf, 0x17, 0x1f, 0x20, 0x21, + 0x22, 0x24, 0x25, 0x26, 0x29, 0x2e, 0x30, 0x31, + 0x32, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3b, 0x3c, + 0x48, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x54, 0x55, 0x56, 0x57, 0x5b, 0x5c, + 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x64, 0x65, + 0x66, 0x67, 0x68, 0x6f, 0x70, 0x79, 0x7b, 0x7e, + 0x81, 0x85, 0x86, 0x89, 0x8a, 0x8d, 0x92, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0x9d, 0x9e, 0x9f, 0xa0, + 0xa6, 0xb0, 0xb2, 0xbc, 0xc6, 0xcb, 0xcc, 0xe2, + 0xec, 0xed, 0xee, 0xef, 0xf1, 0xf4, 0xf6, 0xf7, + 0x115, 0x116, 0x11a, 0x11b, 0x124, 0x134, 0x139, 0x152, + 0x153, 0x155, 0x159, 0x15d, 0x161, 0x162, 0x163, 0x165, + 0x171, 0x174, 0x179, 0x181, 0x18e, 0x18f, 0x191, 0x193, + 0x19a, 0x1a4, 0x1b6, 0x1b8, 0x1b9, 0x1c6, 0x1c7, 0x1c8, + 0x1ca, 0x1cd, 0x1ce, 0x1d0, 0x1d3, 0x1d5, 0x1d7, 0x1d9, + 0x1db, 0x1df, 0x1e2, 0x1e4, 0x1e7, 0x1ec, 0x1f0, 0x1f1, + 0x1f3, 0x1f5, 0x1f6, 0x1fa, 0x1fc, 0x1fd, 0x1fe, 0x1ff, + 0x200, 0x201, 0x204, 0x205, 0x206, 0x208, 0x20b, 0x20c, + 0x20d, 0x211, 0x212, 0x213, 0x215, 0x216, 0x218, 0x219, + 0x21a, 0x21b, 0x21f, 0x221, 0x222, 0x224, 0x225, 0x226, + 0x227, 0x228, 0x22a, 0x22b, 0x232, 0x235, 0x241, 0x247, + 0x24c, 0x24d, 0x24e, 0x251, 0x252, 0x254, 0x255, 0x256, + 0x258, 0x25a, 0x261, 0x262, 0x267, 0x26a, 0x26b, 0x26c, + 0x26d, 0x26e, 0x26f, 0x272, 0x273, 0x276, 0x277, 0x27a +}; + +static const uint8_t glyph_id_ofs_list_29[] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 0, 11, 12, 13, 14, + 0, 15, 16, 17, 18, 0, 0, 19, + 20, 21, 22, 23, 24, 25, 26, 0, + 27, 28, 0, 29, 30, 31, 0, 32, + 33, 34, 35, 0, 36, 37, 38, 39, + 40, 41, 42, 0, 43, 44, 45, 46, + 0, 0, 47, 48, 0, 49, 50, 51 +}; + +static const uint16_t unicode_list_30[] = { + 0x0, 0x3, 0x5, 0x7, 0x8, 0xa, 0xd, 0x10, + 0x14, 0x17, 0x25, 0x26, 0x2a, 0x2d, 0x39, 0x3c, + 0x42, 0x48, 0x4a, 0x4d, 0x4e, 0x52, 0x53, 0x57, + 0x58, 0x59, 0x60, 0x64, 0x65, 0x6a, 0x6d, 0x70, + 0x73, 0x78, 0x7a, 0x7c, 0x7d, 0x7e, 0x81, 0x86, + 0x87, 0x8b, 0x8d, 0x8e, 0x8f, 0x92, 0x93, 0x94, + 0x96, 0x98, 0x9d, 0x9f, 0xa1, 0xa2, 0xa4, 0xa5, + 0xa8, 0xaa, 0xab, 0xac, 0xad, 0xb0, 0xb1, 0xb2, + 0xbf, 0xc1, 0xc2, 0xc3, 0xc4, 0xc9, 0xca, 0xd0, + 0xd2, 0xd6, 0xdf, 0xe0, 0xe4, 0xe7, 0xe9, 0xec, + 0xed, 0xf1, 0xf8, 0xfa, 0xfc, 0xfe, 0x100, 0x102, + 0x106, 0x107, 0x10b, 0x10c, 0x10f, 0x111, 0x115, 0x116, + 0x119, 0x11a, 0x11b, 0x123, 0x125, 0x128, 0x129, 0x134, + 0x135, 0x137, 0x13d, 0x13e, 0x140, 0x147, 0x148, 0x14b, + 0x151, 0x152, 0x154, 0x157, 0x158, 0x164, 0x165, 0x166, + 0x169, 0x16c, 0x170, 0x176, 0x17a, 0x17b, 0x17c, 0x17f, + 0x183, 0x184, 0x187, 0x188, 0x192, 0x194, 0x195, 0x198, + 0x199, 0x19b, 0x19c, 0x1a5, 0x1a6, 0x1a9, 0x1aa, 0x1ac, + 0x1ad, 0x1af, 0x1b0, 0x1b1, 0x1b5, 0x1bc, 0x1bd, 0x1bf, + 0x1c5, 0x1c8, 0x1c9, 0x1cb, 0x1cd, 0x1ce, 0x1cf, 0x1d2, + 0x1d3, 0x1d4, 0x1d6, 0x1d7, 0x1de, 0x1df, 0x1e2, 0x1e3, + 0x1e6, 0x1e8, 0x1e9, 0x1eb, 0x1ed, 0x1ee, 0x1f2, 0x1f3, + 0x1f5, 0x1f6, 0x1f7, 0x1f9, 0x1fb, 0x200, 0x201, 0x202, + 0x203, 0x20d, 0x20e, 0x20f, 0x215, 0x218, 0x21b, 0x21c, + 0x21e, 0x220, 0x223, 0x224, 0x22b, 0x22e, 0x22f, 0x230, + 0x233, 0x234, 0x235, 0x236, 0x238, 0x239, 0x23b, 0x23e, + 0x23f, 0x241, 0x246, 0x250, 0x251, 0x252, 0x253, 0x258, + 0x267, 0x273, 0x275, 0x279, 0x27c, 0x287, 0x28c, 0x296, + 0x2a2, 0x2a4, 0x2a5, 0x2a6, 0x2aa, 0x2ab, 0x2ad, 0x2ae, + 0x2af, 0x2b0, 0x2ba, 0x2c0, 0x2e9, 0x2ea, 0x2f5, 0x300, + 0x302, 0x30e, 0x318, 0x328 +}; + +/*Collect the unicode lists and glyph_id offsets*/ +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ + { + .range_start = 32, .range_length = 16, .glyph_id_start = 1, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 48, .range_length = 256, .glyph_id_start = 17, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 304, .range_length = 256, .glyph_id_start = 273, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 560, .range_length = 256, .glyph_id_start = 529, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 816, .range_length = 256, .glyph_id_start = 785, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 1072, .range_length = 256, .glyph_id_start = 1041, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 8203, .range_length = 49207, .glyph_id_start = 1297, + .unicode_list = unicode_list_6, .glyph_id_ofs_list = NULL, .list_length = 176, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + }, + { + .range_start = 57433, .range_length = 30, .glyph_id_start = 1473, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 57477, .range_length = 1071, .glyph_id_start = 1503, + .unicode_list = unicode_list_8, .glyph_id_ofs_list = NULL, .list_length = 87, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + }, + { + .range_start = 58549, .range_length = 24, .glyph_id_start = 1590, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 58574, .range_length = 17, .glyph_id_start = 1614, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 58592, .range_length = 12, .glyph_id_start = 1631, + .unicode_list = NULL, .glyph_id_ofs_list = glyph_id_ofs_list_11, .list_length = 12, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL + }, + { + .range_start = 58605, .range_length = 23, .glyph_id_start = 1642, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 58631, .range_length = 31, .glyph_id_start = 1665, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 58663, .range_length = 9, .glyph_id_start = 1696, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 58674, .range_length = 30, .glyph_id_start = 1705, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 58705, .range_length = 77, .glyph_id_start = 1735, + .unicode_list = NULL, .glyph_id_ofs_list = glyph_id_ofs_list_16, .list_length = 77, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL + }, + { + .range_start = 58784, .range_length = 641, .glyph_id_start = 1806, + .unicode_list = unicode_list_17, .glyph_id_ofs_list = NULL, .list_length = 26, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + }, + { + .range_start = 61440, .range_length = 15, .glyph_id_start = 1832, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 61456, .range_length = 15, .glyph_id_start = 1847, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 61473, .range_length = 30, .glyph_id_start = 1862, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 61504, .range_length = 15, .glyph_id_start = 1892, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 61520, .range_length = 15, .glyph_id_start = 1907, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 61536, .range_length = 15, .glyph_id_start = 1922, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 61552, .range_length = 246, .glyph_id_start = 1937, + .unicode_list = NULL, .glyph_id_ofs_list = glyph_id_ofs_list_24, .list_length = 246, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL + }, + { + .range_start = 61813, .range_length = 233, .glyph_id_start = 2137, + .unicode_list = NULL, .glyph_id_ofs_list = glyph_id_ofs_list_25, .list_length = 233, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL + }, + { + .range_start = 62060, .range_length = 635, .glyph_id_start = 2270, + .unicode_list = unicode_list_26, .glyph_id_ofs_list = NULL, .list_length = 208, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + }, + { + .range_start = 62714, .range_length = 16, .glyph_id_start = 2478, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 62741, .range_length = 125, .glyph_id_start = 2494, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 62867, .range_length = 64, .glyph_id_start = 2619, + .unicode_list = NULL, .glyph_id_ofs_list = glyph_id_ofs_list_29, .list_length = 64, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL + }, + { + .range_start = 62935, .range_length = 809, .glyph_id_start = 2671, + .unicode_list = unicode_list_30, .glyph_id_ofs_list = NULL, .list_length = 244, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + } +}; + + + +/*-------------------- + * ALL CUSTOM DATA + *--------------------*/ + +#if LVGL_VERSION_MAJOR == 8 +/*Store all the custom data of the font*/ +static lv_font_fmt_txt_glyph_cache_t cache; +#endif + +#if LVGL_VERSION_MAJOR >= 8 +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 = 31, + .bpp = 1, + .kern_classes = 0, + .bitmap_format = 0, +#if LVGL_VERSION_MAJOR == 8 + .cache = &cache +#endif +}; + + + +/*----------------- + * PUBLIC FONT + *----------------*/ + +/*Initialize a public general font descriptor*/ +#if LVGL_VERSION_MAJOR >= 8 +const lv_font_t ui_font_fa = { +#else +lv_font_t ui_font_fa = { +#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 = 20, /*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` */ +#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 + .fallback = NULL, +#endif + .user_data = NULL, +}; + + + +#endif /*#if UI_FONT_FA*/ + diff --git a/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c b/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c new file mode 100644 index 0000000..164f507 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c @@ -0,0 +1,136 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include "../ui.h" + +#ifndef LV_ATTRIBUTE_MEM_ALIGN + #define LV_ATTRIBUTE_MEM_ALIGN +#endif + +// IMAGE DATA: assets/Logo_80x44.png +const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_logo_80x44_png_data[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0xFD,0x23,0xFD,0x45,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xE4,0xFB,0x40,0xFC,0xA0,0xFC,0x47,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0xFB,0x22,0xFB,0xA0,0xFB,0x00,0xFC,0x80,0xFC,0xCA,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFD,0x23,0xFD,0x43,0xFD,0x43,0xFD,0x4D,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xFA,0xA1,0xFA,0x20,0xFB,0xA0,0xFB,0xE0,0xFB,0x40,0xFC,0xAC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFD,0x00,0xFD,0x00,0xFD,0x20,0xFD,0xEF,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xFC,0xC3,0xF9,0x01,0xFA,0x81,0xFA,0x20,0xFB,0x80,0xFB,0xC0,0xFB,0x00,0xFC,0x87,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0xFC,0xA0,0xFC,0xA0,0xFC,0xE0,0xFC,0xAE,0xFD,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xFA,0x02,0xF9,0x62,0xF9,0xE1,0xF9,0x80,0xFA, + 0x00,0xFB,0x60,0xFB,0xA0,0xFB,0xE0,0xFB,0x64,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0xFC,0x81,0xFC,0x81,0xFC,0xC1,0xFC,0x8F,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0xF9,0x63,0xF8,0xE2,0xF8,0x62,0xF9,0xC1,0xF9,0x60,0xFA,0xE0,0xFA,0x80,0xFB,0xC0,0xFB,0x40,0xFC,0x81,0xFC,0x00,0x00,0xCF,0xFD,0xC7,0xFD,0xE4,0xFD,0x8A,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0xFA,0x84,0xF8,0x03,0xF8,0x63,0xF8,0xE2,0xF8,0x42,0xF9,0xC1,0xF9,0x40,0xFA,0xC0,0xFA,0x60,0xFB,0xA0,0xFB,0x20,0xFC,0x80,0xFC,0xE0,0xFC,0x20,0xFD,0x60,0xFD,0xC1,0xFD,0xC9,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xFD,0xA1,0xFD,0xA1,0xFD,0xA4,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xFC,0xE7,0xF8,0x04,0xF8,0x04,0xF8,0x03,0xF8,0x43,0xF8,0xC2,0xF8,0x41,0xF9,0xC0,0xF9,0x20,0xFA,0x80,0xFA,0xE0,0xFA,0x00,0xFB,0x60,0xFB,0xA0,0xFB,0xA0,0xFC,0xE0,0xFC,0x20,0xFD,0xA1,0xFD,0x0B,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xA6,0xFD,0x80,0xFD,0x60,0xFD,0x63,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xF9,0xAB,0xF8,0x28,0xF8,0x06,0xF8,0x05,0xF8,0x05,0xF8,0x04,0xF8,0x43,0xF8,0xA2,0xF8,0x21,0xF9,0xA0,0xF9,0x00,0xFA, + 0x60,0xFA,0xA0,0xFA,0xC0,0xFA,0x00,0xFB,0x40,0xFB,0x60,0xFC,0xC0,0xFC,0x00,0xFD,0x81,0xFD,0x4D,0xFE,0x00,0x00,0x00,0x00,0x2A,0xFE,0x25,0xFE,0x25,0xFE,0x25,0xFE,0x6D,0xFE,0x87,0xFD,0x41,0xFD,0x21,0xFD,0x23,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xBC,0x5F,0xB3,0x1F,0xC3,0xBF,0xCB,0x3F,0xDC,0x9F,0xF4,0x3D,0xFC,0x7B,0xFB,0x97,0xFA, + 0xD4,0xF9,0x31,0xF9,0xAF,0xF8,0x2E,0xF8,0x0C,0xF8,0x0A,0xF8,0x09,0xF8,0x07,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x43,0xF8,0xA2,0xF8,0x21,0xF9,0xA0,0xF9,0x00,0xFA,0x40,0xFA,0x80,0xFA,0xA0,0xFA,0xC0,0xFA,0xE0,0xFA,0x20,0xFC,0xA0,0xFC,0xE0,0xFC,0x40,0xFD,0x62,0xFC,0xA2,0xFB,0xC2,0xFB,0x81,0xFD,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x67,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,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,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xC3,0xBF,0xC2,0x7F,0xCA,0x1F,0xE2,0x7D,0xF9,0xD9,0xF8,0x76,0xF8,0x53,0xF8,0x31,0xF8,0x0F,0xF8,0x2E,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x62,0xF8,0xE1,0xF8,0x20,0xFA,0x60,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x40,0xFA,0x60,0xFA,0x40,0xFB,0x80,0xFC,0xC0,0xFC,0x00,0xFD,0x20,0xFC,0xA0,0xFB,0xA0,0xFB,0x40,0xFD,0x40,0xFE,0x40,0xFE,0x40,0xFE,0x87,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x7F,0xCB,0x1F,0xE2,0x7E,0xF9,0xFA,0xF8,0x96,0xF8,0x74,0xF8,0x31,0xF8,0x30,0xF8,0x2E,0xF8,0x2D,0xF8,0x2B,0xF8,0x0A,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x61,0xF8,0xA1,0xF8,0x00,0xF9,0xC0,0xF9,0xA0,0xFA,0xC0,0xFA,0x80,0xFA,0x00,0xFA,0x20,0xFA,0x60,0xFA,0x20,0xFC,0x80,0xFC,0xA0,0xFC,0xE0,0xFB,0xA0,0xFB,0xC0,0xFB,0x40,0xFD,0x40,0xFE,0x40,0xFE,0x40,0xFE, + 0x87,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xFD,0x03,0xFD,0x03,0xFD,0xE3,0xFC,0x30,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xEF,0x1F,0xDF,0x7F,0xEF,0x3F,0xDF,0x7F,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xFE,0xFE,0xF9,0x1B,0xF9,0xB7,0xF8,0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x2A,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x41,0xF8,0x00,0xF9,0x80,0xF9,0xC0,0xF9, + 0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x00,0xFA,0x40,0xFA,0x20,0xFB,0x20,0xFB,0x40,0xFB,0x20,0xFC,0xA0,0xFC,0x00,0xFD,0x00,0xFD,0xC0,0xFC,0xE0,0xFC,0x40,0xFD,0xC7,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFC,0xE0,0xFC,0xC0,0xFC,0xC0,0xFC,0x0C,0xFD,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xDF,0xFF,0x7F,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0xDF,0xFF,0xBF,0xF7,0x9F,0xF7,0x9F,0xF7,0xDF,0xFF,0xDE,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xF9,0xD8,0xF8, + 0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x09,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0xE5,0xFA,0x44,0xFA,0x41,0xF8,0x40,0xF9,0xE0,0xF9,0x44,0xFB,0x85,0xFC,0x60,0xF9,0x80,0xF9,0xA0,0xF9,0xC0,0xF9,0x87,0xFE,0x24,0xFD,0x60,0xFA,0xA0,0xFA,0xE0,0xFB,0xA0,0xFC,0xE0,0xFC,0xC0,0xFC,0xA0,0xFC,0xC0,0xFC,0x20,0xFD,0x84,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0xFC,0xA0,0xFC,0x80,0xFC,0x80,0xFC,0xCC,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xEF,0xDF,0xFF,0xDF,0xFF,0x5F,0xD7,0x7F,0xDF,0xBF,0xE7, + 0xBF,0xE7,0xBF,0xE7,0xBF,0xE7,0x9F,0xE7,0x7F,0xD7,0xDF,0xB6,0xBF,0xF7,0x9E,0xFF,0x9F,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x98,0xF9,0x75,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x0A,0xF8,0x08,0xF8,0x07,0xF8,0x06,0xF8,0x68,0xFD,0x89,0xFF,0x83,0xFA,0x20,0xF9,0xA0,0xF9,0xE4,0xFB,0xE9,0xFF,0x25,0xFD,0x60,0xF9,0x80,0xF9,0x80,0xF9,0xA6,0xFE,0xC7,0xFF,0x82,0xFB,0xA0,0xFA,0xC0,0xFB,0x60,0xFC,0x80,0xFC,0xA0,0xFC,0xC0,0xFC,0xE0,0xFC,0x20,0xFD,0x84,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,0xFC,0x62,0xFC,0x62,0xFC,0x42,0xFC,0x51,0xFD,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,0xDF,0xFF,0xDF,0xFF,0xBF,0xFF,0xBF,0xFF,0x3F,0xD7,0xBF,0xE7,0xBF,0xEF,0x9F,0xE7,0x5F,0xD7,0x3F,0xE7,0x5F,0xF7,0xFF,0xD6,0xFF,0xCE,0x5F,0xD7,0x7F,0xE7,0x7F,0xE7,0x1F,0xC7,0xBF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x7E,0xFF,0xF5,0xF8,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0x2D,0xF8,0x2C,0xF8,0x0A,0xF8,0x08,0xF8,0x27,0xF8,0x26,0xF8,0x47,0xFD,0xE7,0xFF,0xE4,0xFD,0x80,0xF8,0x60,0xF8,0x63,0xFB,0xE8,0xFF,0x06,0xFF,0x40,0xF9,0x40,0xF9,0x40,0xF9,0xC6,0xFE,0xE7,0xFF,0x24,0xFD,0xE0,0xFA,0xE0,0xFA,0x20,0xFB,0x80,0xFB,0x20,0xFC,0x00,0xFD,0x20,0xFD,0x60,0xFD, + 0x82,0xFD,0xC2,0xFD,0xE2,0xFD,0x22,0xFE,0x49,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,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBF,0xF7,0x5F,0xD7,0x7F,0xDF,0x3F,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x9F,0xEF,0xDF,0xBE,0xFF,0x64,0xFF,0xC6,0x7F,0xDF,0x7F,0xD7,0x9F,0xF7,0xDE,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0xFC,0x74,0xF8,0x31,0xF8,0x10,0xF8,0x0E,0xF8,0x2C,0xF8,0x0A,0xF8,0x09,0xF8,0x07,0xF8,0x26,0xF8,0x65,0xFE,0xC5,0xFF,0x64,0xFE,0x60,0xF8,0x40,0xF8,0x04,0xFD, + 0xE6,0xFF,0x26,0xFF,0x40,0xF9,0x20,0xF9,0x41,0xFA,0xA6,0xFF,0xE7,0xFF,0xA3,0xFC,0xE0,0xFA,0xC0,0xFA,0x00,0xFB,0x40,0xFB,0x20,0xFC,0x00,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x80,0xFD,0xA0,0xFD,0x00,0xFE,0x47,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0x9F,0xEF,0x5F,0xCF,0x7F,0xD7,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0x7F,0xEF,0xBF,0xAE,0x3F,0x5D,0x3F,0x2C,0x7F,0x6B,0xBF,0xE7,0x7F,0xD7,0x5F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, + 0xFF,0xFF,0xB5,0xF9,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x47,0xFA,0x45,0xFF,0xA5,0xFF,0x03,0xFD,0x60,0xF8,0xE0,0xF8,0x04,0xFF,0xC5,0xFF,0x24,0xFE,0x20,0xF9,0xE0,0xF8,0xA4,0xFD,0xA5,0xFF,0x45,0xFF,0x00,0xFA,0x20,0xFA,0xC0,0xFA,0x40,0xFB,0x80,0xFB,0xE0,0xFB,0x60,0xFC,0xA0,0xFC,0xC0,0xFC,0x20,0xFD,0x40,0xFD,0x80,0xFD,0xC0,0xFD,0x27,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xEF,0xBF,0xFF,0x1F,0xC7,0x5F,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xBF,0xF7,0x5F,0xD7,0x3F,0x8E,0xDF,0x24,0xDF,0x1B,0xDF,0x22,0x9F,0x31,0xFF,0xEF,0x3F,0xCF,0xBF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1B,0xFE,0x74,0xF8,0x32,0xF8,0x30,0xF8,0x0E,0xF8,0x0B,0xF8,0x0A,0xF8,0x08,0xF8,0x64,0xFE,0x43,0xFF,0xE3,0xFE,0xA0,0xF8,0x40,0xF8,0x62,0xFD,0x63,0xFF,0x44,0xFF,0x41,0xFA,0x00,0xF9,0x61,0xFB,0x64,0xFF,0x84,0xFF,0x62,0xFC,0x80,0xF9,0xA0,0xF9,0xE0,0xFA,0xA0,0xFB,0xE0,0xFB,0xE0,0xFB,0xA0,0xFB,0x00,0xFC,0x60,0xFC,0x00,0xFD,0x20,0xFD,0x60,0xFD,0xA0,0xFD,0x07,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFB,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA, + 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0xDF,0xB6,0x3F,0xCF,0x3F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xBF,0xF7,0x3F,0x5C,0x9F,0x23,0xDF,0x12,0x3F,0x12,0x1F,0x40,0x00,0xF8,0x3F,0xD7,0x9F,0xAE,0x7E,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0xF9,0x33,0xF8,0x31,0xF8,0x2F,0xF8,0x2C,0xF8,0x0A,0xF8,0x66,0xFD,0x22,0xFF,0x22,0xFF,0x41,0xFC,0x41,0xF8,0x21,0xFB,0x03,0xFF,0x23,0xFF,0x42,0xFD,0xC0,0xF8,0xE0,0xF8,0x42,0xFE,0x63,0xFF,0x82,0xFE,0x00,0xF9,0x60,0xF9,0x80,0xF9,0xE0,0xFA,0x80,0xFB,0xC0,0xFB,0x40,0xFC,0x60,0xFD,0xA0,0xFD,0xC0,0xFD, + 0x41,0xFE,0x81,0xFE,0xA2,0xFE,0xC1,0xFE,0x82,0xFE,0x63,0xFE,0x83,0xFE,0x23,0xFE,0x02,0xFA,0x02,0xFA,0xE2,0xF9,0x82,0xF9,0x46,0xFA,0x08,0xFB,0xE8,0xFA,0xE8,0xFA,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xE7,0x9F,0xF7,0x7F,0xD7,0xBF,0xB6,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xE7,0x3F,0xDF,0x3F,0xEF,0x5F,0xFF,0xBF,0x2A,0x1F,0x42,0x1F,0xF8,0x1F,0x50,0x5F,0xAD,0x3F,0xCF,0xBF,0xCE,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x17,0xFB,0x53,0xF8,0x51,0xF8,0x2E,0xF8,0x2A,0xF8,0x27,0xF9,0x02,0xFF,0x01,0xFF,0x41,0xFE,0x21,0xF8,0x40,0xF8,0xC1,0xFD,0x02,0xFF,0x82,0xFE, + 0xA0,0xF8,0xE0,0xF8,0x00,0xFB,0x02,0xFF,0x22,0xFF,0x21,0xFC,0xE0,0xF9,0x20,0xFA,0x40,0xFA,0x80,0xFA,0xC0,0xFA,0x00,0xFB,0x60,0xFC,0xC0,0xFE,0xC0,0xFE,0xE0,0xFE,0x61,0xFF,0xE2,0xFF,0xE2,0xFF,0xE2,0xFF,0x81,0xFE,0x40,0xFE,0x40,0xFE,0xE0,0xFD,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x80,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xBE,0xFF,0xDF,0xF7,0xFF,0xBE,0x7F,0xCF,0x9F,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0x7F,0xDF,0xFF,0x64,0x3F,0x11,0x9F,0xE6,0xFD,0xFE,0x1F,0xF8,0x1F,0x30,0x1F,0x18,0x1F,0x18,0x7F,0xDF,0x9F,0xB6,0x9F,0xF7,0xFF,0xFF,0xFF,0xFF, + 0xDF,0xFF,0xFF,0xFF,0x7E,0xFF,0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2C,0xF8,0x66,0xFD,0xE1,0xFE,0xE1,0xFE,0x40,0xFC,0x80,0xF8,0xA0,0xF8,0x61,0xFE,0xC1,0xFE,0xC1,0xFD,0xC0,0xF8,0xE0,0xF8,0xE0,0xFB,0xC1,0xFE,0xE1,0xFE,0x60,0xFA,0x40,0xFA,0x80,0xFA,0xA0,0xFA,0x60,0xFA,0x60,0xFA,0x80,0xFA,0x40,0xFC,0xC0,0xFE,0xC0,0xFE,0xC0,0xFE,0x61,0xFF,0xC2,0xFF,0xC2,0xFF,0xC2,0xFF,0x61,0xFE,0x20,0xFE,0x40,0xFE,0xC0,0xFD,0x00,0xFA,0x00,0xFA,0xC0,0xF9,0x80,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x7F,0xF7,0x9F,0xF7,0x1F,0xCF,0x3F,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xF7, + 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x1F,0x63,0x1F,0x30,0x1F,0x08,0xBF,0xC5,0x7F,0x93,0x1F,0x10,0x1F,0x08,0x5F,0x08,0x3F,0xCF,0x9F,0xDF,0xBF,0xFF,0x3F,0xDF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0xF8,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0xE6,0xFD,0xC2,0xFE,0xA1,0xFE,0x21,0xFC,0x60,0xF8,0xA0,0xF8,0x21,0xFE,0xA1,0xFE,0xE1,0xFD,0xC0,0xF8,0xE0,0xF8,0x20,0xFB,0xA1,0xFE,0xA1,0xFE,0xC0,0xFC,0x20,0xFA,0x60,0xFA,0x80,0xFA,0x60,0xFA,0x40,0xFA,0x80,0xFA,0x00,0xFC,0x40,0xFE,0x40,0xFE,0x40,0xFE,0xC1,0xFE,0x22,0xFF,0x02,0xFF,0x22,0xFF,0x21,0xFE,0xE0,0xFD,0x00,0xFE,0x80,0xFD,0xE0,0xF9,0xC0,0xF9,0xA0,0xF9,0x60,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00, + 0x5D,0xFC,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x1F,0x74,0xBF,0xF7,0x5F,0xD7,0xDF,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFF,0x21,0x5F,0x11,0x7F,0x08,0x7F,0x29,0xBF,0x94,0x7F,0x08,0x9F,0x10,0x1F,0x11,0x5F,0x4A,0xBF,0xDF,0x9F,0xF7,0x5F,0xEF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x57,0xF9,0x54,0xF8,0x53,0xF8,0x50,0xF8,0x49,0xFC,0xA1,0xFE,0x81,0xFE,0xA1,0xFD,0x40,0xF8,0x41,0xF8,0x61,0xFD,0x60,0xFE,0x41,0xFE,0x40,0xFB,0xE0,0xF8,0x00,0xF9,0x01,0xFE,0x61,0xFE,0x00,0xFE,0xA0,0xFA,0x80,0xF9,0x80,0xF9,0xA0,0xF9,0xC0,0xFA,0x00,0xFB,0x20,0xFB,0xE0,0xFB,0xA0,0xFC,0xC0,0xFC, + 0x00,0xFD,0x20,0xFD,0x40,0xFD,0x60,0xFD,0xA0,0xFD,0xC0,0xFD,0xC1,0xFD,0x44,0xFD,0x04,0xFA,0xE4,0xF9,0xE4,0xF9,0xC5,0xF9,0x4C,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x3D,0xFC,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x3F,0xBE,0xBF,0xF7,0x1F,0xCF,0xDF,0x8D,0x9F,0xB6,0x7F,0x9E,0x5F,0x8E,0x9F,0x6D,0xBF,0xF7,0xBF,0x9E,0xBF,0xAE,0x3F,0xE7,0xBF,0xF7,0xBF,0xF7,0xFF,0x08,0x9F,0x09,0xDF,0x09,0x1F,0x11,0x5F,0x09,0xBF,0x63,0x1F,0x11,0x7F,0x11,0xDF,0x19,0x9F,0x19,0xBF,0xDF,0x5F,0xE7,0xBF,0xF7,0xFE,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x78,0xF9,0x75,0xF8,0x54,0xF8,0x52,0xF8,0x4F,0xF8,0x23,0xFE,0x20,0xFE,0x00,0xFE,0x41,0xFC,0x01,0xF8,0xE1,0xF9,0x01,0xFE,0x20,0xFE, + 0xC0,0xFD,0x20,0xFA,0x00,0xF9,0x81,0xFB,0x21,0xFE,0x00,0xFE,0x81,0xFD,0x80,0xF9,0x20,0xF9,0x40,0xF9,0xC0,0xFA,0x20,0xFB,0x20,0xFB,0xA0,0xFB,0x60,0xFC,0xA0,0xFC,0xE0,0xFC,0x00,0xFD,0x40,0xFD,0x60,0xFD,0x80,0xFD,0xA0,0xFD,0xC1,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC9,0xFB,0x62,0xFB,0x61,0xFB,0x44,0xFB,0x00,0x00,0xFD,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x5F,0xBE,0x9F,0xFF,0x3F,0xCF,0xBF,0x85,0xBF,0x65,0x1F,0x66,0xDF,0x44,0x9F,0x2B,0x9F,0xEF,0x9F,0x12,0x1F,0x00,0x7F,0x62,0x1F,0x20,0x5F,0x10,0x5F,0x11,0x5F,0x12,0x5F,0x12,0x3F,0x1A,0x7F,0x1A,0xBF,0x53,0x3F,0x1A,0x5F,0x22,0x5F,0x2A,0xDF,0x21,0xBF,0xE7,0x5F,0xDF,0x9F,0xF7,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7A,0xF9,0x97,0xF8,0x75,0xF8,0x53,0xF8,0x51,0xF8,0x4E,0xFA,0xA2,0xFD,0x80,0xFD,0x40,0xFD,0xE1,0xF9,0x00,0xF8,0xA2,0xFB,0xA0,0xFD,0xC0,0xFD,0xE0,0xFC,0x00,0xF9,0x01,0xF8,0x21,0xFC,0xA0,0xFD,0xA0,0xFD,0x60,0xFC,0x20,0xF9,0x40,0xF9,0x60,0xFA,0xA0,0xFA,0xA0,0xFA,0xE0,0xFA,0x60,0xFB,0xC0,0xFB,0x40,0xFC,0x80,0xFC,0xA0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0x20,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xFB,0x20,0xFB,0x20,0xFB,0x43,0xFB,0x00,0x00,0x7C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x1F,0x53,0x5F,0xF7,0xFF,0xBE,0x9F,0xA6,0x5F,0x34,0x7F,0x24,0x1F,0x23,0x9F,0x19,0x3D,0xFF,0x1F,0x00,0x1F,0x00,0x1F,0x40, + 0x1F,0x10,0xFF,0x10,0x5F,0x12,0xDF,0x12,0x7F,0x12,0xDF,0x1A,0x1F,0x2B,0xDF,0x53,0xFF,0x2A,0xFF,0x2A,0xFF,0x32,0x7F,0x22,0xBF,0xE7,0x9F,0xEF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7B,0xF9,0x98,0xF8,0x76,0xF8,0x75,0xF8,0x53,0xF8,0x51,0xF8,0x4B,0xFB,0x00,0xFD,0x20,0xFD,0x81,0xFC,0x02,0xF8,0x03,0xF8,0x81,0xFC,0x60,0xFD,0x60,0xFD,0x61,0xFB,0x01,0xF8,0x01,0xF8,0xA0,0xFC,0x60,0xFD,0x40,0xFD,0x60,0xF9,0x20,0xF9,0x40,0xF9,0x60,0xF9,0xA0,0xF9,0xE0,0xF9,0x20,0xFA,0xC0,0xFA,0xC0,0xFB,0x00,0xFC,0x40,0xFC,0x60,0xFC,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0xFB,0x01,0xFB,0x01,0xFB,0x24,0xFB,0x00,0x00, + 0x9C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0xDF,0xDE,0x5F,0xEF,0xFF,0xBE,0x3F,0xC7,0x3F,0x33,0x5F,0x22,0x1F,0x41,0x1F,0xF8,0x5B,0xFE,0xFF,0xFD,0x1F,0x00,0x1F,0xF8,0xBF,0x10,0xDF,0x11,0x9F,0x12,0xDF,0x12,0xDF,0x22,0x1F,0x23,0xFF,0x4B,0x7F,0x43,0x5F,0x33,0x5F,0x3B,0x3F,0x3B,0x1F,0xCF,0xBF,0xE7,0xDF,0xFF,0xFF,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xF9,0xDA,0xF8,0xB8,0xF8,0x76,0xF8,0x74,0xF8,0x51,0xF8,0x2F,0xF8,0x83,0xFC,0xE0,0xFC,0xA0,0xFC,0x03,0xF8,0x03,0xF8,0x43,0xF8,0x00,0xFD,0x00,0xFD,0x60,0xFC,0x01,0xF8,0x01,0xF8,0x61,0xFA,0x20,0xFD,0x20,0xFD,0xA0,0xFA,0x00,0xF9,0x20,0xF9,0x60,0xF9,0x80,0xF9,0xC0,0xF9,0x00,0xFA,0xA0,0xFA, + 0xA0,0xFB,0xE0,0xFB,0x20,0xFC,0x40,0xFC,0x60,0xFC,0x80,0xFC,0x80,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0x7F,0xEF,0x5F,0xA6,0x3F,0xC7,0xBF,0x1A,0xBF,0xAA,0x00,0xF8,0x00,0xF8,0x1F,0xF8,0xBE,0xFE,0x1F,0x6A,0x7F,0x08,0xFF,0x28,0x9F,0x21,0x1F,0x22,0xFF,0x2A,0x7F,0x2B,0xFF,0x43,0x3F,0x54,0x9F,0x43,0x9F,0x43,0x7F,0x43,0x1F,0x43,0x9F,0xE7,0x7F,0xDF,0xBF,0xFF,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xFD,0x1E,0xF9,0xDC,0xF8,0xBA,0xF8,0x97,0xF8,0x75,0xF8,0x73,0xF8,0x70,0xF8,0x06,0xFC,0xA0,0xFC,0x60,0xFC,0x03,0xF8,0x03,0xF8,0x03,0xF8, + 0x80,0xFC,0xC0,0xFC,0x20,0xFC,0x01,0xF8,0x01,0xF8,0x81,0xF8,0xE0,0xFC,0xE0,0xFC,0x80,0xFA,0xE0,0xF8,0x00,0xF9,0x40,0xF9,0xC0,0xF9,0x00,0xFB,0x20,0xFB,0x40,0xFB,0x80,0xFB,0xA0,0xFB,0xE1,0xFB,0x43,0xFC,0x63,0xFC,0x63,0xFC,0x44,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xFB,0x1C,0xFC,0xDF,0xFF,0xFF,0xFF,0xDF,0xFF,0x5F,0xE7,0xFF,0xE6,0x1F,0xBF,0xDF,0x8D,0xBF,0x52,0x00,0xF8,0x1F,0xF8,0x1F,0x20,0xDF,0x51,0xFF,0xEC,0x3F,0xAB,0x9F,0x39,0x5F,0x32,0xDF,0x32,0x3F,0x3B,0x3F,0x64,0x5F,0x64,0xBF,0x53,0xDF,0x53,0x9F,0x53,0x7F,0x53,0x5F,0x3B,0xDF,0xEF,0x3F,0xCF,0x9F,0xF7,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x3F,0xF9,0x1D,0xF9,0xFB,0xF8,0xB9,0xF8,0x97,0xF8,0x94,0xF8,0x71,0xF8,0xA6,0xFB,0x40,0xFC,0x00,0xFC,0x04,0xF8,0x05,0xF8,0x04,0xF8,0x60,0xFC,0x80,0xFC,0xA0,0xFB,0x01,0xF8,0x01,0xF8,0x61,0xF9,0xA0,0xFC,0x80,0xFC,0xE0,0xF8,0x20,0xF9,0x80,0xF9,0xC0,0xF9,0x20,0xFA,0x20,0xFB,0x40,0xFB,0x40,0xFB,0x60,0xFB,0x80,0xFB,0xC2,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xF8,0x60,0xF8,0x60,0xF8,0x60,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0xFB,0xDC,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x5F,0xF7,0x9F,0xFF,0x7F,0xA6,0xFF,0xBE,0x9F,0x1B,0x1F,0x80,0x1F,0x48,0x1F,0x68,0x7F,0x90,0x7F,0x88,0x1F,0xBB, + 0xFF,0xAB,0xDF,0x93,0x1F,0x84,0x3F,0x84,0x9F,0x6B,0xBF,0x73,0x1F,0x7C,0x3F,0x84,0xDF,0x7B,0x3F,0x63,0xDF,0xEF,0xBF,0xEF,0xBF,0xF7,0xBF,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xDA,0x7F,0xF9,0x3E,0xF9,0x1D,0xF9,0xDB,0xF8,0xB9,0xF8,0x96,0xF8,0x73,0xF8,0xA4,0xFB,0x00,0xFC,0x82,0xFB,0x06,0xF8,0x06,0xF8,0x25,0xF9,0x20,0xFC,0x40,0xFC,0x81,0xF9,0x01,0xF8,0x01,0xF8,0x01,0xFB,0x60,0xFC,0xE0,0xFB,0x80,0xF8,0x00,0xFA,0xA0,0xFA,0xC0,0xFA,0xA0,0xFA,0xE0,0xFA,0x00,0xFB,0x00,0xFB,0x20,0xFB,0x20,0xFB,0x42,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xF8,0x20,0xF8,0x20,0xF8,0x40,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7E,0xFC,0xBD,0xFB,0x7F,0xFE,0xFF,0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xE6,0x7F,0xF7,0xFF,0xBE,0x1F,0xBF,0x1F,0x23,0xBF,0xD8,0x7F,0xF0,0xBF,0xE8,0x5F,0xF1,0x7F,0xF1,0x1F,0xE2,0x1F,0xD2,0x7F,0xBA,0xDF,0xB2,0x3F,0xA3,0x9F,0xA3,0x3F,0xCE,0xDF,0xFF,0xBF,0x9C,0xBF,0xEF,0xFF,0xF7,0x5F,0xDF,0xBF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xCB,0x1F,0xDA,0xBF,0xF1,0x7F,0xF9,0x3E,0xF9,0xFC,0xF8,0xDA,0xF8,0xD8,0xF8,0xB1,0xF9,0xC0,0xFB,0xC0,0xFB,0xA6,0xF9,0x08,0xF8,0x07,0xF8,0x23,0xFB,0xE0,0xFB,0x60,0xFB,0x02,0xF8,0x01,0xF8,0x01,0xF8,0x80,0xFB,0xE0,0xFB,0xE0,0xF9,0x60,0xF8,0x00,0xFA,0xA0,0xFA,0xC0,0xFA,0x60,0xFA,0x80,0xF9,0x80,0xF9,0x80,0xF9, + 0x80,0xF9,0x60,0xF9,0x41,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xF8,0x00,0xF8,0x00,0xF8,0x20,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBE,0xFB,0xFE,0xFB,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xDF,0xFF,0x7F,0xF7,0xBF,0xCE,0x1F,0xC7,0xBF,0xB6,0xBF,0x3A,0x3E,0xF9,0xBB,0xF8,0x1A,0xF9,0x3B,0xF9,0xBC,0xF9,0xFE,0xF9,0x5F,0xF2,0xBF,0xEA,0xFF,0xD2,0x3F,0xCB,0xFF,0xCC,0x5F,0xEF,0x9F,0xE7,0xFF,0xFF,0x9F,0xE7,0xDF,0xFF,0x3F,0xE7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x9F,0xBA,0x3F,0xD2,0xFF,0xE1,0x7F,0xF1,0x5F,0xF9,0x3E,0xF9,0x1C,0xF9,0xD9,0xF8,0x47,0xFB,0xA0,0xFB,0xC6,0xFA,0x2A,0xF8,0x09,0xF8,0x27,0xF9,0x80,0xFB, + 0x60,0xFB,0x82,0xF8,0x02,0xF8,0x02,0xF8,0x20,0xFA,0x40,0xFB,0x60,0xFA,0x41,0xF8,0x41,0xF8,0xC0,0xF9,0x60,0xFA,0x80,0xFA,0x40,0xFA,0x00,0xFA,0x00,0xFA,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x62,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xF9,0xA6,0xF9,0xA6,0xF9,0xE7,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFC,0xBF,0xFB,0x3F,0xFD,0xDF,0xFF,0xDF,0xFF,0xDE,0xFF,0x7F,0xE7,0xBF,0xFF,0xFF,0xD6,0x1F,0xC7,0xFF,0xC6,0x3F,0x5D,0x3F,0xBA,0x39,0xF9,0xF8,0xF8,0x19,0xF9,0x7B,0xF9,0xDD,0xF9,0x5E,0xFA,0xBF,0xEA,0xDF,0xDA,0x5F,0x73,0xDF,0xF7,0xFF,0xF7,0x9F,0xE7,0xDF,0xFF,0x5F,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xA2,0x7F,0xB2,0x3F,0xC2,0xFF,0xD9,0xDF,0xE9,0x7F,0xF9,0x5F,0xF9,0x3D,0xF9,0x58,0xF9,0x09,0xFB,0xC9,0xFA,0x2E,0xF8,0x0C,0xF8,0x0A,0xF8,0x67,0xF9,0x84,0xFA,0x44,0xF9,0x03,0xF8,0x02,0xF8,0x02,0xF8,0x01,0xF8,0x61,0xF8,0x21,0xF8,0x42,0xF8,0x42,0xF8,0x41,0xF9,0xE0,0xF9,0x40,0xFA,0x80,0xFA,0xC0,0xFA,0x00,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xFA,0x08,0xFA,0xE7,0xF9,0x69,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0xF3,0xBF,0xF3,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x5F,0xE7,0xBF,0xFF,0xBF,0xD6,0xBF,0xBE,0x1F,0xCF,0xFF,0xC6,0xBF,0x8D,0x5F,0x1B, + 0x9F,0xAA,0x1F,0xFA,0x7F,0xEA,0xFF,0x42,0xDF,0xBE,0xFF,0xF7,0xFF,0xF7,0xDF,0xF7,0xBF,0xE7,0xDF,0xF7,0x7F,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x9C,0xBF,0x9A,0x7F,0xAA,0x3F,0xBA,0x1F,0xD2,0xFF,0xE9,0xBF,0xF1,0x7F,0xF9,0x5E,0xF9,0x1B,0xF9,0xB7,0xF8,0x53,0xF8,0x30,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x03,0xF8,0x03,0xF8,0x02,0xF8,0x22,0xF8,0x21,0xF8,0x22,0xF8,0x22,0xF8,0x40,0xF9,0xC0,0xF9,0x00,0xFA,0x60,0xFA,0xA0,0xFA,0xC0,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xF8,0x80,0xF8,0x80,0xF8,0xE3,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,0x7F,0xF5,0x7F,0xEB,0x7F,0xE3,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xBF,0xF7,0x1F,0xEF,0x1F,0xEF,0x7F,0xBE,0xBF,0xBE,0x3F,0xD7,0x7F,0xDF,0x7F,0xE7,0xDF,0xEF,0xDF,0xF7,0xFF,0xF7,0xFF,0xF7,0xFF,0xF7,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF,0xD6,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x8C,0x1F,0x7B,0xDF,0x92,0x7F,0xA2,0x5F,0xB2,0x3F,0xD2,0xFF,0xE9,0xDF,0xF9,0x9F,0xF9,0x7E,0xF9,0x1C,0xF9,0xD8,0xF8,0x74,0xF8,0x30,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x80,0xF8,0x80,0xF8,0x40,0xF8,0x21,0xF8,0x40,0xF8,0x60,0xF8,0x80,0xF8,0xC0,0xF8,0x21,0xF9,0x07,0xFB,0x28,0xFB,0x00,0x00, + 0x00,0x00,0x00,0x00,0x60,0xF8,0x60,0xF8,0x60,0xF8,0xE3,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,0x3F,0xEC,0x5F,0xE3,0x7F,0xDB,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x8D,0x1F,0xEF,0x5F,0xEF,0x1F,0xEF,0xFF,0xCE,0x3F,0xCF,0x7F,0xE7,0x9F,0xE7,0x9F,0xE7,0x9F,0xF7,0xBF,0xFF,0xDF,0xFF,0x7F,0xE7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7C,0x5F,0x5B,0x3F,0x73,0xFF,0x8A,0x9F,0x9A,0x5F,0xB2,0x3F,0xCA,0x1F,0xE2,0x1F,0xFA,0xDF,0xF9,0x7E,0xF9,0x3B,0xF9,0xF8,0xF8,0xB5,0xF8,0x51,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8, + 0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x80,0xF8,0xA0,0xF8,0x40,0xF8,0x20,0xF8,0x40,0xF8,0x60,0xF8,0x80,0xF8,0xA0,0xF8,0x23,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xF8,0x20,0xF8,0x20,0xF8,0xC2,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,0x5F,0xDC,0x1F,0xCB,0x3F,0xC3,0xBF,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x5F,0xEF,0x5F,0xB6,0x5F,0xEF,0xBF,0xFF,0xBF,0xFF,0xDF,0xFF,0xDF,0xFF,0x9F,0xE7,0xBF,0x95,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x5B,0x7F,0x4B,0x7F,0x53,0x5F,0x6B, + 0x3F,0x7B,0xFF,0x9A,0x5F,0xAB,0x5F,0xC4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xFC,0xDA,0xFA,0xB6,0xF9,0xF2,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x07,0xF8,0x06,0xF8,0x05,0xF8,0x24,0xF8,0x61,0xF8,0x81,0xF8,0x21,0xF8,0x20,0xF8,0x20,0xF8,0x60,0xF8,0x60,0xF8,0x60,0xF8,0x4C,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0xFB,0x6D,0xFB,0xCF,0xFB,0x30,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,0xDF,0xD4,0x1F,0xBB,0x1F,0xB3,0x1F,0xB4,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xFF,0xFF,0x9F,0x94,0x1F,0x5B,0x3F,0x4B,0x9F,0x5B,0xDF,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xF9,0xEA,0xF8,0x48,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x03,0xF8,0x02,0xF8,0x02,0xF8,0x01,0xF8,0x00,0xF8,0x20,0xF8,0x60,0xF8,0xA1,0xF8,0x8A,0xFA,0x00,0x00,0xE8,0xFA,0x63,0xFA,0x63,0xFA,0x09,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xAB,0xFF,0xA2,0x1F,0xA3,0x7F,0xAC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xAD,0xDF,0x7B,0x1F,0xE7,0xFF,0xFF,0x5F,0xEF,0x1F,0xA5,0x1F,0x94,0x9F,0x9B,0x5F,0xAB,0x5F,0xBB,0x3F,0xC3,0x9F,0xD3,0x1F,0xE4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFB,0xA8,0xF9,0xE6,0xF8,0xA4,0xF8,0x63,0xF8,0x63,0xF8,0x62,0xF8,0xA3,0xF8,0x04,0xF9,0x49,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFA,0x20,0xFA,0x40,0xFA, + 0x85,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xBC,0x3F,0x9B,0xDF,0x82,0x1F,0x73,0x9F,0x73,0xDF,0x94,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xCE,0x5F,0x6C,0xDF,0x4B,0x9F,0x43,0x7F,0x4B,0x7F,0x63,0x5F,0x6B,0x3F,0x73,0x3F,0x83,0x1F,0x93,0xDF,0xA2,0x9F,0xB2,0x5F,0xC2,0x3F,0xD2,0x3F,0xE2,0x3F,0xEA,0x7F,0xFA,0x7D,0xFA,0x3B,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,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,0xFA,0x20,0xFA,0x20,0xFA,0x65,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDF,0xAC,0x5F,0x7B,0x3F,0x63,0x5F,0x53,0x5F,0x4B,0x5F,0x43,0x7F,0x3B,0x7F,0x3B,0x9F,0x33,0x9F,0x33,0x9F,0x2B,0x9F,0x2B,0x9F,0x2B,0x7F,0x2B,0x9F,0x2B,0x9F,0x33,0x9F,0x3B,0x7F,0x4B,0x7F,0x5B,0x7F,0x6B,0x5F,0x73,0x3F,0x83, + 0x1F,0x93,0xFF,0xA2,0xDF,0xB2,0x9F,0xC2,0x9F,0xD2,0x7F,0xE2,0x5F,0xF2,0x3E,0xFA,0xBB,0xF9,0x78,0xF9,0x56,0xF9,0xF4,0xF9,0x56,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,0xCD,0xFB,0xEE,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0x8C,0xDF,0x5B,0x7F,0x4B, + 0x7F,0x3B,0x7F,0x33,0x9F,0x2B,0x9F,0x2B,0x7F,0x2B,0x9F,0x2B,0x9F,0x2B,0x9F,0x33,0xBF,0x3B,0xDF,0x43,0x1F,0x54,0x5F,0x6C,0x3F,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + //alpha channel data: + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0xAC,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x9A,0xEF,0xFD,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xD9,0xFE,0xFE,0xFE,0x53,0x00,0x00,0x00,0x00,0x6C,0xA9,0xAA,0xAB,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xF7,0xFE,0xFE,0xFE,0xFD,0x48,0x00,0x00,0x00,0x00,0xA2,0xFE,0xFE,0xFD,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xC6,0xFE,0xFD,0xFD,0xFE,0xFE,0xFD,0x6D,0x00,0x00,0x00,0x00,0xA1,0xFE,0xFE,0xFD,0x3C,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xE4,0xFD,0xFE,0xFD, + 0xFE,0xFE,0xFE,0xFE,0xA3,0x00,0x00,0x00,0x00,0x8A,0xD6,0xD5,0xD4,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xF5,0xFE,0xFC,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xEA,0x00,0x37,0x6E,0xAA,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0xC8,0xFA,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xF9,0xFC,0xFE,0xFE,0x5D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0xD7,0xD9,0xA4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xA2,0xEC,0xFA,0xFB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x4C,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x7D,0xFE,0xFE,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,0x68,0xA9,0xDA,0xE9,0xF2,0xF8,0xFA,0xFB,0xFD,0xFD,0xFD,0xFE, + 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x44,0x00,0x00,0x55,0x87,0x88,0x8B,0x43,0x6F,0xE5,0xE3,0xA8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x62,0x67,0x53,0x41,0x37,0x37,0x42,0x53, + 0x66,0x80,0xA0,0xC1,0xD1,0xD8,0xDE,0xE5,0xEE,0xF6,0xF8,0xFA,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xD0,0xCE,0xD0,0xE4,0xFE,0xFE,0xFE,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,0x00,0x00,0x69,0x9E,0xBB, + 0xC8,0xCE,0xCC,0xC1,0xA6,0x79,0x00,0x00,0x00,0x60,0x8D,0xA1,0x96,0x90,0x98,0xA1,0xAA,0xB3,0xBE,0xC7,0xCE,0xD3,0xDA,0xE1,0xE9,0xF1,0xF7,0xF8,0xFB,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAF,0xE9,0xFC,0xFB,0xF4,0xEA,0xE8,0xEA,0xF1,0xF6,0xF7,0xEC,0xBD,0x5F,0x1E,0x1E,0x53,0x85,0x8C,0x97,0xA1,0xAB,0xB2,0xBB,0xC2,0xC8,0xCD,0xD5,0xDD,0xE4,0xED,0xF3,0xF7,0xFB,0xFD,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, + 0x71,0x00,0x00,0x00,0x7F,0xBE,0xBE,0xBF,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xE8,0xF6,0xDB,0xA8,0x69,0x2D,0x25,0x2D,0x26,0x29,0x5E,0x99,0xCE,0xEE,0xEB,0xB2,0x3C,0x1E,0x26,0x6C,0x91,0x9C,0xA7,0xAF,0xB7,0xBD,0xC3,0xCA,0xD0,0xD7,0xDE,0xE8,0xF0,0xF5,0xFA,0xFC,0xFE,0xFD, + 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x6F,0x00,0x00,0x00,0xA9,0xFE,0xFE,0xFD,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0xD8,0xF2,0xC4,0x70,0x31,0x4C,0x4D,0x4F,0x49,0x48,0x45,0x4B,0x4D,0x48,0x27,0x69,0xC2,0xE4,0xD9,0x71,0x1E,0x1E,0x64,0x97, + 0xA3,0xAC,0xB3,0xB9,0xBF,0xC6,0xCC,0xD2,0xDA,0xE3,0xED,0xF4,0xFA,0xFD,0xFE,0xFD,0xFC,0xFC,0xFD,0xFD,0xFE,0xFD,0xF6,0xF2,0xFB,0xFD,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0x9D,0x00,0x00,0x00,0xA9,0xFE,0xFE,0xFD,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xEF,0xE6,0x89,0x2C,0x4E,0x4B,0x2E,0x3F,0x4A, + 0x4F,0x4C,0x48,0x40,0x31,0x21,0x34,0x42,0x28,0x86,0xDD,0xE2,0x84,0x1E,0x1E,0x6E,0x9E,0xA8,0xAE,0xB4,0xBA,0xC0,0xC5,0xCC,0xD3,0xDC,0xEC,0xFC,0xEE,0xFA,0xFD,0xFD,0xFE,0xEC,0xF5,0xFC,0xFD,0xFD,0xFD,0xDC,0xF3,0xFC,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xA9,0x00,0x00,0x00,0x87,0xC9,0xC9,0xC7,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x99,0xEF,0xD8,0x5B,0x42,0x4B,0x34,0x52,0x58,0x41,0x2C,0x29,0x27,0x1E,0x1E,0x26,0x31,0x31,0x21,0x38,0x39,0x61,0xD3,0xDC,0x7A,0x1E,0x20,0x80,0xA1,0xA9,0xAD,0xB3,0xB9,0xBF,0xC5,0xCD,0xD4,0xE5,0xFE,0xE4,0xE8,0xFA,0xFB,0xFE,0xEF,0xDF,0xFA,0xFD,0xFD,0xFE,0xE1,0xEA,0xFC,0xFC,0xFD,0xFD,0xFC,0xFD,0xFC, + 0xE0,0xCA,0xCB,0xCC,0x5D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xE7,0xD7,0x4A,0x4B,0x3C,0x42,0x52,0x35,0x7B,0xBF,0xAA,0x95,0x6D,0x49,0x35,0x22,0x10,0x16,0x2E,0x28,0x29,0x3B,0x55,0xD2,0xD6,0x56,0x1E,0x35,0x96,0xA3,0xA8,0xAD,0xB3,0xB9,0xC0,0xC7,0xCE,0xEB,0xFE,0xE4,0xD7,0xF5,0xF7, + 0xFE,0xEE,0xD4,0xF6,0xFC,0xFE,0xFE,0xDE,0xE8,0xFC,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFB,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xF0,0xF0,0xE6,0x00,0x00,0x00,0x00,0xD1,0xE0,0x66,0x3C,0x39,0x3F,0x44,0x4B,0xD1,0xFE,0xFF,0xE6,0x95,0x66,0x43,0x2F,0x20,0x17,0x11,0x07,0x20,0x2C,0x24,0x3B,0x68,0xD4,0xB8,0x1F, + 0x1E,0x67,0x9B,0xA0,0xA7,0xAD,0xB4,0xBA,0xC1,0xCB,0xFA,0xFD,0xD1,0xD3,0xF0,0xFA,0xFD,0xDC,0xD3,0xF5,0xFB,0xFE,0xF5,0xDA,0xF0,0xFB,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFD,0xFD,0xFC,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xFE,0xFE,0xF0,0x00,0x00,0x00,0x8F,0xE9,0x9F,0x26,0x3C,0x36,0x3D,0x45,0xE9,0xFF,0xFF,0xFF,0xF1, + 0x8F,0x5A,0x38,0x26,0x1A,0x14,0x11,0x0E,0x05,0x1C,0x28,0x2E,0x2C,0x9E,0xD2,0x7B,0x1E,0x26,0x8C,0x99,0xA0,0xA6,0xAD,0xB3,0xB8,0xE9,0xFE,0xED,0xC1,0xDF,0xF6,0xFE,0xF7,0xC3,0xDE,0xF8,0xFD,0xFD,0xE5,0xE6,0xF9,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFC,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xFE,0xFE,0xF0, + 0x00,0x00,0x00,0xD2,0xD7,0x35,0x43,0x27,0x3D,0x27,0xB3,0xFD,0xFE,0xFE,0xFE,0xD1,0x9F,0x81,0x5A,0x37,0x11,0x10,0x0E,0x0B,0x04,0x01,0x20,0x21,0x35,0x3C,0xC4,0xB5,0x1E,0x1E,0x6A,0x91,0x98,0xA0,0xA4,0xA3,0xC4,0xFE,0xFB,0xB0,0xC1,0xEA,0xFE,0xFE,0xCC,0xC5,0xEC,0xFB,0xFE,0xE8,0xE0,0xF2,0xFD,0xFD,0xFE,0xFE,0xFD,0xFD,0xFD,0xFE, + 0xFE,0xFD,0xFD,0xFC,0xC4,0xB9,0xBA,0xBB,0xC1,0xC3,0xC5,0xC8,0x78,0x6C,0x6A,0x65,0x00,0x00,0x6C,0xE3,0xA1,0x28,0x33,0x38,0x24,0x7E,0xB4,0xD1,0xF0,0xEC,0xE7,0xC7,0x88,0x54,0x36,0x2B,0x2A,0x17,0x06,0x04,0x01,0x03,0x06,0x28,0x20,0x2F,0x97,0xC1,0x5F,0x1E,0x42,0x79,0x74,0x75,0x76,0x77,0xF0,0xFE,0xCE,0x99,0xC9,0xF0,0xFE,0xEF, + 0xBE,0xDA,0xF1,0xFE,0xFE,0xCF,0xEB,0xFC,0xFE,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0xA2,0xDE,0x5F,0x3C,0x24,0x35,0x1B,0x90,0x97,0x98,0x93,0xBD,0xA1,0x81,0x5A,0x32,0x1B,0x10,0x0E,0x1D,0x17,0x01,0x05,0x0A,0x09,0x20,0x22,0x38,0x62,0xBC, + 0x8B,0x1E,0x1F,0x5E,0x61,0x67,0x6D,0x9C,0xFE,0xFE,0xAE,0xB7,0xC6,0xF5,0xFE,0xDF,0xD1,0xED,0xF6,0xFE,0xFE,0xC5,0xF1,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0x7E,0x00,0x00,0x00,0x00,0x00,0xBB,0xD2,0x20,0x3C,0x2B,0x27,0x44,0x77,0x73,0x71,0x81,0x82,0x5F,0x35, + 0xC9,0xEE,0x66,0x10,0x05,0x11,0x1F,0x07,0x0B,0x13,0x1A,0x15,0x2A,0x37,0x1F,0xB4,0x9D,0x1E,0x1E,0x55,0x5E,0x61,0x66,0xA4,0xFE,0xFE,0xB4,0xB7,0xC4,0xF5,0xFE,0xE7,0xD0,0xED,0xF3,0xFE,0xFE,0xD5,0xEF,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFC,0xFE,0xFE,0xFE,0xFE,0x7F,0x00,0x00,0x00, + 0x58,0x00,0xC8,0xBE,0x10,0x39,0x2D,0x1B,0x49,0x54,0x4E,0x49,0x73,0x39,0x29,0x4E,0xF2,0xF8,0x6A,0x2A,0x18,0x14,0x1D,0x22,0x13,0x1E,0x28,0x0E,0x31,0x34,0x27,0xA5,0xAA,0x1E,0x1E,0x4D,0x5C,0x5D,0x62,0x81,0xFC,0xFE,0xD6,0xA1,0xB3,0xDF,0xFE,0xFC,0xD5,0xE0,0xE1,0xEF,0xFE,0xF8,0xE2,0xF1,0xF9,0xFC,0xFE,0xFD,0xFD,0xFD,0xFE,0xFE, + 0xFE,0xFD,0xFD,0xFD,0xFD,0xFE,0xF9,0xA7,0xA1,0x9C,0x96,0x8F,0x48,0x00,0x00,0x00,0x7C,0x00,0xCD,0xB2,0x1A,0x2F,0x2D,0x12,0x1D,0x1F,0x1D,0x1A,0x43,0x20,0x06,0x29,0x44,0x4A,0x23,0x37,0x3A,0x16,0x2F,0x32,0x20,0x2B,0x35,0x19,0x34,0x33,0x33,0x9B,0xAF,0x1F,0x1E,0x4B,0x5C,0x5D,0x61,0x62,0xCC,0xFE,0xFC,0xA9,0x9D,0xB0,0xF2,0xFE, + 0xF7,0xD8,0xD2,0xAC,0xF7,0xFE,0xF5,0xD7,0xF2,0xFA,0xFE,0xFD,0xFD,0xFD,0xFE,0xFD,0xFD,0xFD,0xFD,0xFD,0xFC,0xFD,0xF3,0x00,0x00,0x00,0x00,0x5D,0xD4,0xD5,0x95,0x00,0x97,0x00,0xCA,0xB1,0x18,0x2B,0x2B,0x11,0x15,0x19,0x17,0x12,0x2C,0x10,0x01,0x0A,0x0D,0x20,0x36,0x4D,0x4C,0x25,0x44,0x46,0x33,0x3D,0x47,0x20,0x39,0x34,0x35,0x98, + 0xAF,0x20,0x1E,0x4D,0x5E,0x60,0x63,0x64,0x69,0xE4,0xFE,0xF4,0x9F,0xAF,0xA1,0xF8,0xFE,0xF0,0xCC,0x9E,0xB4,0xFC,0xFE,0xE3,0xDF,0xF6,0xFC,0xFC,0xFC,0xFB,0xFD,0xFC,0xFD,0xFD,0xFD,0xFD,0xFC,0xFC,0xF0,0x00,0x00,0x00,0x00,0x6E,0xFE,0xFE,0xB1,0x00,0xA5,0x00,0xC0,0xB8,0x10,0x2D,0x28,0x16,0x0F,0x14,0x10,0x0A,0x1E,0x04,0x01,0x04, + 0x1A,0x31,0x4A,0x62,0x3C,0x41,0x54,0x58,0x4B,0x53,0x5D,0x1D,0x42,0x38,0x2F,0x9D,0xAC,0x1F,0x1E,0x55,0x62,0x64,0x66,0x67,0x65,0x7C,0xF7,0xFE,0xC8,0x80,0x86,0xBB,0xFE,0xFE,0xA3,0x99,0x9A,0xD2,0xFE,0xFA,0xD1,0xEA,0xF6,0xF9,0xFC,0xFB,0xFC,0xFC,0xFE,0xFD,0xFD,0xFD,0xFD,0xFD,0xF0,0x00,0x00,0x00,0x00,0x5D,0xDA,0xD9,0x99,0x00, + 0xB8,0x00,0xAE,0xC5,0x1A,0x2E,0x24,0x1E,0x0A,0x0E,0x08,0x01,0x17,0x0C,0x06,0x01,0x16,0x36,0x4A,0x3A,0x35,0x64,0x73,0x5E,0x67,0x6E,0x6B,0x22,0x48,0x3C,0x1F,0xA9,0xA2,0x1E,0x1E,0x5F,0x66,0x68,0x69,0x69,0x69,0x67,0xCC,0xFE,0xEA,0x73,0x89,0x8A,0xF5,0xFE,0xBE,0x93,0x9F,0xA7,0xFD,0xFE,0xD4,0xE1,0xF5,0xF7,0xFB,0xFC,0xFC,0xFC, + 0xFE,0xFD,0xFE,0xFE,0xFE,0xFD,0xF1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0x00,0x95,0xC8,0x5D,0x2D,0x1D,0x29,0x09,0x03,0x02,0x02,0x01,0x1F,0x0C,0x11,0x11,0x15,0x23,0x43,0x67,0x77,0x81,0x7A,0x85,0x8B,0x5F,0x3A,0x41,0x3F,0x3A,0xB1,0x8F,0x1E,0x28,0x69,0x6A,0x6C,0x6C,0x6B,0x6D,0x6C,0xB1,0xFE,0xF2,0x75,0x8A,0x8E, + 0xE5,0xFE,0xC2,0x90,0xA3,0xA2,0xFB,0xFE,0xD1,0xDF,0xF5,0xF7,0xFA,0xFD,0xFD,0xFD,0xFE,0xFD,0xE9,0xAE,0xAC,0xAA,0x9F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0x6D,0x64,0xC3,0x8E,0x21,0x20,0x2C,0x16,0x03,0x02,0x02,0x07,0x09,0x20,0x23,0x23,0x34,0x46,0x5A,0x79,0x85,0x89,0x9B,0xA2,0x97,0x22,0x50,0x2F,0x3A,0x73,0xB2, + 0x71,0x1E,0x4B,0x6C,0x6E,0x6F,0x6F,0x6E,0x70,0x70,0xB7,0xFE,0xE8,0x79,0x8C,0x92,0xE9,0xFE,0xB7,0x96,0xA9,0xAD,0xFD,0xFA,0xC5,0xE2,0xF6,0xF9,0xFB,0xFE,0xFE,0xFE,0xFE,0xFD,0xD7,0x00,0x00,0x00,0x00,0xC7,0xF6,0xF6,0xE1,0x00,0x00,0x00,0x00,0x00,0xA0,0xB0,0x20,0xB1,0xB4,0x23,0x2A,0x1E,0x28,0x09,0x02,0x07,0x0E,0x11,0x12,0x1D, + 0x31,0x41,0x55,0x66,0x6D,0x8B,0xAB,0xB2,0xB8,0x5C,0x44,0x4F,0x3B,0x20,0xA7,0xB5,0x38,0x1E,0x84,0x6E,0x70,0x71,0x72,0x72,0x73,0x76,0xD6,0xFE,0xC4,0x80,0x92,0x9D,0xFB,0xF9,0x9A,0xA1,0xAF,0xCA,0xFE,0xE3,0xC2,0xEB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFD,0xFD,0xD7,0x00,0x00,0x00,0x00,0xCE,0xFD,0xFD,0xE6,0x00,0x00,0x00,0x00,0x00, + 0x54,0xDD,0x29,0x80,0xBE,0x81,0x1F,0x28,0x28,0x24,0x08,0x0D,0x13,0x18,0x1F,0x28,0x30,0x3A,0x4D,0x65,0x81,0x9B,0xCB,0xF5,0x8B,0x3D,0x68,0x39,0x46,0x66,0xBD,0x94,0x1E,0x4E,0xA2,0x7D,0x73,0x74,0x75,0x76,0x76,0x8A,0xF9,0xF5,0x87,0x8F,0x9C,0xCD,0xFE,0xD2,0xA2,0xB1,0xB4,0xEF,0xFA,0xBC,0xCA,0xF2,0xFD,0xFE,0xFC,0xFA,0xFB,0xFD, + 0xFD,0xFC,0xD6,0x00,0x00,0x00,0x00,0xD0,0xFE,0xFD,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x93,0x29,0xB0,0xBA,0x47,0x2F,0x20,0x2D,0x20,0x09,0x14,0x23,0x2D,0x37,0x43,0x4E,0x5D,0x6F,0x86,0xA1,0xB0,0x85,0x41,0x7A,0x48,0x57,0x29,0xAD,0xB8,0x48,0x1E,0x93,0xA5,0x95,0x7A,0x78,0x79,0x7A,0x7C,0xD7,0xFE,0xB0,0x8C,0xA2,0xB0,0xF9, + 0xED,0xAA,0xB3,0xC0,0xD5,0xFC,0xCC,0xBA,0xD7,0xF2,0xFD,0xFD,0xFD,0xFC,0xFA,0xE9,0xE7,0xE6,0xC3,0x00,0x00,0x00,0x00,0x69,0x7A,0x78,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xCF,0x3C,0x65,0xBC,0xA8,0x28,0x35,0x1E,0x29,0x28,0x11,0x12,0x2A,0x42,0x58,0x64,0x70,0x79,0x79,0x63,0x20,0x5F,0x82,0x50,0x5F,0x30,0x96,0xBE,0x86,0x1E, + 0x6E,0xB1,0xA9,0xA2,0x88,0x7E,0x7D,0x7E,0x89,0xD4,0xC3,0x90,0xA2,0xAE,0xBD,0xD9,0xBE,0xBB,0xC4,0xC8,0xC9,0xCA,0xD0,0xC8,0xD1,0xEE,0xFD,0xFD,0xFD,0xFE,0xEA,0x00,0x00,0x00,0x55,0x63,0x6E,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA7,0xAB,0x1E,0x85,0xBA,0x9E,0x23,0x2E,0x20,0x24,0x2E,0x25,0x18,0x11, + 0x19,0x22,0x25,0x16,0x22,0x54,0x78,0x75,0x45,0x62,0x31,0x87,0xC2,0xA7,0x24,0x4A,0xB2,0xB4,0xAE,0xA7,0x9F,0x85,0x80,0x82,0x85,0x8C,0x96,0xA4,0xAD,0xB5,0xBB,0xC3,0xC7,0xC9,0xCB,0xCE,0xD1,0xD0,0xDE,0xCF,0xD5,0xEF,0xFE,0xFE,0xFE,0xFD,0xE8,0x00,0x00,0x00,0xF4,0xFE,0xFE,0xC2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x35,0xBD,0x8C,0x1F,0x91,0xB8,0x9F,0x36,0x25,0x2E,0x1E,0x26,0x34,0x37,0x3C,0x45,0x55,0x68,0x79,0x6A,0x43,0x51,0x56,0x28,0x99,0xC7,0xAE,0x39,0x42,0xB5,0xBD,0xB7,0xB2,0xAC,0xA6,0x97,0x83,0x85,0x8A,0x91,0x9A,0xA6,0xB1,0xBA,0xBF,0xC6,0xCB,0xCD,0xCF,0xD6,0xF2,0xF2,0xEF,0xF1,0xF6,0xF9,0xFC,0xFD,0xD5,0x6C,0x64,0x00, + 0x00,0x00,0xF1,0xFE,0xFE,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xBA,0x83,0x20,0x86,0xB2,0xAA,0x67,0x14,0x2A,0x2F,0x2C,0x25,0x29,0x31,0x35,0x37,0x43,0x4F,0x50,0x36,0x5E,0xBC,0xD0,0xAE,0x3A,0x4A,0xBC,0xC9,0xC1,0xBA,0xB4,0xAD,0xA4,0x9B,0x8D,0x87,0x8E,0x95,0x9B,0xA8,0xB5,0xBE,0xC3,0xC8, + 0xCD,0xD0,0xD3,0xDC,0xFB,0xFD,0xF6,0xF6,0xF9,0xF9,0xFB,0xFD,0xAE,0x00,0x00,0x00,0x00,0x00,0xEF,0xFC,0xFC,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xB0,0x8C,0x25,0x63,0xA8,0xB4,0xA0,0x6E,0x25,0x1C,0x2C,0x38,0x43,0x49,0x47,0x36,0x18,0x69,0xB2,0xD7,0xD4,0x93,0x24,0x71,0xC3,0xCE,0xBB, + 0x9B,0x79,0x5B,0x37,0x00,0x00,0x00,0x00,0x1C,0x4C,0x69,0x8B,0xB2,0xC2,0xC6,0xCC,0xD0,0xD3,0xD7,0xDF,0xF4,0xF6,0xF3,0xF6,0xF9,0xFA,0xFC,0xE9,0x45,0x00,0x00,0x00,0x00,0x00,0x3D,0x3F,0x3D,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x99,0x99,0x48,0x32,0x81,0xAA,0xB2,0xB2,0xA0,0x8D, + 0x80,0x79,0x7F,0x92,0xAA,0xCC,0xDC,0xD8,0xAE,0x59,0x3E,0x8E,0xA2,0x7D,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x98,0xBB,0xD2,0xD8,0xDD,0xE3,0xE8,0xEC,0xF1,0xF8,0xFB,0xFA,0xD1,0x57,0x00,0x67,0xA7,0xA9,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x9A,0x76,0x3B,0x2A,0x6B,0x92,0xAE,0xBC,0xBF,0xC0,0xC5,0xCC,0xD0,0xBB,0x95,0x54,0x1E,0x32,0x50,0x22,0x1E,0x21,0x36,0x48,0x55,0x59,0x56,0x52,0x49,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x75,0x9A,0xB5,0xC5,0xCA,0xCD,0xC2,0xA5,0x5D,0x00,0x00,0x00,0x9D,0xFE,0xFE, + 0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x71,0x8F,0x7C,0x5D,0x38,0x1F,0x34,0x59,0x66,0x67,0x55,0x27,0x1E,0x1E,0x25,0x45,0x60,0x6E,0x77,0x7D,0x86,0x86,0x85,0x85,0x82,0x7F,0x7C,0x77,0x73,0x6F,0x65,0x58,0x42,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xFD,0xFC,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2D,0x61,0x81,0x92,0x8D,0x88,0x89,0x8A,0x8A,0x8B,0x8D,0x93,0x9A,0xA1,0xA0,0x9B,0x94,0x8E,0x88,0x83,0x78,0x72, + 0x72,0x70,0x6D,0x69,0x66,0x65,0x63,0x62,0x69,0x71,0x6F,0x5D,0x2D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x62,0x7C, + 0x94,0xA1,0xA8,0xA8,0xA7,0xA4,0x9F,0x92,0x81,0x70,0x5E,0x4A,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + +}; +const lv_image_dsc_t ui_img_logo_80x44_png = { + .header.w = 80, + .header.h = 44, + .data_size = sizeof(ui_img_logo_80x44_png_data), + .header.cf = LV_COLOR_FORMAT_NATIVE_WITH_ALPHA, + .header.magic = LV_IMAGE_HEADER_MAGIC, + .data = ui_img_logo_80x44_png_data +}; + diff --git a/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c b/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c new file mode 100644 index 0000000..b819d0d --- /dev/null +++ b/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c @@ -0,0 +1,298 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include "../ui.h" + +#ifndef LV_ATTRIBUTE_MEM_ALIGN + #define LV_ATTRIBUTE_MEM_ALIGN +#endif + +// IMAGE DATA: assets/Text_218x40.png +const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_text_218x40_png_data[] = { + 0xE1,0x18,0xE2,0x10,0x02,0x19,0x02,0x11,0xC1,0x00,0xA1,0x00,0xC1,0x08,0x02,0x19,0x22,0x21,0x22,0x19,0x22,0x21,0x22,0x21,0x42,0x21,0x42,0x21,0x02,0x21,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,0xE6,0x08,0xE5,0x10,0xA4,0x00,0x23,0x00,0x23,0x00,0x84,0x00,0xC5,0x10,0x46,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0x10,0x26,0x19,0x46,0x21,0x46,0x21,0x67,0x21,0xA7,0x29,0xA8,0x29,0xE5,0x10,0x92,0x94,0x9A,0xD6,0xFB,0xDE,0xFB,0xDE, + 0xFB,0xDE,0xFB,0xDE,0xDB,0xDE,0x14,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA7,0x31,0x79,0xCE,0x1C,0xE7,0x3C,0xE7,0x5D,0xE7,0x5D,0xEF,0x3D,0xE7,0x39,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xCD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x41,0xDD,0x41,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x62,0xDD,0x61,0xDD,0x02,0xCD,0xA3,0xBC,0xA2,0x93,0xA1,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xBE,0xDB,0xDE,0xDB,0xDE,0xBB,0xD6,0xBB,0xD6,0xDB,0xDE,0xDB,0xDE,0x39,0xC6, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x6B,0x7A,0xCE,0xDB,0xDE,0xDB,0xDE,0xDB,0xDE,0xDB,0xDE,0xFB,0xDE,0xBA,0xD6,0xCC,0x52,0x38,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x73,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xED,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE, + 0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x21,0xFE,0x41,0xFE,0x21,0xF6,0xA1,0xE5,0x61,0xB4,0x21,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xEF,0xF0,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xAD,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xDE,0x93,0x8C,0x1C,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x7C,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5D,0xEF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x21,0xFE,0x21,0xFE,0x21,0xFE,0x41,0xFE,0x81,0xE5,0x21,0xAC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x8C,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBA,0xD6,0x00,0x00,0xFB,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x6B,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x20,0xFE,0x20,0xFE,0xE1,0xF5,0x21,0xBC, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x6B,0x1C,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAF,0x73,0x3D,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xD3,0x9C,0x00,0x00,0xB7,0xAD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x4A,0x5D,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0x7A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x81,0xED,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0x61,0xED,0x61,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0x0C,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0xEC,0x5A,0x00,0x00,0x00,0x00,0xB3,0x94, + 0x39,0xC6,0xD3,0x94,0x76,0xAD,0x7A,0xCE,0xF4,0x9C,0x6A,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x73,0x8C,0x7A,0xCE,0xDB,0xD6,0x7A,0xC6,0x5A,0xC6,0x76,0xAD,0x29,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0x21,0xDD,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x01,0xE5,0x21,0xE5,0xA0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0x61,0xCC,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7B,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x00,0xF8,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x59,0xCE,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xED,0xA0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xA1,0xFD,0xC2,0x82,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0x41,0x81,0xA3,0xE1,0xD4,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x21,0xED,0x62,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x31,0x41,0x6A,0xA2,0xB3,0x82,0xAB,0x61,0x72,0x01,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x41,0xC3,0x7A,0x22,0x93,0x82,0xA3,0x81,0xA3,0x61,0x9B,0x41,0x72,0x81,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x3A,0xFC,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0xC6,0xE4,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x6B,0xDB,0xDE,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x14,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x42,0xCF,0x73,0xF3,0x9C,0xF4,0x9C,0x14,0xA5,0xD3,0x9C,0xB3,0x94,0x6A,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x08,0x88,0x31,0x6E,0x6B,0xB3,0x94,0xF4,0x9C,0xF4,0x9C,0xB3,0x94,0x31,0x84,0x4A,0x4A,0xAC,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x00,0x8B,0x01,0x6B,0x00,0x8B,0x01,0x2B,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x52,0xB3,0x94,0x14,0x9D,0x14,0xA5,0xB3,0x94,0x11,0x7C,0xC8,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xED,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0xC1,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x62,0xE1,0xD4,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x82,0xA3,0x22,0xAC,0xA0,0xD4,0xA0,0xD4,0xA0,0xD4,0xA1,0xCC,0xA1,0xCC,0xA1,0xCC,0x61,0xC4,0x03,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xC4,0x81,0xD4,0x81,0xCC,0x60,0xCC, + 0x60,0xCC,0x80,0xCC,0xA0,0xCC,0x22,0xB4,0x00,0x00,0x03,0xAC,0xA1,0xCC,0xA0,0xCC,0xA1,0xCC,0xA1,0xD4,0x80,0xD4,0xE1,0xB3,0x00,0x00,0x00,0x00,0xC2,0x72,0x01,0xB4,0x01,0xE5,0x61,0xF5,0xA1,0xFD,0x81,0xFD,0x60,0xF5,0xA1,0xD4,0x62,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6A,0xC1,0xA3,0xE1,0xD4,0x41,0xED,0xA1,0xF5,0xC1,0xFD,0xC1,0xFD,0xC1,0xFD,0xC1,0xFD,0xA1,0xF5,0x61,0xED,0xC1,0xD4,0xA1,0xA3,0x21,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xDE,0xEF,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x31,0x84,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x2D,0x63,0x00,0x00,0x00,0x00,0x76,0xAD,0x9A,0xCE,0x9A,0xD6,0x9A,0xD6,0xBA,0xD6,0xBA,0xD6,0x9A,0xD6,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0x6B,0x96,0xB5,0xBA,0xD6,0x7D,0xEF,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0xDB,0xDE,0x59,0xCE,0xB3,0x94,0x0D,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x7C,0x39,0xC6,0x79,0xCE,0x79,0xCE,0x79,0xCE,0x79,0xCE,0x79,0xCE,0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7B,0x55,0xA5,0x9A,0xD6, + 0x3D,0xE7,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBF,0xF7,0x7D,0xEF,0xBA,0xD6,0x18,0xC6,0x52,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0x4A,0xB7,0xB5,0x9A,0xCE,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x7A,0xCE,0x14,0xA5,0x00,0x00,0xF0,0x7B,0x76,0xAD,0xDB,0xDE,0x7E,0xEF,0xDF,0xF7,0xDF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBE,0xF7,0x5D,0xE7,0xBB,0xD6,0x35,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xED,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0xA1,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x7A,0x61,0xF5,0x80,0xFD,0x80,0xFD,0x80,0xFD, + 0x80,0xFD,0x80,0xFD,0x80,0xFD,0x42,0xCC,0xE1,0x8A,0x80,0xFD,0x80,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x60,0xF5,0x42,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xDC,0x80,0xFD,0x80,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x80,0xFD,0x81,0xA3,0x00,0x00,0x62,0xC4,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x00,0xED,0x81,0x08,0xC2,0xAB,0x01,0xE5,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0xC1,0xE4,0x81,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x92,0xE1,0xB3,0x01,0xE5,0x80,0xFD,0x80,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA1,0xFD,0xA1,0xFD,0xA1,0xFD,0xA1,0xFD, + 0xC1,0xFD,0xC1,0xFD,0xA1,0xFD,0x01,0xDD,0x81,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x84,0x7E,0xEF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x71,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xC6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x79,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xBD,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x35,0xA5,0xFC,0xDE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0x9E,0xF7,0xDB,0xDE,0x51,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0xEA,0x31,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDB,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xAD,0x3C,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xEF,0xF8,0xBD,0x30,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x4A,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x92,0x8C,0xBB,0xD6,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xBE,0xF7,0xF8,0xBD,0x00,0x00,0x00,0x00,0x21,0xED,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x60,0xFD,0xA2,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x62,0xA1,0xDC,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x41,0xCC,0xE1,0x9A,0xC1,0xDC,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x21,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x93,0x40,0xF5,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x60,0xFD,0xE1,0xE4,0x41,0x39,0x00,0x00,0x22,0xC4,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x40,0xFD,0xE1,0xEC, + 0xE1,0x8A,0x20,0xF5,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x61,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x49,0x01,0xC4,0x20,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x81,0xFD,0xA1,0xFD,0x61,0xF5,0xE1,0xBB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBA,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xF7,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x29,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x55,0xAD,0x00,0x00,0x00,0x00,0x00,0x00, + 0xD7,0xB5,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x00,0x76,0xAD,0x9E,0xEF,0xDF,0xFF,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,0x5D,0xEF,0x71,0x8C,0x00,0x00,0x00,0x00,0x46,0x21,0x7E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xF8,0xBD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF, + 0xFC,0xDE,0x55,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x4A,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0xD6,0xFC,0xDE,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE,0xF7,0xB6,0xB5,0x00,0x00,0x01,0xED,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0xA2,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x41,0x61,0xD4,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x41,0xD4,0x00,0x00,0xA1,0xB3,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD, + 0x81,0xDC,0x61,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xC4,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x41,0xCC,0x00,0x00,0x00,0x00,0xE1,0xC3,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x01,0xFD,0xA1,0xE4,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0xC1,0xC3,0x00,0x00,0x00,0x00,0x61,0x49,0x01,0xC4,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x61,0xFD,0x61,0xFD,0x41,0xFD,0xC1,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB6,0xB5, + 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDB,0xD6,0x31,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x5B,0x9E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x3D,0xE7,0x2D,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xB5,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xA5,0x7D,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0xDE,0xAB,0x52,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7, + 0xDF,0xFF,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xBD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x9A,0xD6,0x2A,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x52,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0x2D,0x63,0xE0,0xEC,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x20,0xFD,0x81,0x82, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x72,0x61,0xDC,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x20,0xFD,0x01,0xCC,0x00,0x00,0x01,0x62,0xA0,0xEC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0xE0,0xF4,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xDC,0x20,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x22,0x9B,0x00,0x00,0x00,0x00,0xC1,0xBB,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x81,0xB3,0x00,0x00,0x00,0x00, + 0x82,0xAB,0x00,0xF5,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0xE0,0xF4,0x81,0x8A,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x7C,0x7D,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9E,0xEF,0x8E,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7A,0xCE,0xBF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x7A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF7,0xBD,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xD6, + 0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0xBA,0xD6,0xFB,0xDE,0x1C,0xDF,0x9A,0xD6,0xDB,0xDE,0x9E,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0xD3,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0x7E,0xEF,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x7D,0xEF,0x7D,0xEF,0xDF,0xF7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE,0xF7,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0xAB,0x52,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF, + 0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x96,0xAD,0xA0,0xEC,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x00,0xFD,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x59,0xA0,0xEC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0xA1,0xC3,0x00,0x00,0x00,0x00,0x41,0xD4,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0x81,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC2,0x82,0xE0,0xEC,0x00,0xFD,0x00,0xFD, + 0x00,0xFD,0x00,0xFD,0x00,0xFD,0x81,0xE4,0x62,0x82,0x00,0x00,0x00,0x00,0xA1,0xBB,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0xA0,0xFC,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC1,0xF4,0xC1,0xEC,0xA1,0xEC,0xA0,0xF4,0xA0,0xF4,0xA1,0x8A,0x00,0x00,0x00,0x00,0x81,0xE4,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0xE0,0xFC,0x21,0xD4,0x62,0xAB,0x02,0x9B,0xE2,0x92,0xA1,0xBB,0x81,0xDC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x01,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xD6,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0xDF,0xF7,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xDB,0xD6,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xBD,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x08,0x00,0x3C,0xE7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0x14,0xA5,0x2D,0x63,0x00,0x00,0x00,0x00,0x88,0x29,0x8C,0x52,0xAF,0x73,0x7A,0xCE,0x3C,0xE7,0xDF,0xF7,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x21,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xD6,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7, + 0xDF,0xF7,0xDF,0xF7,0x9E,0xF7,0x39,0xC6,0xB3,0x94,0x8A,0x52,0x6A,0x4A,0x72,0x8C,0xF8,0xBD,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFB,0xDE,0xEC,0x5A,0x00,0x00,0x00,0x00,0xAB,0x52,0xDB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xBE,0xF7,0xBB,0xD6,0xD7,0xB5,0xB7,0xB5,0x18,0xBE,0x38,0xC6,0x1C,0xDF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x59,0xC6,0xA1,0xEC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xC3,0xC0,0xFC,0xC0,0xFC, + 0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x01,0xA3,0x00,0x00,0x00,0x00,0x62,0xA3,0xC0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xE0,0xD3,0x81,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xAB,0x00,0xFD,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x21,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xBB,0xA0,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xE1,0xD3,0x63,0xB3,0x83,0x72,0x62,0x39,0x61,0x41,0x81,0x82,0x20,0xA3,0xE1,0x51,0x00,0x00,0xC1,0x9A,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x61,0xB3,0x22,0x31,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x31,0xA1,0xC3,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0x80,0xF4,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xAD,0xBE,0xEF,0xBE,0xF7,0xBE,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBA,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0x52,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0x7D,0xEF,0x6E,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xBD,0xDF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0xC5,0x08,0x9E,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFB,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x8E,0x6B,0xD7,0xB5,0x0C,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0xBA,0xD6,0x0A,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBE,0xF7,0x96,0xB5,0x49,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xA5,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x92,0x8C,0x00,0x00,0x00,0x00,0xAB,0x52,0xBB,0xD6,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9E,0xEF,0x76,0xAD,0x4E,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x6B,0xDB,0xD6,0xDF,0xF7, + 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9A,0xCE,0x81,0xEC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x49,0x60,0xBB,0x60,0xF4,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xFC,0x60,0xFC,0x20,0xEC,0x01,0x7A,0x00,0x00,0x00,0x00,0xA1,0x51,0x20,0xE4,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xF4,0x20,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xE1,0xCB,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0xE1,0xA2,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xBB,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC, + 0x40,0xFC,0x60,0xFC,0x60,0xFC,0xA0,0xCB,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xC3,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x80,0xFC,0x00,0xE4,0x21,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0x69,0x21,0xE4,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x41,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x84,0x7E,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x5D,0xE7,0xCC,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0xB5,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xD7,0xB5,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x07,0x01,0xBE,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDB,0xD6,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0xBF,0xF7,0xBA,0xD6,0x0A,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0xBE,0xF7,0xBE,0xF7,0xBE,0xEF,0xBE,0xEF,0xBE,0xF7,0xBF,0xF7,0xFC,0xDE,0x8F,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7A,0xCE,0xDF,0xF7, + 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x79,0xCE,0x00,0x00,0x00,0x00,0x8B,0x52,0xBB,0xD6,0xBF,0xF7,0xDF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0x79,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xAD,0xBE,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x3D,0xE7,0x41,0xEC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x62,0xBB,0xC1,0xC3,0xA1,0xC3,0xA0,0xC3,0x81,0xC3,0x80,0xC3,0x80,0xC3,0x61,0xCB,0xE0,0xE3,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x40,0xCB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBB,0x60,0xFC,0x60,0xFC, + 0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x7A,0x20,0xE4,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x80,0xFC,0x00,0xE4,0xC1,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBB,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0xC0,0xE3,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xDB,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xC3,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x61,0xFC,0x81,0xCB,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xCE,0x9E,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0xBF,0xF7,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBE,0xEF,0x9A,0xCE,0x35,0xA5,0x0C,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x21,0x5D,0xE7,0xBE,0xEF, + 0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBA,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xC6,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xB5,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x8B,0x4A,0xBB,0xCE,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xF7,0x7E,0xEF,0xF4,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x4A,0x3C,0xDF,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xEF,0x3D,0xE7,0x01,0xEC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC, + 0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xC0,0xF3,0x01,0x8A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x82,0x20,0xF4,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x60,0xFC,0xA0,0xD3,0x81,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x92,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xFC,0x61,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xBB,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x40,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xC1,0xE3,0x20,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x01,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xB3,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0xA1,0xDB,0x82,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x32,0xFC,0xD6,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x5D,0xDF,0xF0,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xAD,0xBE,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xF8,0xB5,0x00,0x00,0x00,0x00, + 0x00,0x00,0x9A,0xCE,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0x9E,0xEF,0x5D,0xE7,0xBB,0xD6,0x18,0xBE,0xB3,0x94,0x33,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x21,0x5D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBA,0xCE,0x00,0x00,0x00,0x00,0x87,0x21,0xDB,0xD6,0x7E,0xEF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xEF,0x14,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x9D,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x1C,0xDF,0x00,0x00,0x00,0x00,0x6A,0x42,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF, + 0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0x3D,0xE7,0xAB,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xD6,0xBF,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0x1C,0xDF,0xC1,0xEB,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC1,0xB2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x10,0x81,0xD3,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xF4,0xC1,0x79,0x00,0x00,0x00,0x00,0xE2,0x28,0x81,0xCB,0x60,0xFC,0x60,0xFC, + 0x60,0xFC,0x40,0xFC,0x60,0xFC,0x40,0xF4,0x61,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xBA,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0x60,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xEB,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x81,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xA2,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x81,0xDB,0xC2,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x73,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x1C,0xD7,0x0A,0x2A, + 0x00,0x00,0x00,0x00,0x93,0x8C,0x5E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9B,0xCE,0xAB,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xA5,0x9E,0xEF,0x9E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x84,0x7D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBF,0xEF,0xBF,0xEF,0x9E,0xEF,0xDB,0xD6,0x59,0xC6,0x72,0x8C,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDD,0x64,0x5E,0xE7,0x9E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xBB,0xCE,0x00,0x00,0x00,0x00,0x4A,0x21,0x9A,0xCE,0x5D,0xE7,0x5E,0xE7,0x7E,0xE7, + 0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x76,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x42,0x5D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x1C,0xDF,0xC5,0x08,0x00,0x00,0x4A,0x42,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x3D,0xDF,0x4A,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xD6,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x1C,0xDF,0xA1,0xE3,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB, + 0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xF3,0xA1,0xBA,0xE1,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xBA,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x01,0xBB,0x00,0x00,0x00,0x00,0x42,0x51,0xC1,0xDB,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0xA1,0xDB,0x21,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x41,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x39,0xA1,0xF3,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x21,0x92,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x92,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xA1,0xE3,0xA2,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x5B,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xF4,0x94,0x00,0x00,0x00,0x00,0xF8,0xB5,0x7E,0xE7,0x7E,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xA5,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x42,0xD7,0xB5,0x5D,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xE7, + 0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x5D,0xE7,0x7A,0xCE,0x31,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD6,0x4B,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x6C,0x42,0x7A,0xC6,0x5D,0xDF,0x5D,0xDF,0x5D,0xDF,0x5E,0xDF,0x5E,0xDF,0x3D,0xDF,0x39,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x21,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x3D,0xDF,0xA8,0x29,0x00,0x00,0x4A,0x42,0x9A,0xCE,0x9E,0xE7,0x9E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x1D,0xDF,0x6B,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xDB,0xD6,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0xFC,0xD6,0x81,0xEB,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x01,0xE3,0x61,0xB2,0x01,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x69,0xC0,0xEB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x41,0xD3,0x00,0x00,0x00,0x00,0x02,0x82,0x00,0xF4,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x01,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0x80,0xFB,0x80,0xFB, + 0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x00,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x80,0xEB,0xA0,0xFB,0xA0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xE1,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x92,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x81,0xE3,0xA2,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xB6,0x3E,0xDF,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x5E,0xDF,0xB7,0xAD,0x00,0x00,0x29,0x3A,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x3D,0xDF,0x72,0x84,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0xA5,0x7E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7E,0xDF,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x42,0x15,0x9D,0xDB,0xCE,0x5E,0xE7,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xFC,0xD6,0xF4,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x19,0xFC,0xD6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7A,0xC6,0x00,0x00,0x00,0x00,0x4D,0x42,0x7A,0xC6,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xD7,0x18,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x46,0x21,0x1D,0xD7,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x1D,0xD7,0x09,0x32,0x00,0x00,0x8B,0x4A,0x7A,0xC6,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x1D,0xD7,0x6B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xCE,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xFC,0xD6,0x61,0xEB,0xA0,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0xE0,0xF2,0xA0,0xDA,0xA1,0xD2,0x22,0xAA,0xA2,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x21,0xD3,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0x80,0xEB,0x01,0x51,0x00,0x00,0xE2,0xBA,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xF3,0x21,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0xE0,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xEB,0x80,0xFB,0x80,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xC1,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x92,0x80,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB, + 0x21,0xDB,0x42,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x74,0x1D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x39,0xB6,0x46,0x19,0xD0,0x6B,0xFD,0xCE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0x5E,0xD7,0x9B,0xC6,0xEB,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xA5,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xD8,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x63,0x76,0xA5,0x7A,0xC6,0x1D,0xD7,0x3D,0xD7,0x3D,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xDC,0xCE,0x6E,0x63,0x00,0x00,0x00,0x00,0x26,0x19, + 0xDC,0xCE,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x5D,0xDF,0x5E,0xDF,0x5A,0xBE,0x00,0x00,0x00,0x00,0xCB,0x31,0x39,0xBE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x1D,0xD7,0x19,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x29,0x1D,0xD7,0x5E,0xDF,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x5E,0xDF,0xFC,0xCE,0x87,0x21,0x00,0x00,0x8B,0x4A,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x1C,0xD7,0x6B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xDB,0xCE,0x41,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB, + 0x60,0xFB,0x60,0xFB,0x40,0xFB,0xA2,0x89,0x82,0x79,0xA2,0x89,0xC1,0x99,0xC1,0x99,0xA1,0x91,0xA1,0x91,0xA2,0x91,0x42,0x69,0x03,0x59,0xE2,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAA,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x41,0xB2,0x00,0x00,0x21,0xD3,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0xA0,0xFB,0x40,0xE3,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xBA,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0xC0,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0xC1,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xA2,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0xE1,0xDA,0xA2,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA9,0x29,0x7B,0xBE,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xBC,0xC6,0xD0,0x6B,0x56,0x9D,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xD7,0x3D,0xD7,0xB7,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x9D,0x5E,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0xD8,0xAD, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0x4A,0xAF,0x63,0xB7,0xA5,0x7A,0xBE,0xBB,0xCE,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xDF,0x56,0xA5,0x00,0x00,0x00,0x00,0x26,0x19,0xBC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x3D,0xD7,0x39,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xCF,0x1D,0xCF,0x1D,0xD7,0x1D,0xD7,0x15,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x8C,0x1D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0xBB,0xC6,0x00,0x00,0x00,0x00,0x6B,0x4A,0x5A,0xBE, + 0x5E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x1C,0xD7,0x8C,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9B,0xC6,0x3E,0xD7,0x3E,0xD7,0x3D,0xD7,0x3D,0xDF,0x5D,0xDF,0xBB,0xCE,0x21,0xEB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x82,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x71,0x20,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0xA0,0xCA,0x63,0x51,0x40,0xF3,0x60,0xFB, + 0x40,0xFB,0x40,0xFB,0x40,0xFB,0x60,0xFB,0xA1,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xBA,0x20,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0x80,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xD2,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x81,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAA,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0xA1,0xDA,0x82,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xA5,0xFD,0xCE,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6, + 0xFD,0xC6,0xFD,0xC6,0x15,0x95,0xF9,0xAD,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xDC,0xC6,0x11,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x9D,0x3E,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x3D,0xD7,0x3E,0xD7,0xB8,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x7C,0xB4,0x8C,0x19,0xB6,0xFC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x39,0xB6,0x09,0x3A,0x00,0x00,0x05,0x19,0x9C,0xC6,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0x19,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xB6,0xFD,0xCE, + 0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0xB7,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF4,0x94,0x1D,0xD7,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xF9,0xAD,0x00,0x00,0x00,0x00,0x2A,0x3A,0x3A,0xBE,0x3E,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0xFC,0xCE,0xED,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0xBE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0xBB,0xC6,0x01,0xE3,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xFA,0x62,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xD2,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0xC0,0xE2,0x41,0x9A,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xF3,0x81,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBA,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xA0,0xFA,0x40,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xCA,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x80,0xDA,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x28,0x81,0xCA,0x00,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x42,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x74,0xBC,0xBE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xB8,0x9D,0x1A,0xAE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDC,0xC6,0x19,0xAE,0xC8,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x95,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x97,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x8C,0xDC,0xC6,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0x3A,0xB6,0xF1,0x73,0x00,0x00,0x26,0x19,0x7B,0xBE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0xF9,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x57,0x9D,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xF9,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xA5,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xB8,0xA5,0x00,0x00,0x00,0x00,0x09,0x3A,0x19,0xB6,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xFC,0xCE,0xED,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x5B,0xBE,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xBB,0xC6,0xC1,0xEA,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xA1,0xC0,0xF2,0xE0,0xFA,0x00,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xF2,0x61,0xBA,0x00,0xFB,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0x60,0xDA,0x81,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xBA, + 0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x00,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB9,0xA0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x80,0xF2,0x61,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x81,0xC0,0xF2,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA2,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x19,0x1A,0xAE,0xBD,0xBE,0xBD,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x7B,0xB6,0x9C,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x15,0x95,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x8C,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0x97,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x84,0xF5,0x84,0xC8,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x01,0x5B,0xB6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0x3A,0xB6,0x11,0x74,0x00,0x00,0x26,0x19,0x7B,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xB8,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0xF1,0x6B,0xBC,0xBE,0xBD,0xC6,0xDC,0xC6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x9C,0xBE,0x12,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x6F,0x5B,0x5A,0xB6,0xDC,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0x32,0x74,0x00,0x00,0x00,0x00,0xE9,0x31,0x19,0xAE,0xFD,0xCE,0xFD,0xC6,0xFD,0xC6,0xFD,0xCE,0x1D,0xCF,0xDC,0xC6,0x8C,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3A,0xB6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0x9B,0xBE,0x81,0xEA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0xA0,0xFA,0x80,0xFA,0x21,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x49,0x41,0xDA,0xC0,0xFA,0xC0,0xFA,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xC0,0xF2,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x00,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xB9,0x60,0xFA,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0xC0,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x58,0x40,0xEA,0x80,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x20,0xDA,0x61,0x99,0xE1,0x58,0x00,0x00,0x00,0x00,0xC2,0x48,0x81,0x89,0x60,0xDA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA, + 0x60,0xFA,0x00,0xDA,0x01,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x9D,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x7B,0xB6,0xF1,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x84,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xC6,0xDD,0xBE,0x77,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0xD1,0x63,0x1A,0xAE,0x9C,0xB6,0x98,0x9D,0x93,0x7C,0x0E,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x00,0x73,0x7C,0x9C,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xDD,0xBE,0x97,0x9D,0x09,0x32, + 0x00,0x00,0x05,0x19,0x3B,0xAE,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0xB8,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x3A,0xF9,0xA5,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x1A,0xAE,0x73,0x7C,0x6B,0x3A,0x00,0x00,0x00,0x00,0xE9,0x31,0xF1,0x6B,0xD8,0xA5,0x9C,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBD,0xBE,0x3A,0xAE,0x09,0x32,0x00,0x00,0x00,0x00,0x09,0x32,0xF9,0xAD,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0xFD,0xC6,0xBC,0xBE,0x4B,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x1A,0xAE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xC6,0xDD,0xBE,0x5B,0xB6,0x41,0xEA,0x60,0xFA, + 0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB1,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x41,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB9,0x20,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xA0,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xB9,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x40,0xF2,0x20,0xDA,0x41,0xDA,0x41,0xD2,0x41,0xE2,0x80,0xF2,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x20,0xFA,0x80,0xB9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0x84,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0xD9,0xA5,0xC8,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x84,0xBC,0xBE,0x9C,0xB6,0x9C,0xB6,0xBC,0xBE,0xBC,0xBE, + 0xBD,0xBE,0x56,0x95,0x00,0x00,0x00,0x00,0xD3,0x4B,0x98,0x9D,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7B,0xB6,0xD9,0xA5,0x77,0x95,0x57,0x95,0x52,0x74,0x52,0x74,0xF5,0x8C,0xB8,0xA5,0x5B,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x36,0x95,0x00,0x00,0x00,0x00,0x05,0x11,0x3A,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x98,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x84,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xB6,0xF9,0xA5,0xB8,0xA5,0xB8,0xA5,0xD9,0xA5,0x7B,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xBE,0x9C,0xB6,0x16,0x8D,0x00,0x00,0x00,0x00,0x00,0x00, + 0xE9,0x31,0xD9,0xA5,0xBD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0x9B,0xB6,0x2A,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xF9,0xA5,0xBC,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0x1A,0xAE,0x21,0xE2,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x79,0x40,0xEA,0x60,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA, + 0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x20,0xE2,0xC1,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xB9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0x80,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x69,0x01,0xE2,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0xC0,0xD9,0xA1,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x11,0xFA,0x9D, + 0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x37,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0x7C,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x36,0x8D,0x00,0x00,0x00,0x00,0x15,0x8D,0x7B,0xB6,0x7B,0xB6,0x7B,0xB6,0x7B,0xAE,0x5B,0xAE,0x7B,0xAE,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xBE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x1A,0xA6,0x90,0x63,0x00,0x00,0x00,0x00,0x26,0x11,0x1A,0xA6,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x78,0x95,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x68,0x09,0x98,0x9D,0x7C,0xAE,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0xD9,0x9D,0x8B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x29,0xB9,0x9D,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0xBC,0xB6,0xBC,0xBE,0x5B,0xAE,0x2A,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xF9,0xA5,0x9C,0xB6,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0xD9,0x9D,0xE1,0xE1,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x00,0xFA,0xE1,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,0x22,0x00,0xC1,0xD1,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0xC0,0xD1,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xB1,0xA0,0xF9,0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0xA0,0xF9,0x60,0xD1,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,0x91,0xE1,0xE1,0x00,0xFA,0x20,0xFA,0x20,0xFA, + 0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xA0,0xE1,0xE1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x8D,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x32,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x7C,0x7C,0xAE,0x5B,0xAE,0x5C,0xAE,0x5C,0xAE,0x7C,0xAE,0x7C,0xAE,0xF5,0x84,0x00,0x00,0x00,0x00,0x57,0x95,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE, + 0x5B,0xAE,0x7B,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x1A,0xA6,0x94,0x7C,0x84,0x00,0x00,0x00,0x00,0x00,0x4D,0x22,0xFA,0xA5,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x77,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x4B,0x98,0x95,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x98,0x95,0xB1,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x29,0x98,0x9D,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x3B,0xAE,0x2A,0x2A,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xD9,0x9D,0x7C,0xAE,0x7C,0xAE,0x5C,0xAE,0x5B,0xAE,0x5B,0xAE,0xB9,0x9D,0xA0,0xE1,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xE2,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xA1,0x00,0xFA,0x00,0xFA,0x20,0xFA,0x20,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x21,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x41,0xB9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xD1,0x00,0x00,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,0x81,0xC1,0xD9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA1,0xD9,0xE1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x6C,0xFA,0x9D,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0xFA,0x9D,0xFA,0x9D,0xB9,0x95,0x4B,0x32,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x7C,0x5B,0xAE,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x5B,0xA6,0x5B,0xAE,0xD5,0x84,0x00,0x00,0x00,0x00,0x6B,0x32,0xB5,0x7C,0xB9,0x9D,0x3B,0xA6,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x3B,0xAE,0x3B,0xA6,0x3B,0xA6,0xD9,0x9D,0x74,0x74,0x4B,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0x44,0xFA,0x9D,0x1B,0xA6,0x1B,0xA6,0x1B,0xA6,0x1B,0x9E,0x1B,0xA6,0x57,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xED,0x4A,0x37,0x8D,0x1B,0xA6,0x3B,0xA6,0x3B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE, + 0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x3B,0xAE,0x3B,0xA6,0x1B,0xA6,0x37,0x8D,0xD1,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE9,0x29,0x98,0x95,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x1A,0xA6,0xEA,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xB9,0x95,0x5B,0xA6,0x5B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0xB9,0x9D,0x60,0xE1,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0xC2,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x38,0x81,0xC9,0xE0,0xF9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xC0,0xF9,0xA0,0xE1,0xE2,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xB1,0x60,0xF1,0x40,0xF1,0x40,0xF1,0x20,0xF1,0x20,0xF9,0x40,0xF9,0x00,0xE1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x50,0x61,0xB9,0x81,0xD1,0xA0,0xF1,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA0,0xF1,0x61,0xD9,0x41,0xB1, + 0xA2,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x32,0x58,0x85,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xBA,0x95,0xB9,0x95,0xD5,0x7C,0xE9,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x74,0x3B,0xA6,0x1B,0x9E,0xFB,0x9D,0xFB,0x9D,0x1B,0x9E,0x1B,0xA6,0xD5,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x4B,0xD5,0x7C,0x98,0x95,0x1B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x1B,0xA6,0xB9,0x95,0xF6,0x84,0xB0,0x5B,0x06,0x09,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0x3C,0xD9,0x95,0xDA,0x9D,0xFA,0x9D,0xDA,0x9D,0xDA,0x9D,0xFA,0x9D,0x37,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0x42,0x12,0x6C,0x57,0x8D,0xFA,0xA5,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xAE,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x1B,0xA6,0xFA,0x9D,0x57,0x8D,0x53,0x74,0xCD,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE9,0x29,0x78,0x95,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0xF9,0x9D,0xA8,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x98,0x95,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0xA6,0x1B,0xA6,0xB8,0x95, + 0xE1,0xB0,0x21,0xC1,0x41,0xB9,0x41,0xC1,0x41,0xC9,0x41,0xD9,0x20,0xD9,0xC7,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x99,0xC0,0xF9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA0,0xF9,0x40,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x80,0x01,0xB9,0x21,0xC1,0x21,0xC1,0x01,0xC1,0x01,0xC1,0x01,0xD1,0xE2,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,0x62,0x30,0xE1,0x88,0x41,0xC1,0x60,0xC9,0x80,0xD9,0x80,0xE1,0x80,0xE1,0x80,0xD9,0x61,0xC9,0x41,0xC1,0xE1,0x90,0xC6,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x11,0xD1,0x5B,0x75,0x6C,0x33,0x6C,0x13,0x64,0x12,0x64,0x13,0x64,0x33,0x6C,0xF2,0x63,0xD1,0x63,0x6F,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x5B,0xD5,0x7C,0x94,0x74,0x94,0x74, + 0x94,0x74,0x94,0x7C,0x94,0x7C,0x6F,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x21,0x12,0x6C,0x16,0x85,0x16,0x8D,0x77,0x95,0x98,0x95,0x98,0x95,0x78,0x95,0x16,0x8D,0x37,0x8D,0x53,0x74,0xC9,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x6C,0x53,0x6C,0x33,0x6C,0x32,0x6C,0x12,0x6C,0x12,0x6C,0x90,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x5B,0xB5,0x7C,0xD9,0x9D,0x57,0x95,0x98,0x9D,0x98,0x9D,0x57,0x95,0x98,0x95,0xB4,0x7C,0x0E,0x4B,0x06,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x67,0x21,0x11,0x6C,0xB5,0x7C,0xB5,0x7C,0xF6,0x84,0x16,0x85,0x16,0x8D,0x94,0x7C,0x26,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0xF2,0x63,0x74,0x74,0x94,0x7C,0xB5,0x7C,0xB5,0x84,0xD5,0x84,0x94,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x81,0xA0,0xE1,0xC0,0xF9,0xA0,0xF9, + 0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF1,0xC1,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,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xA8,0xE0,0xC0,0xE0,0xB8,0xE1,0xB0,0x21,0xB1,0x61,0xC9,0xA0,0xE9,0xA0,0xF9,0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x01,0xC1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC1,0x40,0xF9,0x40,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xD9,0xA1,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD1,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xF9,0xE0,0xE0,0xC1,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0xE0,0xD8,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xF9,0x20,0xF9,0x00,0xF9,0x00,0xD1,0xA1,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x50,0xC0,0xD8,0x00,0xF9,0x20,0xF9,0x00,0xF9,0x00,0xF9,0x00,0xF9,0x20,0xF9,0x20,0xF1, + 0x00,0xF1,0xE0,0xD8,0xE1,0xB8,0xA2,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x60,0xA1,0xB0,0xC0,0xD0,0xC1,0xD0,0xC1,0xD0,0xC1,0xD0,0xC1,0xC8,0xE3,0xD0,0xE1,0xB8,0xA2,0x90,0x82,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + //alpha channel data: + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x11,0x11,0x11,0x11,0x11,0x11,0x05,0x47,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xDC,0xFF,0xFF,0xFF,0xFF,0xFF,0xB4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0xC2,0x96,0x56,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x40,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xAD,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x02,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB1,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x5A, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x00,0x5D,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x16,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xAE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x21,0x00,0x00,0x3C, + 0x4C,0x93,0x73,0x4B,0x45,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x45,0x4D,0x55,0x4E,0x45,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xE7,0xD3,0xD3,0xD3,0xD3,0xD3,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFE,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1F,0x5F,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0x3F,0x3F,0x3F,0x3F,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x33,0x43,0x76,0x8E,0x8E,0x69,0x3F,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x2D,0x52,0x8F,0x97,0x8F,0x86,0x46,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x2C,0x49,0x7F,0x8E,0x8E,0x8C,0x40,0x35,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x0C,0x0C,0x03, + 0x00,0x00,0x00,0x00,0x3C,0x52,0x8F,0x8E,0x84,0x43,0x1A,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x85,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xDA,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xEF,0xEF,0xEF, + 0xEF,0xEF,0xEF,0x6C,0x00,0x78,0xEF,0xEF,0xEF,0xEF,0xEF,0xD8,0x00,0x00,0x1E,0xB7,0xF6,0xFF,0xFF,0xFF,0xFF,0xF5,0x2A,0x00,0x00,0x00,0x00,0x00,0x1C,0x87,0xDE,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xD4,0x79,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x52,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x5B,0xF0,0xEF,0xEF,0xEF,0xEF,0xEF,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x7F,0xE4,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xED,0x9C,0x2F,0x01,0x00,0x00,0x00,0x00,0x01,0xE0,0xEF,0xEF,0xEF,0xEF,0xEF,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x7A,0xDF, + 0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF0,0x8F,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xD0,0xEF,0xF1,0xF2,0xF2,0xF2,0x9C,0x00,0x05,0x7C,0xDA,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xBB,0x34,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xFC,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x95,0x50,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x05,0x58,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x2A,0x00,0x00,0x00,0x02,0x82,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xE8,0x4D,0x00,0x00,0x00,0x00,0x00,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x01,0x57,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFD,0xAD,0x2E,0x00,0x00,0x00,0x27,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x87,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0x19,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xF7,0x80,0x02,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x01,0xD4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x0E,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x8A,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x15,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xA0,0x07,0x00,0x00,0x00,0x05,0xDA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x71,0x00,0x00,0x00, + 0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x01,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x2B,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x06,0x9B,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x98,0x03,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x00,0x82,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xED,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0x00,0x00,0x02,0xB9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00,0x00,0x00,0x8A, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x22,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x29,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x11,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x99,0x03,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x00,0x2D,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00, + 0x4E,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x55,0x00,0x00,0x00,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x5D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0xAA, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBC,0xB6,0xEB,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x35,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xF6,0x08,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0x00,0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xA2,0x56,0x54,0x98,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x00,0x00,0x00,0x00,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8B,0x00,0x00,0x00,0x00, + 0x00,0x00,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x72,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x0C,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x5C,0x08,0x01,0x00,0x07,0x0D,0x4C,0x8B,0xF6,0xFF,0x92,0x01,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x00,0x00,0x00,0x01,0xA9,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xCE,0x69,0x55,0x55,0x58,0xC2,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDE,0x06,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xA5,0x64,0x55,0xA1,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0x00,0x00,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0x06,0x00,0x00,0x00,0x00,0x00,0x7D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x80,0x43,0x43,0x43,0x45,0x8C,0x14,0x00,0x3B,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB2,0x08,0x00,0x00,0x00, + 0x00,0x14,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x00,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x00,0x00,0x00,0x00,0x00,0x15,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x24,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x38,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x21,0x89,0x0A,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x08,0x00,0x00,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x02,0x00,0x00,0x00,0x00,0x00,0x6B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4B,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9E,0x03,0x00,0x00,0x00,0x00,0x20,0xDD,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x85,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x35,0x00,0x00,0x17,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x46,0x00,0x00,0x00,0x00,0x03,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x51,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xAF,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x00,0x00,0x00,0x36,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x29,0x00,0x00,0x00,0x00,0x5B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00, + 0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x1E,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x07,0x00,0x00,0x6E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xD3,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x90,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x4D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC2,0x90,0x90,0x90,0x90,0x90,0x90,0xC8,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0x03,0x00,0x00,0x00,0xBB,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x00,0x00,0x13,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x0C,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7,0x00, + 0x00,0x00,0x00,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x61,0x00,0x00,0x00,0x00,0xB1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x4D,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x71,0x00,0x00,0x00,0x00,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x02,0x00,0x00,0x00,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x06,0x00,0x00,0x00,0xA2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7,0x00,0x00,0x00,0x14,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x21,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00, + 0x00,0xB7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0xD5,0x9A,0x46,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x02,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x00,0x00,0x03,0xF7,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC4,0x00,0x00,0x00,0x00,0x00,0x0D,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x37,0x00,0x00,0x01,0xB8,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x5C,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x13, + 0x00,0x00,0x5A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0x04,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x5D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFB,0x9F,0x46,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x09,0xE4,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x16,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xBE,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x97,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x86,0x00,0x00,0x12,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x18,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x05,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x47,0x00,0x00,0x97,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x01,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x43,0x00,0x00,0x00,0x00,0x09,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x08,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x6A,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xD8,0x00,0x00,0x53,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA8,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9D,0x00,0x09,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x37,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x01,0x84,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x50,0x00,0x00,0x00,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x0C,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFA,0xB1,0x5C,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x2D,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x52,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFC,0x09,0x00,0x00,0x00,0x00,0x49,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x0A,0x41,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x92,0xE1,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x1D,0x00,0x00,0x3E, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x0A,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x28,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xA1,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x54,0x40,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x67,0x00,0xED,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x0F,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x00,0x0B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2E,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x3D,0x78,0xB3,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xB5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x00,0x00,0x03,0xF7, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x2F,0xFB,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x02,0x00,0x00,0x00,0x00,0x00,0xA1,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0x83,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x47,0xB2,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0x01,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xAF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x7A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB9,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDA,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x63,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x02,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x96, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x4F,0x91,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x02,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x56,0x00,0x00,0x00,0x00,0x00, + 0x00,0x38,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6D,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x08,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x4A,0x06,0x00,0x00,0x04,0x67,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFE,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x29,0xF7,0xFF,0xE6,0x4A,0x07,0x00,0x00,0x00,0x00,0x00,0x01,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1,0x02, + 0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x0B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x54,0x05,0x00,0x00,0x06,0x46,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x1D,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE5,0xB6,0xB6,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xAB,0x00,0x00,0x05,0xD5,0xFF,0xFF,0xFF,0xFE,0xEF,0xB0,0x69,0x69,0x67,0x67,0xA8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE0,0xB6,0xB6,0xE3,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8D,0x00,0x00,0x00, + 0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFD,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xF4, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x9E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x32,0x00,0x00,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00, + 0x00,0x06,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD3,0x18,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xF3,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x9B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0x01,0x00,0x00,0x22,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x22,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x2D,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE5,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x32,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x04,0x77,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x83,0x01,0x00,0x00,0x00,0x08,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xC9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD2,0x1E,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xD2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x83,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x96, + 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x25,0xA8,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xB2,0x2F,0x01,0x00, + 0x00,0x00,0x00,0x04,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x70,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x67,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x46,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,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,0x00,0x00,0xA3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x3F,0x3F,0x3F,0x3F,0x3F,0x40,0x26,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x61,0x9D,0xE0,0xDF,0xDF,0xDF,0xDF,0xDE,0x91,0x54,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3C,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x3F,0x3F,0x3F, + 0x3F,0x3F,0x3F,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x53,0x8F,0xC7,0xDF,0xDF,0xE5,0xE3,0xD7,0x8E,0x62,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x3F,0x3F,0x3F,0x3F,0x3F,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x89,0x93,0xDF,0xDF,0xDF,0xDC,0x8F,0x82,0x3F,0x05,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x3D,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xFC,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0xBD,0x94,0x94,0x94,0xB9,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xF9,0x9B,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xA9,0xB0,0xDD,0xFF,0xFF,0xFF,0xBD,0xAF,0x5F,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; +const lv_image_dsc_t ui_img_text_218x40_png = { + .header.w = 218, + .header.h = 40, + .data_size = sizeof(ui_img_text_218x40_png_data), + .header.cf = LV_COLOR_FORMAT_NATIVE_WITH_ALPHA, + .header.magic = LV_IMAGE_HEADER_MAGIC, + .data = ui_img_text_218x40_png_data +}; + diff --git a/main/Application/Tasks/GUI/Export/project.info b/main/Application/Tasks/GUI/Export/project.info new file mode 100644 index 0000000..ff358ab --- /dev/null +++ b/main/Application/Tasks/GUI/Export/project.info @@ -0,0 +1,9 @@ +{ + "project_name": "SquareLine_Project.spj", + "datetime": "2025-12-31T13:28:21.9912286+01:00", + "editor_version": "1.5.4", + "project_version": 83, + "user": "Kampert Daniel", + "export_datetime": "2025-12-31T13:28:22.6736847+01:00", + "export_user": "Kampert Daniel" +} diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.c b/main/Application/Tasks/GUI/Export/screens/ui_Info.c new file mode 100644 index 0000000..4cb6708 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.c @@ -0,0 +1,757 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include "../ui.h" + +lv_obj_t * ui_Info = NULL; +lv_obj_t * ui_Panel_Info_Header = NULL; +lv_obj_t * ui_Label_Info_Header = NULL; +lv_obj_t * ui_Panel_Info_Content = NULL; +lv_obj_t * ui_Panel_Device = NULL; +lv_obj_t * ui_Label_Info_Device = NULL; +lv_obj_t * ui_Container_Info_Device = NULL; +lv_obj_t * ui_Info_Container4 = NULL; +lv_obj_t * ui_Label_Info_MAC_Name = NULL; +lv_obj_t * ui_Label_Info_IP_Name = NULL; +lv_obj_t * ui_Info_Container5 = NULL; +lv_obj_t * ui_Label_Info_MAC = NULL; +lv_obj_t * ui_Label_Info_IP = NULL; +lv_obj_t * ui_Panel_Battery = NULL; +lv_obj_t * ui_Label_Info_Battery = NULL; +lv_obj_t * ui_Container_Battery = NULL; +lv_obj_t * ui_Info_Container2 = NULL; +lv_obj_t * ui_Label_Info_Battery_Status_Name = NULL; +lv_obj_t * ui_Label_Info_Battery_Voltage_Name = NULL; +lv_obj_t * ui_Label_Info_Battery_Remaining_Name = NULL; +lv_obj_t * ui_Info_Container3 = NULL; +lv_obj_t * ui_Label_Info_Battery_Status = NULL; +lv_obj_t * ui_Label_Info_Battery_Voltage = NULL; +lv_obj_t * ui_Label_Info_Battery_Remaining = NULL; +lv_obj_t * ui_Info_Bar2 = NULL; +lv_obj_t * ui_Panel_Lepton = NULL; +lv_obj_t * ui_Label_Info_Lepton = NULL; +lv_obj_t * ui_Container_Lepton = NULL; +lv_obj_t * ui_Info_Container1 = NULL; +lv_obj_t * ui_Label_Info_Lepton_Serial_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_Part_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_Revision_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_Uptime_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_FPA_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_AUX_Name = NULL; +lv_obj_t * ui_Info_Container7 = NULL; +lv_obj_t * ui_Label_Info_Lepton_Serial = NULL; +lv_obj_t * ui_Label_Info_Lepton_Part = NULL; +lv_obj_t * ui_Label_Info_Lepton_Revision = NULL; +lv_obj_t * ui_Label_Info_Lepton_Uptime = NULL; +lv_obj_t * ui_Label_Info_Lepton_FPA = NULL; +lv_obj_t * ui_Label_Info_Lepton_AUX = NULL; +// event funtions +void ui_event_Info(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { + lv_indev_wait_release(lv_indev_active()); + _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); + } + if(event_code == LV_EVENT_SCREEN_LOADED) { + ScreenInfoLoaded(e); + } +} + +// build funtions + +void ui_Info_screen_init(void) +{ + ui_Info = lv_obj_create(NULL); + lv_obj_remove_flag(ui_Info, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_bg_color(ui_Info, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Info, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Panel_Info_Header = lv_obj_create(ui_Info); + lv_obj_set_width(ui_Panel_Info_Header, 320); + lv_obj_set_height(ui_Panel_Info_Header, 30); + lv_obj_set_x(ui_Panel_Info_Header, 1); + lv_obj_set_y(ui_Panel_Info_Header, 1); + lv_obj_set_align(ui_Panel_Info_Header, LV_ALIGN_TOP_MID); + lv_obj_remove_flag(ui_Panel_Info_Header, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_radius(ui_Panel_Info_Header, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Panel_Info_Header, lv_color_hex(0x7B3FF0), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Panel_Info_Header, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Panel_Info_Header, lv_color_hex(0x7B3FF0), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Panel_Info_Header, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Header = lv_label_create(ui_Panel_Info_Header); + lv_obj_set_width(ui_Label_Info_Header, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Header, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Header, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Header, "SYSTEM INFORMATION"); + lv_obj_remove_flag(ui_Label_Info_Header, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Header, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Header, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Header, &lv_font_montserrat_14, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Panel_Info_Content = lv_obj_create(ui_Info); + lv_obj_set_width(ui_Panel_Info_Content, 320); + lv_obj_set_height(ui_Panel_Info_Content, 210); + lv_obj_set_x(ui_Panel_Info_Content, 0); + lv_obj_set_y(ui_Panel_Info_Content, 30); + lv_obj_set_align(ui_Panel_Info_Content, LV_ALIGN_TOP_MID); + lv_obj_set_flex_flow(ui_Panel_Info_Content, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Panel_Info_Content, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_set_scrollbar_mode(ui_Panel_Info_Content, LV_SCROLLBAR_MODE_ON); + lv_obj_set_scroll_dir(ui_Panel_Info_Content, LV_DIR_VER); + lv_obj_set_style_radius(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Panel_Info_Content, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Panel_Info_Content, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Panel_Info_Content, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Panel_Info_Content, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Panel_Info_Content, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Panel_Info_Content, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + + lv_obj_set_style_radius(ui_Panel_Info_Content, 2, LV_PART_SCROLLBAR | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Panel_Info_Content, lv_color_hex(0x7B3FF0), LV_PART_SCROLLBAR | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Panel_Info_Content, 255, LV_PART_SCROLLBAR | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Panel_Info_Content, 0, LV_PART_SCROLLBAR | LV_STATE_DEFAULT); + + ui_Panel_Device = lv_obj_create(ui_Panel_Info_Content); + lv_obj_set_width(ui_Panel_Device, 300); + lv_obj_set_height(ui_Panel_Device, 100); + lv_obj_set_align(ui_Panel_Device, LV_ALIGN_CENTER); + lv_obj_set_flex_flow(ui_Panel_Device, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Panel_Device, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Panel_Device, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | + LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | + LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_radius(ui_Panel_Device, 6, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Panel_Device, lv_color_hex(0x252525), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Panel_Device, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Panel_Device, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Panel_Device, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Panel_Device, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Panel_Device, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Device = lv_label_create(ui_Panel_Device); + lv_obj_set_height(ui_Label_Info_Device, lv_pct(15)); + lv_obj_set_width(ui_Label_Info_Device, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Device, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Device, "DEVICE"); + lv_obj_remove_flag(ui_Label_Info_Device, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Device, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Device, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Device, &lv_font_montserrat_14, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Info_Device = lv_obj_create(ui_Panel_Device); + lv_obj_remove_style_all(ui_Container_Info_Device); + lv_obj_set_width(ui_Container_Info_Device, lv_pct(100)); + lv_obj_set_height(ui_Container_Info_Device, lv_pct(50)); + lv_obj_set_align(ui_Container_Info_Device, LV_ALIGN_TOP_MID); + lv_obj_set_flex_flow(ui_Container_Info_Device, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(ui_Container_Info_Device, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Container_Info_Device, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_pad_left(ui_Container_Info_Device, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Container_Info_Device, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Container_Info_Device, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Container_Info_Device, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Info_Container4 = lv_obj_create(ui_Container_Info_Device); + lv_obj_remove_style_all(ui_Info_Container4); + lv_obj_set_width(ui_Info_Container4, lv_pct(50)); + lv_obj_set_height(ui_Info_Container4, lv_pct(100)); + lv_obj_set_align(ui_Info_Container4, LV_ALIGN_LEFT_MID); + lv_obj_set_flex_flow(ui_Info_Container4, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Info_Container4, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Info_Container4, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Label_Info_MAC_Name = lv_label_create(ui_Info_Container4); + lv_obj_set_width(ui_Label_Info_MAC_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_MAC_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_MAC_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_MAC_Name, "MAC:"); + lv_obj_remove_flag(ui_Label_Info_MAC_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_MAC_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_MAC_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_MAC_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_MAC_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_MAC_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_MAC_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_MAC_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_IP_Name = lv_label_create(ui_Info_Container4); + lv_obj_set_width(ui_Label_Info_IP_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_IP_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_IP_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_IP_Name, "IP:"); + lv_obj_remove_flag(ui_Label_Info_IP_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_IP_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_IP_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_IP_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_IP_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_IP_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_IP_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_IP_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Info_Container5 = lv_obj_create(ui_Container_Info_Device); + lv_obj_remove_style_all(ui_Info_Container5); + lv_obj_set_width(ui_Info_Container5, lv_pct(50)); + lv_obj_set_height(ui_Info_Container5, lv_pct(100)); + lv_obj_set_align(ui_Info_Container5, LV_ALIGN_RIGHT_MID); + lv_obj_set_flex_flow(ui_Info_Container5, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Info_Container5, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_END); + lv_obj_remove_flag(ui_Info_Container5, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Label_Info_MAC = lv_label_create(ui_Info_Container5); + lv_obj_set_width(ui_Label_Info_MAC, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_MAC, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_MAC, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_MAC, "AA:BB:CC:DD:EE:FF"); + lv_obj_remove_flag(ui_Label_Info_MAC, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_MAC, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_MAC, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_MAC, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_MAC, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_MAC, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_MAC, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_MAC, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_MAC, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_IP = lv_label_create(ui_Info_Container5); + lv_obj_set_width(ui_Label_Info_IP, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_IP, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_IP, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_IP, "127.0.0.1\n"); + lv_obj_remove_flag(ui_Label_Info_IP, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_IP, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_IP, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_IP, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_IP, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_IP, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_IP, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_IP, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_IP, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Panel_Battery = lv_obj_create(ui_Panel_Info_Content); + lv_obj_set_width(ui_Panel_Battery, 300); + lv_obj_set_height(ui_Panel_Battery, 100); + lv_obj_set_align(ui_Panel_Battery, LV_ALIGN_CENTER); + lv_obj_set_flex_flow(ui_Panel_Battery, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Panel_Battery, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Panel_Battery, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_radius(ui_Panel_Battery, 6, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Panel_Battery, lv_color_hex(0x252525), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Panel_Battery, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Panel_Battery, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Panel_Battery, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Panel_Battery, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Panel_Battery, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Battery = lv_label_create(ui_Panel_Battery); + lv_obj_set_height(ui_Label_Info_Battery, lv_pct(15)); + lv_obj_set_width(ui_Label_Info_Battery, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Battery, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Battery, "BATTERY"); + lv_obj_remove_flag(ui_Label_Info_Battery, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Battery, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Battery, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery, &lv_font_montserrat_14, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Battery = lv_obj_create(ui_Panel_Battery); + lv_obj_remove_style_all(ui_Container_Battery); + lv_obj_set_width(ui_Container_Battery, lv_pct(100)); + lv_obj_set_height(ui_Container_Battery, lv_pct(50)); + lv_obj_set_align(ui_Container_Battery, LV_ALIGN_TOP_MID); + lv_obj_set_flex_flow(ui_Container_Battery, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(ui_Container_Battery, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Container_Battery, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_pad_left(ui_Container_Battery, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Container_Battery, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Container_Battery, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Container_Battery, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Info_Container2 = lv_obj_create(ui_Container_Battery); + lv_obj_remove_style_all(ui_Info_Container2); + lv_obj_set_width(ui_Info_Container2, lv_pct(50)); + lv_obj_set_height(ui_Info_Container2, lv_pct(100)); + lv_obj_set_align(ui_Info_Container2, LV_ALIGN_LEFT_MID); + lv_obj_set_flex_flow(ui_Info_Container2, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Info_Container2, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Info_Container2, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Label_Info_Battery_Status_Name = lv_label_create(ui_Info_Container2); + lv_obj_set_width(ui_Label_Info_Battery_Status_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Battery_Status_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Battery_Status_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Battery_Status_Name, "Status:"); + lv_obj_remove_flag(ui_Label_Info_Battery_Status_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Battery_Status_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Battery_Status_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Status_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Battery_Status_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Battery_Status_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Battery_Status_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Battery_Status_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Battery_Voltage_Name = lv_label_create(ui_Info_Container2); + lv_obj_set_width(ui_Label_Info_Battery_Voltage_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Battery_Voltage_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Battery_Voltage_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Battery_Voltage_Name, "Voltage:"); + lv_obj_remove_flag(ui_Label_Info_Battery_Voltage_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Battery_Voltage_Name, lv_color_hex(0x888888), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Battery_Voltage_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Voltage_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Battery_Voltage_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Battery_Voltage_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Battery_Voltage_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Battery_Voltage_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Battery_Remaining_Name = lv_label_create(ui_Info_Container2); + lv_obj_set_width(ui_Label_Info_Battery_Remaining_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Battery_Remaining_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Battery_Remaining_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Battery_Remaining_Name, "Remaining:"); + lv_obj_remove_flag(ui_Label_Info_Battery_Remaining_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Battery_Remaining_Name, lv_color_hex(0x888888), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Battery_Remaining_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Remaining_Name, &lv_font_montserrat_10, + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Battery_Remaining_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Battery_Remaining_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Battery_Remaining_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Battery_Remaining_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Info_Container3 = lv_obj_create(ui_Container_Battery); + lv_obj_remove_style_all(ui_Info_Container3); + lv_obj_set_width(ui_Info_Container3, lv_pct(50)); + lv_obj_set_height(ui_Info_Container3, lv_pct(100)); + lv_obj_set_align(ui_Info_Container3, LV_ALIGN_RIGHT_MID); + lv_obj_set_flex_flow(ui_Info_Container3, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Info_Container3, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_END); + lv_obj_remove_flag(ui_Info_Container3, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Label_Info_Battery_Status = lv_label_create(ui_Info_Container3); + lv_obj_set_width(ui_Label_Info_Battery_Status, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Battery_Status, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Battery_Status, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Battery_Status, "Nothing"); + lv_obj_remove_flag(ui_Label_Info_Battery_Status, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Battery_Status, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Battery_Status, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Battery_Status, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Status, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Battery_Status, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Battery_Status, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Battery_Status, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Battery_Status, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Battery_Voltage = lv_label_create(ui_Info_Container3); + lv_obj_set_width(ui_Label_Info_Battery_Voltage, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Battery_Voltage, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Battery_Voltage, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Battery_Voltage, "4.2 V"); + lv_obj_remove_flag(ui_Label_Info_Battery_Voltage, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Battery_Voltage, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Battery_Voltage, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Battery_Voltage, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Voltage, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Battery_Voltage, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Battery_Voltage, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Battery_Voltage, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Battery_Voltage, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Battery_Remaining = lv_label_create(ui_Info_Container3); + lv_obj_set_width(ui_Label_Info_Battery_Remaining, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Battery_Remaining, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Battery_Remaining, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Battery_Remaining, "75%"); + lv_obj_remove_flag(ui_Label_Info_Battery_Remaining, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Battery_Remaining, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Battery_Remaining, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Battery_Remaining, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Remaining, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Battery_Remaining, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Battery_Remaining, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Battery_Remaining, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Battery_Remaining, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Info_Bar2 = lv_bar_create(ui_Panel_Battery); + lv_bar_set_value(ui_Info_Bar2, 100, LV_ANIM_OFF); + lv_bar_set_start_value(ui_Info_Bar2, 0, LV_ANIM_OFF); + lv_obj_set_height(ui_Info_Bar2, 15); + lv_obj_set_width(ui_Info_Bar2, lv_pct(100)); + lv_obj_set_align(ui_Info_Bar2, LV_ALIGN_BOTTOM_MID); + lv_obj_set_style_bg_color(ui_Info_Bar2, lv_color_hex(0x333333), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Info_Bar2, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Info_Bar2, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Info_Bar2, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Info_Bar2, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Info_Bar2, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + lv_obj_set_style_radius(ui_Info_Bar2, 4, LV_PART_INDICATOR | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Info_Bar2, lv_color_hex(0xFF0000), LV_PART_INDICATOR | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Info_Bar2, 255, LV_PART_INDICATOR | LV_STATE_DEFAULT); + lv_obj_set_style_bg_grad_color(ui_Info_Bar2, lv_color_hex(0x61FF00), LV_PART_INDICATOR | LV_STATE_DEFAULT); + lv_obj_set_style_bg_grad_dir(ui_Info_Bar2, LV_GRAD_DIR_HOR, LV_PART_INDICATOR | LV_STATE_DEFAULT); + + //Compensating for LVGL9.1 draw crash with bar/slider max value when top-padding is nonzero and right-padding is 0 + if(lv_obj_get_style_pad_top(ui_Info_Bar2, LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_Info_Bar2, + lv_obj_get_style_pad_right(ui_Info_Bar2, LV_PART_MAIN) + 1, LV_PART_MAIN); + ui_Panel_Lepton = lv_obj_create(ui_Panel_Info_Content); + lv_obj_set_width(ui_Panel_Lepton, 300); + lv_obj_set_height(ui_Panel_Lepton, 140); + lv_obj_set_x(ui_Panel_Lepton, 0); + lv_obj_set_y(ui_Panel_Lepton, 80); + lv_obj_set_align(ui_Panel_Lepton, LV_ALIGN_CENTER); + lv_obj_set_flex_flow(ui_Panel_Lepton, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Panel_Lepton, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Panel_Lepton, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | + LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | + LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_radius(ui_Panel_Lepton, 6, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Panel_Lepton, lv_color_hex(0x252525), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Panel_Lepton, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Panel_Lepton, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Panel_Lepton, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Panel_Lepton, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Panel_Lepton, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton = lv_label_create(ui_Panel_Lepton); + lv_obj_set_height(ui_Label_Info_Lepton, lv_pct(15)); + lv_obj_set_width(ui_Label_Info_Lepton, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton, "LEPTON\n"); + lv_obj_remove_flag(ui_Label_Info_Lepton, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton, &lv_font_montserrat_14, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Lepton = lv_obj_create(ui_Panel_Lepton); + lv_obj_remove_style_all(ui_Container_Lepton); + lv_obj_set_width(ui_Container_Lepton, lv_pct(100)); + lv_obj_set_height(ui_Container_Lepton, lv_pct(100)); + lv_obj_set_align(ui_Container_Lepton, LV_ALIGN_TOP_MID); + lv_obj_set_flex_flow(ui_Container_Lepton, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(ui_Container_Lepton, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Container_Lepton, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Info_Container1 = lv_obj_create(ui_Container_Lepton); + lv_obj_remove_style_all(ui_Info_Container1); + lv_obj_set_width(ui_Info_Container1, lv_pct(50)); + lv_obj_set_height(ui_Info_Container1, lv_pct(100)); + lv_obj_set_align(ui_Info_Container1, LV_ALIGN_CENTER); + lv_obj_set_flex_flow(ui_Info_Container1, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Info_Container1, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_remove_flag(ui_Info_Container1, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Label_Info_Lepton_Serial_Name = lv_label_create(ui_Info_Container1); + lv_obj_set_width(ui_Label_Info_Lepton_Serial_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton_Serial_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_Serial_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_Serial_Name, "Serial:"); + lv_obj_remove_flag(ui_Label_Info_Lepton_Serial_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Serial_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Serial_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Serial_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Serial_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_Part_Name = lv_label_create(ui_Info_Container1); + lv_obj_set_width(ui_Label_Info_Lepton_Part_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton_Part_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_Part_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_Part_Name, "Part Number:"); + lv_obj_remove_flag(ui_Label_Info_Lepton_Part_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Part_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Part_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Part_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Part_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Part_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Part_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Part_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_Revision_Name = lv_label_create(ui_Info_Container1); + lv_obj_set_width(ui_Label_Info_Lepton_Revision_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton_Revision_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_Revision_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_Revision_Name, "Software Revision:"); + lv_obj_remove_flag(ui_Label_Info_Lepton_Revision_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Revision_Name, lv_color_hex(0x888888), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Revision_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Revision_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Revision_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_Uptime_Name = lv_label_create(ui_Info_Container1); + lv_obj_set_width(ui_Label_Info_Lepton_Uptime_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton_Uptime_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_Uptime_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_Uptime_Name, "Uptime:"); + lv_obj_remove_flag(ui_Label_Info_Lepton_Uptime_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Uptime_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Uptime_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Uptime_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Uptime_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Uptime_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Uptime_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Uptime_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_FPA_Name = lv_label_create(ui_Info_Container1); + lv_obj_set_width(ui_Label_Info_Lepton_FPA_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton_FPA_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Label_Info_Lepton_FPA_Name, 0); + lv_obj_set_y(ui_Label_Info_Lepton_FPA_Name, 1); + lv_obj_set_align(ui_Label_Info_Lepton_FPA_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_FPA_Name, "FPA Temperature:"); + lv_obj_remove_flag(ui_Label_Info_Lepton_FPA_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_FPA_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_FPA_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_FPA_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_FPA_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_FPA_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_FPA_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_FPA_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_AUX_Name = lv_label_create(ui_Info_Container1); + lv_obj_set_width(ui_Label_Info_Lepton_AUX_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton_AUX_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_AUX_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_AUX_Name, "AUX Temperature:"); + lv_obj_remove_flag(ui_Label_Info_Lepton_AUX_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_AUX_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_AUX_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_AUX_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_AUX_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_AUX_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_AUX_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_AUX_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Info_Container7 = lv_obj_create(ui_Container_Lepton); + lv_obj_remove_style_all(ui_Info_Container7); + lv_obj_set_width(ui_Info_Container7, lv_pct(50)); + lv_obj_set_height(ui_Info_Container7, lv_pct(100)); + lv_obj_set_x(ui_Info_Container7, 172); + lv_obj_set_y(ui_Info_Container7, -2); + lv_obj_set_align(ui_Info_Container7, LV_ALIGN_CENTER); + lv_obj_set_flex_flow(ui_Info_Container7, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Info_Container7, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_END); + lv_obj_remove_flag(ui_Info_Container7, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Label_Info_Lepton_Serial = lv_label_create(ui_Info_Container7); + lv_obj_set_width(ui_Label_Info_Lepton_Serial, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Lepton_Serial, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_Serial, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_Serial, "Nothing"); + lv_obj_remove_flag(ui_Label_Info_Lepton_Serial, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Serial, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Serial, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Lepton_Serial, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Serial, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Serial, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_Part = lv_label_create(ui_Info_Container7); + lv_obj_set_width(ui_Label_Info_Lepton_Part, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Lepton_Part, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_Part, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_Part, "Nothing"); + lv_obj_remove_flag(ui_Label_Info_Lepton_Part, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Part, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Part, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Lepton_Part, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Part, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Part, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Part, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Part, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Part, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_Revision = lv_label_create(ui_Info_Container7); + lv_obj_set_width(ui_Label_Info_Lepton_Revision, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Lepton_Revision, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_Revision, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_Revision, "Nothing"); + lv_obj_remove_flag(ui_Label_Info_Lepton_Revision, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Revision, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Revision, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Lepton_Revision, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Revision, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Revision, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_Uptime = lv_label_create(ui_Info_Container7); + lv_obj_set_width(ui_Label_Info_Lepton_Uptime, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Lepton_Uptime, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_Uptime, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_Uptime, "0"); + lv_obj_remove_flag(ui_Label_Info_Lepton_Uptime, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Uptime, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Uptime, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Lepton_Uptime, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Uptime, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Uptime, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Uptime, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Uptime, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Uptime, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_FPA = lv_label_create(ui_Info_Container7); + lv_obj_set_width(ui_Label_Info_Lepton_FPA, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Lepton_FPA, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_FPA, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_FPA, "0"); + lv_obj_remove_flag(ui_Label_Info_Lepton_FPA, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_FPA, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_FPA, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Lepton_FPA, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_FPA, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_FPA, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_FPA, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_FPA, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_FPA, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_AUX = lv_label_create(ui_Info_Container7); + lv_obj_set_width(ui_Label_Info_Lepton_AUX, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Lepton_AUX, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_AUX, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_AUX, "0\n"); + lv_obj_remove_flag(ui_Label_Info_Lepton_AUX, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_AUX, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_AUX, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Lepton_AUX, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_AUX, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_AUX, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_AUX, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_AUX, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_AUX, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + lv_obj_add_event_cb(ui_Info, ui_event_Info, LV_EVENT_ALL, NULL); + +} + +void ui_Info_screen_destroy(void) +{ + if(ui_Info) lv_obj_del(ui_Info); + + // NULL screen variables + ui_Info = NULL; + ui_Panel_Info_Header = NULL; + ui_Label_Info_Header = NULL; + ui_Panel_Info_Content = NULL; + ui_Panel_Device = NULL; + ui_Label_Info_Device = NULL; + ui_Container_Info_Device = NULL; + ui_Info_Container4 = NULL; + ui_Label_Info_MAC_Name = NULL; + ui_Label_Info_IP_Name = NULL; + ui_Info_Container5 = NULL; + ui_Label_Info_MAC = NULL; + ui_Label_Info_IP = NULL; + ui_Panel_Battery = NULL; + ui_Label_Info_Battery = NULL; + ui_Container_Battery = NULL; + ui_Info_Container2 = NULL; + ui_Label_Info_Battery_Status_Name = NULL; + ui_Label_Info_Battery_Voltage_Name = NULL; + ui_Label_Info_Battery_Remaining_Name = NULL; + ui_Info_Container3 = NULL; + ui_Label_Info_Battery_Status = NULL; + ui_Label_Info_Battery_Voltage = NULL; + ui_Label_Info_Battery_Remaining = NULL; + ui_Info_Bar2 = NULL; + ui_Panel_Lepton = NULL; + ui_Label_Info_Lepton = NULL; + ui_Container_Lepton = NULL; + ui_Info_Container1 = NULL; + ui_Label_Info_Lepton_Serial_Name = NULL; + ui_Label_Info_Lepton_Part_Name = NULL; + ui_Label_Info_Lepton_Revision_Name = NULL; + ui_Label_Info_Lepton_Uptime_Name = NULL; + ui_Label_Info_Lepton_FPA_Name = NULL; + ui_Label_Info_Lepton_AUX_Name = NULL; + ui_Info_Container7 = NULL; + ui_Label_Info_Lepton_Serial = NULL; + ui_Label_Info_Lepton_Part = NULL; + ui_Label_Info_Lepton_Revision = NULL; + ui_Label_Info_Lepton_Uptime = NULL; + ui_Label_Info_Lepton_FPA = NULL; + ui_Label_Info_Lepton_AUX = NULL; + +} diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.h b/main/Application/Tasks/GUI/Export/screens/ui_Info.h new file mode 100644 index 0000000..81829b0 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.h @@ -0,0 +1,66 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#ifndef UI_INFO_H +#define UI_INFO_H + +#ifdef __cplusplus +extern "C" { +#endif + +// SCREEN: ui_Info +extern void ui_Info_screen_init(void); +extern void ui_Info_screen_destroy(void); +extern void ui_event_Info(lv_event_t * e); +extern lv_obj_t * ui_Info; +extern lv_obj_t * ui_Panel_Info_Header; +extern lv_obj_t * ui_Label_Info_Header; +extern lv_obj_t * ui_Panel_Info_Content; +extern lv_obj_t * ui_Panel_Device; +extern lv_obj_t * ui_Label_Info_Device; +extern lv_obj_t * ui_Container_Info_Device; +extern lv_obj_t * ui_Info_Container4; +extern lv_obj_t * ui_Label_Info_MAC_Name; +extern lv_obj_t * ui_Label_Info_IP_Name; +extern lv_obj_t * ui_Info_Container5; +extern lv_obj_t * ui_Label_Info_MAC; +extern lv_obj_t * ui_Label_Info_IP; +extern lv_obj_t * ui_Panel_Battery; +extern lv_obj_t * ui_Label_Info_Battery; +extern lv_obj_t * ui_Container_Battery; +extern lv_obj_t * ui_Info_Container2; +extern lv_obj_t * ui_Label_Info_Battery_Status_Name; +extern lv_obj_t * ui_Label_Info_Battery_Voltage_Name; +extern lv_obj_t * ui_Label_Info_Battery_Remaining_Name; +extern lv_obj_t * ui_Info_Container3; +extern lv_obj_t * ui_Label_Info_Battery_Status; +extern lv_obj_t * ui_Label_Info_Battery_Voltage; +extern lv_obj_t * ui_Label_Info_Battery_Remaining; +extern lv_obj_t * ui_Info_Bar2; +extern lv_obj_t * ui_Panel_Lepton; +extern lv_obj_t * ui_Label_Info_Lepton; +extern lv_obj_t * ui_Container_Lepton; +extern lv_obj_t * ui_Info_Container1; +extern lv_obj_t * ui_Label_Info_Lepton_Serial_Name; +extern lv_obj_t * ui_Label_Info_Lepton_Part_Name; +extern lv_obj_t * ui_Label_Info_Lepton_Revision_Name; +extern lv_obj_t * ui_Label_Info_Lepton_Uptime_Name; +extern lv_obj_t * ui_Label_Info_Lepton_FPA_Name; +extern lv_obj_t * ui_Label_Info_Lepton_AUX_Name; +extern lv_obj_t * ui_Info_Container7; +extern lv_obj_t * ui_Label_Info_Lepton_Serial; +extern lv_obj_t * ui_Label_Info_Lepton_Part; +extern lv_obj_t * ui_Label_Info_Lepton_Revision; +extern lv_obj_t * ui_Label_Info_Lepton_Uptime; +extern lv_obj_t * ui_Label_Info_Lepton_FPA; +extern lv_obj_t * ui_Label_Info_Lepton_AUX; +// CUSTOM VARIABLES + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif + diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.c b/main/Application/Tasks/GUI/Export/screens/ui_Main.c new file mode 100644 index 0000000..9c10754 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.c @@ -0,0 +1,440 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include "../ui.h" + +lv_obj_t * ui_Main = NULL; +lv_obj_t * ui_Container_Main_StatusBar = NULL; +lv_obj_t * ui_Image_Main_WiFi = NULL; +lv_obj_t * ui_Image_Main_Bluetooth = NULL; +lv_obj_t * ui_Image_Main_SDCard = NULL; +lv_obj_t * ui_Label_Main_Time = NULL; +lv_obj_t * ui_Image_Main_Battery = NULL; +lv_obj_t * ui_Label_Main_Battery_Remaining = NULL; +lv_obj_t * ui_Label_Main_MinTemp = NULL; +lv_obj_t * ui_Label_Main_MaxTemp = NULL; +lv_obj_t * ui_Container_Main_Thermal = NULL; +lv_obj_t * ui_Image_Thermal = NULL; +lv_obj_t * ui_Image_Main_Thermal_ROI = NULL; +lv_obj_t * ui_Label_Main_Thermal_Crosshair = NULL; +lv_obj_t * ui_Label_Main_Thermal_PixelTemperature = NULL; +lv_obj_t * ui_Container_Gradient = NULL; +lv_obj_t * ui_Label_TempScaleMax = NULL; +lv_obj_t * ui_Image_Gradient = NULL; +lv_obj_t * ui_Label_TempScaleMin = NULL; +lv_obj_t * ui_Container_Main_Buttons = NULL; +lv_obj_t * ui_Button_Main_WiFi = NULL; +lv_obj_t * ui_Label_Main_Button_WiFi = NULL; +lv_obj_t * ui_Button_Main_ROI = NULL; +lv_obj_t * ui_Label_Main_Button_ROI = NULL; +lv_obj_t * ui_Button_Main_Info = NULL; +lv_obj_t * ui_Label_Main_Button_Info = NULL; +lv_obj_t * ui_Button_Main_Menu = NULL; +lv_obj_t * ui_Label_Main_Button_Menu = NULL; +// event funtions +void ui_event_Main(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_SCREEN_LOADED) { + ScreenMainLoaded(e); + } +} + +void ui_event_Button_Main_WiFi(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_CLICKED) { + ButtonMainWiFiClicked(e); + } +} + +void ui_event_Button_Main_Info(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_CLICKED) { + _ui_screen_change(&ui_Info, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Info_screen_init); + } +} + +void ui_event_Button_Main_Menu(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_CLICKED) { + _ui_screen_change(&ui_Menu, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Menu_screen_init); + } +} + +// build funtions + +void ui_Main_screen_init(void) +{ + ui_Main = lv_obj_create(NULL); + lv_obj_remove_flag(ui_Main, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_flex_flow(ui_Main, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Main, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_set_style_bg_color(ui_Main, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Main, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Main_StatusBar = lv_obj_create(ui_Main); + lv_obj_remove_style_all(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Container_Main_StatusBar, 320); + lv_obj_set_height(ui_Container_Main_StatusBar, lv_pct(8)); + lv_obj_set_align(ui_Container_Main_StatusBar, LV_ALIGN_TOP_MID); + lv_obj_remove_flag(ui_Container_Main_StatusBar, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_bg_color(ui_Container_Main_StatusBar, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Container_Main_StatusBar, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_image_opa(ui_Container_Main_StatusBar, 180, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Main_WiFi = lv_label_create(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Image_Main_WiFi, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Image_Main_WiFi, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Image_Main_WiFi, 5); + lv_obj_set_y(ui_Image_Main_WiFi, 0); + lv_label_set_text(ui_Image_Main_WiFi, "W"); + lv_obj_remove_flag(ui_Image_Main_WiFi, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0xFF0000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Image_Main_WiFi, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Image_Main_WiFi, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Main_Bluetooth = lv_label_create(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Image_Main_Bluetooth, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Image_Main_Bluetooth, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Image_Main_Bluetooth, 25); + lv_obj_set_y(ui_Image_Main_Bluetooth, 0); + lv_label_set_text(ui_Image_Main_Bluetooth, "B"); + lv_obj_remove_flag(ui_Image_Main_Bluetooth, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Image_Main_Bluetooth, lv_color_hex(0xFF0000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Image_Main_Bluetooth, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Image_Main_Bluetooth, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Main_SDCard = lv_label_create(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Image_Main_SDCard, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Image_Main_SDCard, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Image_Main_SDCard, 45); + lv_obj_set_y(ui_Image_Main_SDCard, 0); + lv_label_set_text(ui_Image_Main_SDCard, "C"); + lv_obj_remove_flag(ui_Image_Main_SDCard, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Image_Main_SDCard, lv_color_hex(0xFF0000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Image_Main_SDCard, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Image_Main_SDCard, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Time = lv_label_create(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Label_Main_Time, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Time, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Label_Main_Time, 200); + lv_obj_set_y(ui_Label_Main_Time, 0); + lv_label_set_text(ui_Label_Main_Time, "12:34:56"); + lv_obj_remove_flag(ui_Label_Main_Time, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Main_Time, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Time, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_Time, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Main_Battery = lv_label_create(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Image_Main_Battery, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Image_Main_Battery, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Image_Main_Battery, 260); + lv_obj_set_y(ui_Image_Main_Battery, 0); + lv_label_set_text(ui_Image_Main_Battery, "B"); + lv_obj_remove_flag(ui_Image_Main_Battery, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Image_Main_Battery, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Image_Main_Battery, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Image_Main_Battery, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Battery_Remaining = lv_label_create(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Label_Main_Battery_Remaining, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Battery_Remaining, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Label_Main_Battery_Remaining, 290); + lv_obj_set_y(ui_Label_Main_Battery_Remaining, 0); + lv_label_set_text(ui_Label_Main_Battery_Remaining, "75%"); + lv_obj_set_style_text_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Battery_Remaining, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_Battery_Remaining, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_MinTemp = lv_label_create(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Label_Main_MinTemp, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_MinTemp, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Label_Main_MinTemp, 65); + lv_obj_set_y(ui_Label_Main_MinTemp, 0); + lv_obj_set_align(ui_Label_Main_MinTemp, LV_ALIGN_LEFT_MID); + lv_label_set_text(ui_Label_Main_MinTemp, "-99.99 °C"); + lv_obj_add_flag(ui_Label_Main_MinTemp, LV_OBJ_FLAG_HIDDEN); /// Flags + lv_obj_set_style_text_color(ui_Label_Main_MinTemp, lv_color_hex(0x004DFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_MinTemp, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_MinTemp, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_MaxTemp = lv_label_create(ui_Container_Main_StatusBar); + lv_obj_set_width(ui_Label_Main_MaxTemp, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_MaxTemp, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Label_Main_MaxTemp, 130); + lv_obj_set_y(ui_Label_Main_MaxTemp, 0); + lv_obj_set_align(ui_Label_Main_MaxTemp, LV_ALIGN_LEFT_MID); + lv_label_set_text(ui_Label_Main_MaxTemp, "+99.99 °C"); + lv_obj_add_flag(ui_Label_Main_MaxTemp, LV_OBJ_FLAG_HIDDEN); /// Flags + lv_obj_set_style_text_color(ui_Label_Main_MaxTemp, lv_color_hex(0xFF0000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_MaxTemp, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_MaxTemp, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Main_Thermal = lv_obj_create(ui_Main); + lv_obj_remove_style_all(ui_Container_Main_Thermal); + lv_obj_set_width(ui_Container_Main_Thermal, lv_pct(100)); + lv_obj_set_height(ui_Container_Main_Thermal, lv_pct(75)); + lv_obj_set_x(ui_Container_Main_Thermal, 0); + lv_obj_set_y(ui_Container_Main_Thermal, 10); + lv_obj_set_align(ui_Container_Main_Thermal, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Container_Main_Thermal, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Image_Thermal = lv_image_create(ui_Container_Main_Thermal); + lv_obj_set_width(ui_Image_Thermal, 240); + lv_obj_set_height(ui_Image_Thermal, 180); + lv_obj_set_x(ui_Image_Thermal, 10); + lv_obj_set_y(ui_Image_Thermal, 0); + lv_obj_set_align(ui_Image_Thermal, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Image_Thermal, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | + LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_radius(ui_Image_Thermal, 3, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Image_Thermal, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Image_Thermal, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_grad_color(ui_Image_Thermal, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_grad_dir(ui_Image_Thermal, LV_GRAD_DIR_HOR, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Main_Thermal_ROI = lv_obj_create(ui_Image_Thermal); + lv_obj_set_width(ui_Image_Main_Thermal_ROI, 60); + lv_obj_set_height(ui_Image_Main_Thermal_ROI, 60); + lv_obj_remove_flag(ui_Image_Main_Thermal_ROI, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_scrollbar_mode(ui_Image_Main_Thermal_ROI, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_bg_color(ui_Image_Main_Thermal_ROI, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Image_Main_Thermal_ROI, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Image_Main_Thermal_ROI, lv_color_hex(0x7B3FF0), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Image_Main_Thermal_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Image_Main_Thermal_ROI, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Thermal_Crosshair = lv_label_create(ui_Image_Thermal); + lv_obj_set_width(ui_Label_Main_Thermal_Crosshair, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Thermal_Crosshair, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Thermal_Crosshair, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Main_Thermal_Crosshair, "CH"); + lv_obj_set_style_text_font(ui_Label_Main_Thermal_Crosshair, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Thermal_PixelTemperature = lv_label_create(ui_Image_Thermal); + lv_obj_set_width(ui_Label_Main_Thermal_PixelTemperature, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Thermal_PixelTemperature, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Label_Main_Thermal_PixelTemperature, 0); + lv_obj_set_y(ui_Label_Main_Thermal_PixelTemperature, -15); + lv_obj_set_align(ui_Label_Main_Thermal_PixelTemperature, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Main_Thermal_PixelTemperature, "101.1"); + lv_obj_set_style_text_font(ui_Label_Main_Thermal_PixelTemperature, &lv_font_montserrat_14, + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Label_Main_Thermal_PixelTemperature, lv_color_hex(0xFFFFFF), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Label_Main_Thermal_PixelTemperature, 127, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Gradient = lv_obj_create(ui_Container_Main_Thermal); + lv_obj_remove_style_all(ui_Container_Gradient); + lv_obj_set_width(ui_Container_Gradient, 40); + lv_obj_set_height(ui_Container_Gradient, 190); + lv_obj_set_x(ui_Container_Gradient, -135); + lv_obj_set_y(ui_Container_Gradient, 0); + lv_obj_set_align(ui_Container_Gradient, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Container_Gradient, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Label_TempScaleMax = lv_label_create(ui_Container_Gradient); + lv_obj_set_height(ui_Label_TempScaleMax, 20); + lv_obj_set_width(ui_Label_TempScaleMax, lv_pct(100)); + lv_obj_set_x(ui_Label_TempScaleMax, 0); + lv_obj_set_y(ui_Label_TempScaleMax, -80); + lv_obj_set_align(ui_Label_TempScaleMax, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_TempScaleMax, "Max"); + lv_obj_set_style_text_color(ui_Label_TempScaleMax, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_TempScaleMax, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_TempScaleMax, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_decor(ui_Label_TempScaleMax, LV_TEXT_DECOR_NONE, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_TempScaleMax, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Gradient = lv_image_create(ui_Container_Gradient); + lv_obj_set_height(ui_Image_Gradient, 150); + lv_obj_set_width(ui_Image_Gradient, lv_pct(50)); + lv_obj_set_align(ui_Image_Gradient, LV_ALIGN_CENTER); + lv_obj_add_flag(ui_Image_Gradient, LV_OBJ_FLAG_CLICKABLE); /// Flags + lv_obj_remove_flag(ui_Image_Gradient, LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_radius(ui_Image_Gradient, 3, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Image_Gradient, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Image_Gradient, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_grad_color(ui_Image_Gradient, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_grad_dir(ui_Image_Gradient, LV_GRAD_DIR_VER, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_TempScaleMin = lv_label_create(ui_Container_Gradient); + lv_obj_set_height(ui_Label_TempScaleMin, 20); + lv_obj_set_width(ui_Label_TempScaleMin, lv_pct(100)); + lv_obj_set_x(ui_Label_TempScaleMin, 0); + lv_obj_set_y(ui_Label_TempScaleMin, 90); + lv_obj_set_align(ui_Label_TempScaleMin, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_TempScaleMin, "Min"); + lv_obj_set_style_text_color(ui_Label_TempScaleMin, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_TempScaleMin, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_TempScaleMin, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_TempScaleMin, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Main_Buttons = lv_obj_create(ui_Main); + lv_obj_remove_style_all(ui_Container_Main_Buttons); + lv_obj_set_width(ui_Container_Main_Buttons, lv_pct(100)); + lv_obj_set_height(ui_Container_Main_Buttons, lv_pct(10)); + lv_obj_set_x(ui_Container_Main_Buttons, 11); + lv_obj_set_y(ui_Container_Main_Buttons, 97); + lv_obj_set_align(ui_Container_Main_Buttons, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Container_Main_Buttons, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Button_Main_WiFi = lv_button_create(ui_Container_Main_Buttons); + lv_obj_set_width(ui_Button_Main_WiFi, 50); + lv_obj_set_height(ui_Button_Main_WiFi, lv_pct(95)); + lv_obj_set_x(ui_Button_Main_WiFi, -20); + lv_obj_set_y(ui_Button_Main_WiFi, 0); + lv_obj_set_align(ui_Button_Main_WiFi, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Button_Main_WiFi, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_bg_color(ui_Button_Main_WiFi, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Button_Main_WiFi, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Button_Main_WiFi, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Button_Main_WiFi, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Button_Main_WiFi, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Button_WiFi = lv_label_create(ui_Button_Main_WiFi); + lv_obj_set_width(ui_Label_Main_Button_WiFi, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Button_WiFi, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Button_WiFi, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Main_Button_WiFi, "W"); + lv_obj_set_style_text_color(ui_Label_Main_Button_WiFi, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Button_WiFi, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_Button_WiFi, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Button_Main_ROI = lv_button_create(ui_Container_Main_Buttons); + lv_obj_set_width(ui_Button_Main_ROI, 50); + lv_obj_set_height(ui_Button_Main_ROI, lv_pct(95)); + lv_obj_set_x(ui_Button_Main_ROI, 100); + lv_obj_set_y(ui_Button_Main_ROI, 0); + lv_obj_set_align(ui_Button_Main_ROI, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Button_Main_ROI, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_bg_color(ui_Button_Main_ROI, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Button_Main_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Button_Main_ROI, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Button_Main_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Button_Main_ROI, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Button_ROI = lv_label_create(ui_Button_Main_ROI); + lv_obj_set_width(ui_Label_Main_Button_ROI, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Button_ROI, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Button_ROI, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Main_Button_ROI, "R"); + lv_obj_set_style_text_color(ui_Label_Main_Button_ROI, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Button_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_Button_ROI, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Button_Main_Info = lv_button_create(ui_Container_Main_Buttons); + lv_obj_set_width(ui_Button_Main_Info, 50); + lv_obj_set_height(ui_Button_Main_Info, lv_pct(95)); + lv_obj_set_x(ui_Button_Main_Info, 40); + lv_obj_set_y(ui_Button_Main_Info, 0); + lv_obj_set_align(ui_Button_Main_Info, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Button_Main_Info, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_bg_color(ui_Button_Main_Info, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Button_Main_Info, 200, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Button_Main_Info, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Button_Main_Info, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Button_Main_Info, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Button_Info = lv_label_create(ui_Button_Main_Info); + lv_obj_set_width(ui_Label_Main_Button_Info, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Button_Info, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Button_Info, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Main_Button_Info, "I"); + lv_obj_set_style_text_font(ui_Label_Main_Button_Info, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Button_Main_Menu = lv_button_create(ui_Container_Main_Buttons); + lv_obj_set_width(ui_Button_Main_Menu, 50); + lv_obj_set_height(ui_Button_Main_Menu, lv_pct(95)); + lv_obj_set_x(ui_Button_Main_Menu, -80); + lv_obj_set_y(ui_Button_Main_Menu, 0); + lv_obj_set_align(ui_Button_Main_Menu, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Button_Main_Menu, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_bg_color(ui_Button_Main_Menu, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Button_Main_Menu, 200, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Button_Main_Menu, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Button_Main_Menu, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Button_Main_Menu, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Button_Menu = lv_label_create(ui_Button_Main_Menu); + lv_obj_set_width(ui_Label_Main_Button_Menu, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Button_Menu, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Button_Menu, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Main_Button_Menu, "M"); + lv_obj_set_style_text_font(ui_Label_Main_Button_Menu, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + + lv_obj_add_event_cb(ui_Button_Main_WiFi, ui_event_Button_Main_WiFi, LV_EVENT_ALL, NULL); + lv_obj_add_event_cb(ui_Button_Main_Info, ui_event_Button_Main_Info, LV_EVENT_ALL, NULL); + lv_obj_add_event_cb(ui_Button_Main_Menu, ui_event_Button_Main_Menu, LV_EVENT_ALL, NULL); + lv_obj_add_event_cb(ui_Main, ui_event_Main, LV_EVENT_ALL, NULL); + +} + +void ui_Main_screen_destroy(void) +{ + if(ui_Main) lv_obj_del(ui_Main); + + // NULL screen variables + ui_Main = NULL; + ui_Container_Main_StatusBar = NULL; + ui_Image_Main_WiFi = NULL; + ui_Image_Main_Bluetooth = NULL; + ui_Image_Main_SDCard = NULL; + ui_Label_Main_Time = NULL; + ui_Image_Main_Battery = NULL; + ui_Label_Main_Battery_Remaining = NULL; + ui_Label_Main_MinTemp = NULL; + ui_Label_Main_MaxTemp = NULL; + ui_Container_Main_Thermal = NULL; + ui_Image_Thermal = NULL; + ui_Image_Main_Thermal_ROI = NULL; + ui_Label_Main_Thermal_Crosshair = NULL; + ui_Label_Main_Thermal_PixelTemperature = NULL; + ui_Container_Gradient = NULL; + ui_Label_TempScaleMax = NULL; + ui_Image_Gradient = NULL; + ui_Label_TempScaleMin = NULL; + ui_Container_Main_Buttons = NULL; + ui_Button_Main_WiFi = NULL; + ui_Label_Main_Button_WiFi = NULL; + ui_Button_Main_ROI = NULL; + ui_Label_Main_Button_ROI = NULL; + ui_Button_Main_Info = NULL; + ui_Label_Main_Button_Info = NULL; + ui_Button_Main_Menu = NULL; + ui_Label_Main_Button_Menu = NULL; + +} diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.h b/main/Application/Tasks/GUI/Export/screens/ui_Main.h new file mode 100644 index 0000000..0d261af --- /dev/null +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.h @@ -0,0 +1,55 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#ifndef UI_MAIN_H +#define UI_MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +// SCREEN: ui_Main +extern void ui_Main_screen_init(void); +extern void ui_Main_screen_destroy(void); +extern void ui_event_Main(lv_event_t * e); +extern lv_obj_t * ui_Main; +extern lv_obj_t * ui_Container_Main_StatusBar; +extern lv_obj_t * ui_Image_Main_WiFi; +extern lv_obj_t * ui_Image_Main_Bluetooth; +extern lv_obj_t * ui_Image_Main_SDCard; +extern lv_obj_t * ui_Label_Main_Time; +extern lv_obj_t * ui_Image_Main_Battery; +extern lv_obj_t * ui_Label_Main_Battery_Remaining; +extern lv_obj_t * ui_Label_Main_MinTemp; +extern lv_obj_t * ui_Label_Main_MaxTemp; +extern lv_obj_t * ui_Container_Main_Thermal; +extern lv_obj_t * ui_Image_Thermal; +extern lv_obj_t * ui_Image_Main_Thermal_ROI; +extern lv_obj_t * ui_Label_Main_Thermal_Crosshair; +extern lv_obj_t * ui_Label_Main_Thermal_PixelTemperature; +extern lv_obj_t * ui_Container_Gradient; +extern lv_obj_t * ui_Label_TempScaleMax; +extern lv_obj_t * ui_Image_Gradient; +extern lv_obj_t * ui_Label_TempScaleMin; +extern lv_obj_t * ui_Container_Main_Buttons; +extern void ui_event_Button_Main_WiFi(lv_event_t * e); +extern lv_obj_t * ui_Button_Main_WiFi; +extern lv_obj_t * ui_Label_Main_Button_WiFi; +extern lv_obj_t * ui_Button_Main_ROI; +extern lv_obj_t * ui_Label_Main_Button_ROI; +extern void ui_event_Button_Main_Info(lv_event_t * e); +extern lv_obj_t * ui_Button_Main_Info; +extern lv_obj_t * ui_Label_Main_Button_Info; +extern void ui_event_Button_Main_Menu(lv_event_t * e); +extern lv_obj_t * ui_Button_Main_Menu; +extern lv_obj_t * ui_Label_Main_Button_Menu; +// CUSTOM VARIABLES + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif + diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c new file mode 100644 index 0000000..81df529 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c @@ -0,0 +1,85 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include "../ui.h" + +lv_obj_t * ui_Menu = NULL; +lv_obj_t * ui_Panel_Menu_Header = NULL; +lv_obj_t * ui_Label_Menu_Header = NULL; +lv_obj_t * ui_Container_Menu = NULL; +// event funtions +void ui_event_Menu(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { + lv_indev_wait_release(lv_indev_active()); + _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); + } + if(event_code == LV_EVENT_SCREEN_LOADED) { + ScreenMenuLoaded(e); + } +} + +// build funtions + +void ui_Menu_screen_init(void) +{ + ui_Menu = lv_obj_create(NULL); + lv_obj_remove_flag(ui_Menu, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_bg_color(ui_Menu, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Menu, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Panel_Menu_Header = lv_obj_create(ui_Menu); + lv_obj_set_width(ui_Panel_Menu_Header, 320); + lv_obj_set_height(ui_Panel_Menu_Header, lv_pct(12)); + lv_obj_set_x(ui_Panel_Menu_Header, 1); + lv_obj_set_y(ui_Panel_Menu_Header, 1); + lv_obj_set_align(ui_Panel_Menu_Header, LV_ALIGN_TOP_MID); + lv_obj_remove_flag(ui_Panel_Menu_Header, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_radius(ui_Panel_Menu_Header, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Panel_Menu_Header, lv_color_hex(0x7B3FF0), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Panel_Menu_Header, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Panel_Menu_Header, lv_color_hex(0x7B3FF0), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Panel_Menu_Header, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Menu_Header = lv_label_create(ui_Panel_Menu_Header); + lv_obj_set_width(ui_Label_Menu_Header, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Menu_Header, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Menu_Header, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Menu_Header, "MENU"); + lv_obj_remove_flag(ui_Label_Menu_Header, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Menu_Header, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Menu_Header, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Menu_Header, &lv_font_montserrat_14, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Menu = lv_obj_create(ui_Menu); + lv_obj_remove_style_all(ui_Container_Menu); + lv_obj_set_height(ui_Container_Menu, 210); + lv_obj_set_width(ui_Container_Menu, lv_pct(100)); + lv_obj_set_x(ui_Container_Menu, 0); + lv_obj_set_y(ui_Container_Menu, 15); + lv_obj_set_align(ui_Container_Menu, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Container_Menu, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + lv_obj_add_event_cb(ui_Menu, ui_event_Menu, LV_EVENT_ALL, NULL); + +} + +void ui_Menu_screen_destroy(void) +{ + if(ui_Menu) lv_obj_del(ui_Menu); + + // NULL screen variables + ui_Menu = NULL; + ui_Panel_Menu_Header = NULL; + ui_Label_Menu_Header = NULL; + ui_Container_Menu = NULL; + +} diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h new file mode 100644 index 0000000..44ee69d --- /dev/null +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h @@ -0,0 +1,28 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#ifndef UI_MENU_H +#define UI_MENU_H + +#ifdef __cplusplus +extern "C" { +#endif + +// SCREEN: ui_Menu +extern void ui_Menu_screen_init(void); +extern void ui_Menu_screen_destroy(void); +extern void ui_event_Menu(lv_event_t * e); +extern lv_obj_t * ui_Menu; +extern lv_obj_t * ui_Panel_Menu_Header; +extern lv_obj_t * ui_Label_Menu_Header; +extern lv_obj_t * ui_Container_Menu; +// CUSTOM VARIABLES + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif + diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c new file mode 100644 index 0000000..2714406 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c @@ -0,0 +1,127 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include "../ui.h" + +lv_obj_t * ui_Splash = NULL; +lv_obj_t * ui_SplashScreen_Logo = NULL; +lv_obj_t * ui_SplashScreen_LogoText = NULL; +lv_obj_t * ui_SplashScreen_Subtext = NULL; +lv_obj_t * ui_SplashScreen_LoadingBar = NULL; +lv_obj_t * ui_SplashScreen_StatusText = NULL; +lv_obj_t * ui_SplashScreen_FirmwareVersion = NULL; +// event funtions + +// build funtions + +void ui_Splash_screen_init(void) +{ + ui_Splash = lv_obj_create(NULL); + lv_obj_remove_flag(ui_Splash, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_bg_color(ui_Splash, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Splash, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_SplashScreen_Logo = lv_image_create(ui_Splash); + lv_image_set_src(ui_SplashScreen_Logo, &ui_img_logo_80x44_png); + lv_obj_set_width(ui_SplashScreen_Logo, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_SplashScreen_Logo, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_SplashScreen_Logo, 0); + lv_obj_set_y(ui_SplashScreen_Logo, -80); + lv_obj_set_align(ui_SplashScreen_Logo, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_SplashScreen_Logo, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | + LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_SplashScreen_LogoText = lv_image_create(ui_Splash); + lv_image_set_src(ui_SplashScreen_LogoText, &ui_img_text_218x40_png); + lv_obj_set_width(ui_SplashScreen_LogoText, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_SplashScreen_LogoText, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_SplashScreen_LogoText, 0); + lv_obj_set_y(ui_SplashScreen_LogoText, -20); + lv_obj_set_align(ui_SplashScreen_LogoText, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_SplashScreen_LogoText, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | + LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_SplashScreen_Subtext = lv_label_create(ui_Splash); + lv_obj_set_width(ui_SplashScreen_Subtext, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_SplashScreen_Subtext, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_SplashScreen_Subtext, 0); + lv_obj_set_y(ui_SplashScreen_Subtext, 20); + lv_obj_set_align(ui_SplashScreen_Subtext, LV_ALIGN_CENTER); + lv_label_set_text(ui_SplashScreen_Subtext, "OPEN SOURCE THERMAL CAMERA"); + lv_obj_remove_flag(ui_SplashScreen_Subtext, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_SplashScreen_Subtext, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_SplashScreen_Subtext, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_SplashScreen_Subtext, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_SplashScreen_LoadingBar = lv_bar_create(ui_Splash); + lv_bar_set_value(ui_SplashScreen_LoadingBar, 1, LV_ANIM_OFF); + lv_bar_set_start_value(ui_SplashScreen_LoadingBar, 0, LV_ANIM_OFF); + lv_obj_set_width(ui_SplashScreen_LoadingBar, 200); + lv_obj_set_height(ui_SplashScreen_LoadingBar, 5); + lv_obj_set_x(ui_SplashScreen_LoadingBar, 0); + lv_obj_set_y(ui_SplashScreen_LoadingBar, 45); + lv_obj_set_align(ui_SplashScreen_LoadingBar, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_SplashScreen_LoadingBar, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_bg_color(ui_SplashScreen_LoadingBar, lv_color_hex(0x333333), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_SplashScreen_LoadingBar, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + lv_obj_set_style_bg_color(ui_SplashScreen_LoadingBar, lv_color_hex(0xB998FF), LV_PART_INDICATOR | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_SplashScreen_LoadingBar, 255, LV_PART_INDICATOR | LV_STATE_DEFAULT); + + //Compensating for LVGL9.1 draw crash with bar/slider max value when top-padding is nonzero and right-padding is 0 + if(lv_obj_get_style_pad_top(ui_SplashScreen_LoadingBar, + LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_SplashScreen_LoadingBar, + lv_obj_get_style_pad_right(ui_SplashScreen_LoadingBar, LV_PART_MAIN) + 1, LV_PART_MAIN); + ui_SplashScreen_StatusText = lv_label_create(ui_Splash); + lv_obj_set_width(ui_SplashScreen_StatusText, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_SplashScreen_StatusText, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_SplashScreen_StatusText, 0); + lv_obj_set_y(ui_SplashScreen_StatusText, 65); + lv_obj_set_align(ui_SplashScreen_StatusText, LV_ALIGN_CENTER); + lv_label_set_text(ui_SplashScreen_StatusText, "Initialize system..."); + lv_obj_remove_flag(ui_SplashScreen_StatusText, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_SplashScreen_StatusText, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_SplashScreen_StatusText, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_SplashScreen_StatusText, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_SplashScreen_FirmwareVersion = lv_label_create(ui_Splash); + lv_obj_set_width(ui_SplashScreen_FirmwareVersion, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_SplashScreen_FirmwareVersion, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_SplashScreen_FirmwareVersion, 0); + lv_obj_set_y(ui_SplashScreen_FirmwareVersion, 90); + lv_obj_set_align(ui_SplashScreen_FirmwareVersion, LV_ALIGN_CENTER); + lv_label_set_text(ui_SplashScreen_FirmwareVersion, "Firmware 1.0.0\n(c) 2026 PyroVision Project"); + lv_obj_remove_flag(ui_SplashScreen_FirmwareVersion, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_SplashScreen_FirmwareVersion, lv_color_hex(0x666666), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_SplashScreen_FirmwareVersion, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_SplashScreen_FirmwareVersion, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_SplashScreen_FirmwareVersion, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + +} + +void ui_Splash_screen_destroy(void) +{ + if(ui_Splash) lv_obj_del(ui_Splash); + + // NULL screen variables + ui_Splash = NULL; + ui_SplashScreen_Logo = NULL; + ui_SplashScreen_LogoText = NULL; + ui_SplashScreen_Subtext = NULL; + ui_SplashScreen_LoadingBar = NULL; + ui_SplashScreen_StatusText = NULL; + ui_SplashScreen_FirmwareVersion = NULL; + +} diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h new file mode 100644 index 0000000..6bd4ce1 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h @@ -0,0 +1,30 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#ifndef UI_SPLASH_H +#define UI_SPLASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +// SCREEN: ui_Splash +extern void ui_Splash_screen_init(void); +extern void ui_Splash_screen_destroy(void); +extern lv_obj_t * ui_Splash; +extern lv_obj_t * ui_SplashScreen_Logo; +extern lv_obj_t * ui_SplashScreen_LogoText; +extern lv_obj_t * ui_SplashScreen_Subtext; +extern lv_obj_t * ui_SplashScreen_LoadingBar; +extern lv_obj_t * ui_SplashScreen_StatusText; +extern lv_obj_t * ui_SplashScreen_FirmwareVersion; +// CUSTOM VARIABLES + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif + diff --git a/main/Application/Tasks/GUI/Export/ui.c b/main/Application/Tasks/GUI/Export/ui.c new file mode 100644 index 0000000..f2ce471 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/ui.c @@ -0,0 +1,47 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include "ui.h" +#include "ui_helpers.h" + +///////////////////// VARIABLES //////////////////// + +// EVENTS +lv_obj_t * ui____initial_actions0; + +// IMAGES AND IMAGE SETS + +///////////////////// TEST LVGL SETTINGS //////////////////// +#if LV_COLOR_DEPTH != 16 + #error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" +#endif + +///////////////////// ANIMATIONS //////////////////// + +///////////////////// FUNCTIONS //////////////////// + +///////////////////// SCREENS //////////////////// + +void ui_init(void) +{ + lv_disp_t * dispp = lv_display_get_default(); + lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), + false, LV_FONT_DEFAULT); + lv_disp_set_theme(dispp, theme); + ui_Splash_screen_init(); + ui_Main_screen_init(); + ui_Menu_screen_init(); + ui_Info_screen_init(); + ui____initial_actions0 = lv_obj_create(NULL); + lv_disp_load_scr(ui_Splash); +} + +void ui_destroy(void) +{ + ui_Splash_screen_destroy(); + ui_Main_screen_destroy(); + ui_Menu_screen_destroy(); + ui_Info_screen_destroy(); +} diff --git a/main/Application/Tasks/GUI/Export/ui.h b/main/Application/Tasks/GUI/Export/ui.h new file mode 100644 index 0000000..19aa4ab --- /dev/null +++ b/main/Application/Tasks/GUI/Export/ui.h @@ -0,0 +1,48 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#ifndef _PYROVISION_UI_H +#define _PYROVISION_UI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lvgl.h" + +#include "ui_helpers.h" +#include "ui_events.h" + + +///////////////////// SCREENS //////////////////// + +#include "screens/ui_Splash.h" +#include "screens/ui_Main.h" +#include "screens/ui_Menu.h" +#include "screens/ui_Info.h" + +///////////////////// VARIABLES //////////////////// + + +// EVENTS + +extern lv_obj_t * ui____initial_actions0; + +// IMAGES AND IMAGE SETS +LV_IMG_DECLARE(ui_img_logo_80x44_png); // assets/Logo_80x44.png +LV_IMG_DECLARE(ui_img_text_218x40_png); // assets/Text_218x40.png + +// FONTS +LV_FONT_DECLARE(ui_font_fa); + +// UI INIT +void ui_init(void); +void ui_destroy(void); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/main/Application/Tasks/GUI/Export/ui_events.cpp b/main/Application/Tasks/GUI/Export/ui_events.cpp new file mode 100644 index 0000000..3ca73ee --- /dev/null +++ b/main/Application/Tasks/GUI/Export/ui_events.cpp @@ -0,0 +1,196 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include + +#include "ui.h" + +#include "../../../application.h" + +void ScreenMainLoaded(lv_event_t *e) +{ + char Buf[128]; + + snprintf(Buf, sizeof(Buf), "Firmware %u.%u.%u\n(c) 2026 PyroVision Project", + PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, PYROVISION_VERSION_BUILD); + lv_label_set_text(ui_SplashScreen_FirmwareVersion, Buf); + + lv_label_set_text(ui_Image_Main_WiFi, LV_SYMBOL_WIFI); + lv_label_set_text(ui_Image_Main_Bluetooth, LV_SYMBOL_BLUETOOTH); + lv_label_set_text(ui_Image_Main_SDCard, LV_SYMBOL_SD_CARD); + lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_FULL); + + lv_label_set_text(ui_Label_Main_Button_Menu, "\uF0C9"); + lv_label_set_text(ui_Label_Main_Button_Info, "\uF129"); + lv_label_set_text(ui_Label_Main_Button_ROI, "\uF05B"); + lv_label_set_text(ui_Label_Main_Button_WiFi, "\uF1EB"); + lv_label_set_text(ui_Label_Main_Thermal_Crosshair, "\uF05B"); +} + +void ScreenInfoLoaded(lv_event_t *e) +{ + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_UPTIME, NULL, 0, 0); + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_FPA_AUX_TEMP, NULL, 0, 0); +} + +/* +static lv_obj_t * create_text(lv_obj_t * parent, const char * icon, const char * txt, + int builder_variant) +{ + lv_obj_t * obj = lv_menu_cont_create(parent); + + lv_obj_t * img = NULL; + lv_obj_t * label = NULL; + + if(icon) { + img = lv_img_create(obj); + lv_img_set_src(img, icon); + } + + if(txt) { + label = lv_label_create(obj); + lv_label_set_text(label, txt); + lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); + lv_obj_set_flex_grow(label, 1); + } + + if(builder_variant == 1 && icon && txt) { + lv_obj_add_flag(img, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK); + lv_obj_swap(img, label); + } + + return obj; +} + +static lv_obj_t * create_slider(lv_obj_t * parent, const char * icon, const char * txt, int32_t min, int32_t max, int32_t val) +{ + lv_obj_t * obj = create_text(parent, icon, txt, 0); + + lv_obj_t * slider = lv_slider_create(obj); + lv_obj_set_flex_grow(slider, 1); + lv_slider_set_range(slider, min, max); + lv_slider_set_value(slider, val, LV_ANIM_OFF); + + if(icon == NULL) { + lv_obj_add_flag(slider, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK); + } + + return obj; +} + +static lv_obj_t * create_switch(lv_obj_t * parent, const char * icon, const char * txt, bool chk) +{ + lv_obj_t * obj = create_text(parent, icon, txt, 0); + + lv_obj_t * sw = lv_switch_create(obj); + lv_obj_add_state(sw, LV_STATE_CHECKED); + + return obj; +} +*/ + +void ScreenMenuLoaded(lv_event_t *e) +{ + /* + lv_obj_t * root_page; + lv_obj_t *menu; + lv_obj_t * cont; + lv_obj_t * section; + lv_obj_t * text_area; + lv_obj_t * btn; + + menu = lv_menu_create(ui_Container_Menu); + lv_obj_set_size(menu, 320, 210); + lv_obj_set_pos(menu, 0, 15); + lv_obj_center(menu); + + lv_menu_set_mode_header(menu, LV_MENU_HEADER_TOP_FIXED); + + lv_obj_t * sub_wifi_page = lv_menu_page_create(menu, "WiFi"); + lv_menu_separator_create(sub_wifi_page); + section = lv_menu_section_create(sub_wifi_page); + + cont = create_switch(section, LV_SYMBOL_WIFI, "Auto Connect", false); + + lv_obj_t * ssid_cont = lv_menu_cont_create(sub_wifi_page); + lv_obj_t * ssid_label = lv_label_create(ssid_cont); + lv_label_set_text(ssid_label, "SSID:"); + text_area = lv_textarea_create(ssid_cont); + lv_textarea_set_one_line(text_area, true); + lv_textarea_set_placeholder_text(text_area, "WiFi Name"); + lv_obj_set_width(text_area, 200); + + lv_obj_t * ip_cont = lv_menu_cont_create(sub_wifi_page); + lv_obj_t * ip_label = lv_label_create(ip_cont); + lv_label_set_text(ip_label, "IP Address:"); + text_area = lv_textarea_create(ip_cont); + lv_textarea_set_one_line(text_area, true); + lv_textarea_set_placeholder_text(text_area, "192.168.1.100"); + lv_obj_set_width(text_area, 200); + + lv_obj_t * pwd_cont = lv_menu_cont_create(sub_wifi_page); + lv_obj_t * pwd_label = lv_label_create(pwd_cont); + lv_label_set_text(pwd_label, "Password:"); + text_area = lv_textarea_create(pwd_cont); + lv_textarea_set_one_line(text_area, true); + lv_textarea_set_password_mode(text_area, true); + lv_textarea_set_placeholder_text(text_area, "Password"); + lv_obj_set_width(text_area, 200); + + lv_obj_t * sub_display_page = lv_menu_page_create(menu, "Display"); + lv_menu_separator_create(sub_display_page); + section = lv_menu_section_create(sub_display_page); + create_slider(section, LV_SYMBOL_IMAGE, "Brightness", 0, 100, 80); + + lv_obj_t * sub_about_page = lv_menu_page_create(menu, "About"); + + lv_obj_t * sub_software_info_page = lv_menu_page_create(menu, "Software Information"); + section = lv_menu_section_create(sub_software_info_page); + create_text(section, NULL, "PyroVision Firmware", 0); + char version_buf[64]; + snprintf(version_buf, sizeof(version_buf), "Version %u.%u.%u", + PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, PYROVISION_VERSION_BUILD); + create_text(section, NULL, version_buf, 0); + create_text(section, NULL, "ESP32-S3 Platform", 0); + create_text(section, NULL, "LVGL 9.1.0", 0); + + lv_obj_t * sub_legal_info_page = lv_menu_page_create(menu, "Legal Information"); + section = lv_menu_section_create(sub_legal_info_page); + create_text(section, NULL, "(c) 2026 PyroVision Project", 0); + create_text(section, NULL, "Licensed under GNU GPL v3", 0); + create_text(section, NULL, "", 0); + create_text(section, NULL, "This program is free software:", 0); + create_text(section, NULL, "you can redistribute it and/or", 0); + create_text(section, NULL, "modify it under the terms of", 0); + create_text(section, NULL, "the GNU General Public License", 0); + create_text(section, NULL, "as published by the Free", 0); + create_text(section, NULL, "Software Foundation.", 0); + + lv_menu_separator_create(sub_about_page); + section = lv_menu_section_create(sub_about_page); + cont = create_text(section, LV_SYMBOL_FILE, "Software information", 0); + lv_menu_set_load_page_event(menu, cont, sub_software_info_page); + cont = create_text(section, LV_SYMBOL_LIST, "Legal information", 0); + lv_menu_set_load_page_event(menu, cont, sub_legal_info_page); + + root_page = lv_menu_page_create(menu, NULL); + section = lv_menu_section_create(root_page); + + cont = create_text(section, LV_SYMBOL_WIFI, "WiFi", 0); + lv_menu_set_load_page_event(menu, cont, sub_wifi_page); + + cont = create_text(section, LV_SYMBOL_IMAGE, "Display", 0); + lv_menu_set_load_page_event(menu, cont, sub_display_page); + + cont = create_text(section, LV_SYMBOL_HOME, "About", 0); + lv_menu_set_load_page_event(menu, cont, sub_about_page); + + lv_menu_set_sidebar_page(menu, root_page);*/ +} + +void ButtonMainWiFiClicked(lv_event_t *e) +{ + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_OPEN_WIFI_REQUEST, NULL, 0, 0); +} diff --git a/main/Application/Tasks/GUI/Export/ui_events.h b/main/Application/Tasks/GUI/Export/ui_events.h new file mode 100644 index 0000000..a0f98a5 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/ui_events.h @@ -0,0 +1,22 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#ifndef _UI_EVENTS_H +#define _UI_EVENTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +void ScreenMainLoaded(lv_event_t * e); +void ButtonMainWiFiClicked(lv_event_t * e); +void ScreenMenuLoaded(lv_event_t * e); +void ScreenInfoLoaded(lv_event_t * e); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/main/Application/Tasks/GUI/Export/ui_helpers.c b/main/Application/Tasks/GUI/Export/ui_helpers.c new file mode 100644 index 0000000..62ee629 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/ui_helpers.c @@ -0,0 +1,347 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#include "ui_helpers.h" + +void _ui_bar_set_property(lv_obj_t * target, int id, int val) +{ + if(id == _UI_BAR_PROPERTY_VALUE_WITH_ANIM) lv_bar_set_value(target, val, LV_ANIM_ON); + if(id == _UI_BAR_PROPERTY_VALUE) lv_bar_set_value(target, val, LV_ANIM_OFF); +} + +void _ui_basic_set_property(lv_obj_t * target, int id, int val) +{ + if(id == _UI_BASIC_PROPERTY_POSITION_X) lv_obj_set_x(target, val); + if(id == _UI_BASIC_PROPERTY_POSITION_Y) lv_obj_set_y(target, val); + if(id == _UI_BASIC_PROPERTY_WIDTH) lv_obj_set_width(target, val); + if(id == _UI_BASIC_PROPERTY_HEIGHT) lv_obj_set_height(target, val); +} + + +void _ui_dropdown_set_property(lv_obj_t * target, int id, int val) +{ + if(id == _UI_DROPDOWN_PROPERTY_SELECTED) lv_dropdown_set_selected(target, val); +} + +void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val) +{ + if(id == _UI_IMAGE_PROPERTY_IMAGE) lv_image_set_src(target, val); +} + +void _ui_label_set_property(lv_obj_t * target, int id, const char * val) +{ + if(id == _UI_LABEL_PROPERTY_TEXT) lv_label_set_text(target, val); +} + + +void _ui_roller_set_property(lv_obj_t * target, int id, int val) +{ + if(id == _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM) lv_roller_set_selected(target, val, LV_ANIM_ON); + if(id == _UI_ROLLER_PROPERTY_SELECTED) lv_roller_set_selected(target, val, LV_ANIM_OFF); +} + +void _ui_slider_set_property(lv_obj_t * target, int id, int val) +{ + if(id == _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM) lv_slider_set_value(target, val, LV_ANIM_ON); + if(id == _UI_SLIDER_PROPERTY_VALUE) lv_slider_set_value(target, val, LV_ANIM_OFF); +} + + +void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, + void (*target_init)(void)) +{ + if(*target == NULL) + target_init(); + lv_screen_load_anim(*target, fademode, spd, delay, false); +} + +void _ui_arc_increment(lv_obj_t * target, int val) +{ + int old = lv_arc_get_value(target); + lv_arc_set_value(target, old + val); + lv_obj_send_event(target, LV_EVENT_VALUE_CHANGED, 0); +} + +void _ui_bar_increment(lv_obj_t * target, int val, int anm) +{ + int old = lv_bar_get_value(target); + lv_bar_set_value(target, old + val, anm); +} + +void _ui_slider_increment(lv_obj_t * target, int val, int anm) +{ + int old = lv_slider_get_value(target); + lv_slider_set_value(target, old + val, anm); + lv_obj_send_event(target, LV_EVENT_VALUE_CHANGED, 0); +} + +void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea) +{ + lv_keyboard_set_textarea(keyboard, textarea); +} + +void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value) +{ + if(value == _UI_MODIFY_FLAG_TOGGLE) { + if(lv_obj_has_flag(target, flag)) lv_obj_remove_flag(target, flag); + else lv_obj_add_flag(target, flag); + } + else if(value == _UI_MODIFY_FLAG_ADD) lv_obj_add_flag(target, flag); + else lv_obj_remove_flag(target, flag); +} +void _ui_state_modify(lv_obj_t * target, int32_t state, int value) +{ + if(value == _UI_MODIFY_STATE_TOGGLE) { + if(lv_obj_has_state(target, state)) lv_obj_remove_state(target, state); + else lv_obj_add_state(target, state); + } + else if(value == _UI_MODIFY_STATE_ADD) lv_obj_add_state(target, state); + else lv_obj_remove_state(target, state); +} + + +void _ui_textarea_move_cursor(lv_obj_t * target, int val) + +{ + + if(val == UI_MOVE_CURSOR_UP) lv_textarea_cursor_up(target); + if(val == UI_MOVE_CURSOR_RIGHT) lv_textarea_cursor_right(target); + if(val == UI_MOVE_CURSOR_DOWN) lv_textarea_cursor_down(target); + if(val == UI_MOVE_CURSOR_LEFT) lv_textarea_cursor_left(target); + lv_obj_add_state(target, LV_STATE_FOCUSED); +} + +typedef void (*screen_destroy_cb_t)(void); + +void scr_unloaded_delete_cb(lv_event_t * e) + +{ + + // Get the destroy callback from user_data + + screen_destroy_cb_t destroy_cb = lv_event_get_user_data(e); + if(destroy_cb) { + + destroy_cb(); // call the specific screen destroy function + + } + +} + +void _ui_opacity_set(lv_obj_t * target, int val) +{ + lv_obj_set_style_opa(target, val, 0); +} + +void _ui_anim_callback_free_user_data(lv_anim_t * a) +{ + lv_free(a->user_data); + a->user_data = NULL; +} + +void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_x(usr->target, v); + +} + + +void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_y(usr->target, v); + +} + + +void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_width(usr->target, v); + +} + + +void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_height(usr->target, v); + +} + + +void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + lv_obj_set_style_opa(usr->target, v, 0); + +} + + +void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + lv_image_set_scale(usr->target, v); + +} + + +void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + lv_image_set_rotation(usr->target, v); + +} + + +void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + usr->val = v; + + if(v < 0) v = 0; + if(v >= usr->imgset_size) v = usr->imgset_size - 1; + lv_image_set_src(usr->target, usr->imgset[v]); +} + +int32_t _ui_anim_callback_get_x(lv_anim_t * a) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_x_aligned(usr->target); + +} + + +int32_t _ui_anim_callback_get_y(lv_anim_t * a) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_y_aligned(usr->target); + +} + + +int32_t _ui_anim_callback_get_width(lv_anim_t * a) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_width(usr->target); + +} + + +int32_t _ui_anim_callback_get_height(lv_anim_t * a) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_height(usr->target); + +} + + +int32_t _ui_anim_callback_get_opacity(lv_anim_t * a) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + return lv_obj_get_style_opa(usr->target, 0); + +} + +int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + return lv_image_get_scale(usr->target); + +} + +int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + return lv_image_get_rotation(usr->target); + +} + +int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a) + +{ + + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + return usr->val; + +} + +void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix) +{ + char buf[_UI_TEMPORARY_STRING_BUFFER_SIZE]; + + lv_snprintf(buf, sizeof(buf), "%s%d%s", prefix, (int)lv_arc_get_value(src), postfix); + + lv_label_set_text(trg, buf); +} + +void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix) +{ + char buf[_UI_TEMPORARY_STRING_BUFFER_SIZE]; + + lv_snprintf(buf, sizeof(buf), "%s%d%s", prefix, (int)lv_slider_get_value(src), postfix); + + lv_label_set_text(trg, buf); +} +void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off) +{ + if(lv_obj_has_state(src, LV_STATE_CHECKED)) lv_label_set_text(trg, txt_on); + else lv_label_set_text(trg, txt_off); +} + + +void _ui_spinbox_step(lv_obj_t * target, int val) + +{ + + if(val > 0) lv_spinbox_increment(target); + + else lv_spinbox_decrement(target); + + + lv_obj_send_event(target, LV_EVENT_VALUE_CHANGED, 0); +} + +void _ui_switch_theme(int val) + +{ + +#ifdef UI_THEME_ACTIVE + ui_theme_set(val); +#endif +} + + diff --git a/main/Application/Tasks/GUI/Export/ui_helpers.h b/main/Application/Tasks/GUI/Export/ui_helpers.h new file mode 100644 index 0000000..81650e0 --- /dev/null +++ b/main/Application/Tasks/GUI/Export/ui_helpers.h @@ -0,0 +1,147 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.4 +// LVGL version: 9.1.0 +// Project name: PyroVision + +#ifndef _PYROVISION_UI_HELPERS_H +#define _PYROVISION_UI_HELPERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ui.h" + +#define _UI_TEMPORARY_STRING_BUFFER_SIZE 32 +#define _UI_BAR_PROPERTY_VALUE 0 +#define _UI_BAR_PROPERTY_VALUE_WITH_ANIM 1 +void _ui_bar_set_property(lv_obj_t * target, int id, int val); + +#define _UI_BASIC_PROPERTY_POSITION_X 0 +#define _UI_BASIC_PROPERTY_POSITION_Y 1 +#define _UI_BASIC_PROPERTY_WIDTH 2 +#define _UI_BASIC_PROPERTY_HEIGHT 3 +void _ui_basic_set_property(lv_obj_t * target, int id, int val); + +#define _UI_DROPDOWN_PROPERTY_SELECTED 0 +void _ui_dropdown_set_property(lv_obj_t * target, int id, int val); + +#define _UI_IMAGE_PROPERTY_IMAGE 0 +void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val); + +#define _UI_LABEL_PROPERTY_TEXT 0 +void _ui_label_set_property(lv_obj_t * target, int id, const char * val); + +#define _UI_ROLLER_PROPERTY_SELECTED 0 +#define _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM 1 +void _ui_roller_set_property(lv_obj_t * target, int id, int val); + +#define _UI_SLIDER_PROPERTY_VALUE 0 +#define _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM 1 +void _ui_slider_set_property(lv_obj_t * target, int id, int val); + +void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, + void (*target_init)(void)); + +void _ui_arc_increment(lv_obj_t * target, int val); + +void _ui_bar_increment(lv_obj_t * target, int val, int anm); + +void _ui_slider_increment(lv_obj_t * target, int val, int anm); + +void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea); + +#define _UI_MODIFY_FLAG_ADD 0 +#define _UI_MODIFY_FLAG_REMOVE 1 +#define _UI_MODIFY_FLAG_TOGGLE 2 +void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value); + +#define _UI_MODIFY_STATE_ADD 0 +#define _UI_MODIFY_STATE_REMOVE 1 +#define _UI_MODIFY_STATE_TOGGLE 2 +void _ui_state_modify(lv_obj_t * target, int32_t state, int value); + +#define UI_MOVE_CURSOR_UP 0 +#define UI_MOVE_CURSOR_RIGHT 1 +#define UI_MOVE_CURSOR_DOWN 2 +#define UI_MOVE_CURSOR_LEFT 3 +void _ui_textarea_move_cursor(lv_obj_t * target, int val) +; + + +void scr_unloaded_delete_cb(lv_event_t * e); + +void _ui_opacity_set(lv_obj_t * target, int val); + +/** Describes an animation*/ +typedef struct _ui_anim_user_data_t { + lv_obj_t * target; + lv_image_dsc_t ** imgset; + int32_t imgset_size; + int32_t val; +} ui_anim_user_data_t; +void _ui_anim_callback_free_user_data(lv_anim_t * a); + +void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v); + + +int32_t _ui_anim_callback_get_x(lv_anim_t * a); + +int32_t _ui_anim_callback_get_y(lv_anim_t * a); + +int32_t _ui_anim_callback_get_width(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_height(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_opacity(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a); + + +void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); + +void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); + +void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off); + +void _ui_spinbox_step(lv_obj_t * target, int val) +; + + +void _ui_switch_theme(int val) +; + + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/main/Application/Tasks/GUI/Private/guiHelper.cpp b/main/Application/Tasks/GUI/Private/guiHelper.cpp new file mode 100644 index 0000000..c4e9321 --- /dev/null +++ b/main/Application/Tasks/GUI/Private/guiHelper.cpp @@ -0,0 +1,333 @@ +/* + * guiHelper.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Helper functions for the GUI task. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include "guiHelper.h" +#include "Application/application.h" +#include "../Export/ui.h" + +#if defined(CONFIG_LCD_SPI2_HOST) +#define LCD_SPI_HOST SPI2_HOST +#elif defined(CONFIG_LCD_SPI3_HOST) +#define LCD_SPI_HOST SPI3_HOST +#else +#error "No SPI host defined for LCD!" +#endif + +#define GUI_DRAW_BUFFER_SIZE (CONFIG_GUI_WIDTH * CONFIG_GUI_HEIGHT * sizeof(uint16_t) / 10) + +static const esp_lcd_panel_dev_config_t _GUI_Panel_Config = { + .reset_gpio_num = CONFIG_LCD_RST, + .color_space = ESP_LCD_COLOR_SPACE_BGR, + .bits_per_pixel = 16, + .flags = { + .reset_active_high = 0, + }, + .vendor_config = NULL, +}; + +static esp_lcd_panel_io_spi_config_t _GUI_Panel_IO_Config = { + .cs_gpio_num = CONFIG_LCD_CS, + .dc_gpio_num = CONFIG_LCD_DC, + .spi_mode = 0, + .pclk_hz = CONFIG_LCD_CLOCK, + .trans_queue_depth = 10, + .on_color_trans_done = NULL, + .user_ctx = NULL, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + .flags = { + .dc_low_on_data = 0, + .octal_mode = 0, + .sio_mode = 0, + .lsb_first = 0, + .cs_high_active = 0, + }, +}; + +static esp_lcd_touch_config_t _GUI_Touch_Config = { + .x_max = CONFIG_GUI_WIDTH, + .y_max = CONFIG_GUI_HEIGHT, + .rst_gpio_num = static_cast(CONFIG_TOUCH_RST), + .int_gpio_num = static_cast(CONFIG_TOUCH_IRQ), + .flags = { + .swap_xy = 0, + .mirror_x = 0, + .mirror_y = 0, + }, +}; + +static esp_lcd_panel_io_spi_config_t _GUI_Touch_IO_Config = ESP_LCD_TOUCH_IO_SPI_XPT2046_CONFIG(CONFIG_TOUCH_CS); + +static const char *TAG = "gui_helper"; + +static void GUI_LVGL_TickTimer_CB(void *p_Arg) +{ + lv_tick_inc(CONFIG_GUI_LVGL_TICK_PERIOD_MS); +} + +static void GUI_LCD_Flush_CB(lv_display_t *p_Disp, const lv_area_t *p_Area, uint8_t *p_PxMap) +{ + esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)lv_display_get_user_data(p_Disp); + + int offsetx1 = p_Area->x1; + int offsetx2 = p_Area->x2; + int offsety1 = p_Area->y1; + int offsety2 = p_Area->y2; + + esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, p_PxMap); + + lv_display_flush_ready(p_Disp); +} + +esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t Touch_Read_Callback) +{ +#if CONFIG_LCD_BL >= 0 + gpio_config_t bk_gpio_config = { + .pin_bit_mask = 1ULL << CONFIG_LCD_BL, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); + gpio_set_level(static_cast(CONFIG_LCD_BL), LCD_BK_LIGHT_ON_LEVEL); +#endif + + _GUI_Panel_IO_Config.on_color_trans_done = NULL; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(static_cast(LCD_SPI_HOST), &_GUI_Panel_IO_Config, + &p_GUITask_State->Panel_IO_Handle)); + ESP_LOGD(TAG, "SPI panel IO created"); + + ESP_LOGD(TAG, "Initialize LVGL library"); + lv_init(); + + /* Initialize LVGL display first (needed for callback) */ + p_GUITask_State->Display = lv_display_create(CONFIG_GUI_WIDTH, CONFIG_GUI_HEIGHT); + ESP_LOGD(TAG, "LVGL display object created"); + + /* Register event callbacks BEFORE installing panel driver */ + esp_lcd_panel_io_callbacks_t cbs = { + .on_color_trans_done = NULL, + }; + ESP_ERROR_CHECK(esp_lcd_panel_io_register_event_callbacks(p_GUITask_State->Panel_IO_Handle, &cbs, + p_GUITask_State->Display)); + ESP_LOGD(TAG, "LCD panel IO callbacks registered"); + ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(p_GUITask_State->Panel_IO_Handle, &_GUI_Panel_Config, + &p_GUITask_State->PanelHandle)); + ESP_LOGD(TAG, "ILI9341 panel driver installed"); + ESP_ERROR_CHECK(esp_lcd_panel_reset(p_GUITask_State->PanelHandle)); + ESP_LOGD(TAG, "Panel reset complete"); + vTaskDelay(100 / portTICK_PERIOD_MS); + ESP_ERROR_CHECK(esp_lcd_panel_init(p_GUITask_State->PanelHandle)); + ESP_LOGD(TAG, "Panel initialized"); + vTaskDelay(100 / portTICK_PERIOD_MS); + + /* Set to landscape mode (320x240) - swap width and height */ + ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(p_GUITask_State->PanelHandle, true)); + ESP_LOGD(TAG, "Panel swap_xy enabled for landscape"); + + /* 180 degree rotation: mirror both X and Y */ + ESP_ERROR_CHECK(esp_lcd_panel_mirror(p_GUITask_State->PanelHandle, true, true)); + ESP_LOGD(TAG, "Panel mirroring configured (180 degree rotation)"); + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(p_GUITask_State->PanelHandle, true)); + ESP_LOGD(TAG, "Panel display turned ON"); + vTaskDelay(100 / portTICK_PERIOD_MS); + + /* Set LVGL display properties */ + lv_display_set_flush_cb(p_GUITask_State->Display, GUI_LCD_Flush_CB); + lv_display_set_user_data(p_GUITask_State->Display, + p_GUITask_State->PanelHandle); + + /* Note: Color format set to RGB565 by default, matching thermal image BGR565 conversion */ + /* Allocate draw buffers in PSRAM */ + p_GUITask_State->DisplayBuffer1 = heap_caps_malloc(GUI_DRAW_BUFFER_SIZE, MALLOC_CAP_SPIRAM); + p_GUITask_State->DisplayBuffer2 = heap_caps_malloc(GUI_DRAW_BUFFER_SIZE, MALLOC_CAP_SPIRAM); + ESP_LOGD(TAG, "Allocated LVGL buffers: %d bytes each in PSRAM", GUI_DRAW_BUFFER_SIZE); + if ((p_GUITask_State->DisplayBuffer1 == NULL) || (p_GUITask_State->DisplayBuffer2 == NULL)) { + ESP_LOGE(TAG, "Failed to allocate LVGL draw buffers!"); + return ESP_ERR_NO_MEM; + } + lv_display_set_buffers(p_GUITask_State->Display, + p_GUITask_State->DisplayBuffer1, + p_GUITask_State->DisplayBuffer2, + GUI_DRAW_BUFFER_SIZE, + LV_DISPLAY_RENDER_MODE_PARTIAL); + ESP_LOGD(TAG, "LVGL display buffers configured"); + + p_GUITask_State->EventGroup = xEventGroupCreate(); + if (p_GUITask_State->EventGroup == NULL) { + ESP_LOGE(TAG, "Failed to create GUI event group!"); + return ESP_ERR_NO_MEM; + } + + ESP_LOGD(TAG, "Initialize touch controller XPT2046"); + ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(static_cast(LCD_SPI_HOST), &_GUI_Touch_IO_Config, + &p_GUITask_State->Touch_IO_Handle)); + ESP_ERROR_CHECK(esp_lcd_touch_new_spi_xpt2046(p_GUITask_State->Touch_IO_Handle, &_GUI_Touch_Config, + &p_GUITask_State->TouchHandle)); + + /* Register touchpad input device */ + ESP_LOGD(TAG, "Register touch input device to LVGL"); + p_GUITask_State->Touch = lv_indev_create(); + lv_indev_set_type(p_GUITask_State->Touch, LV_INDEV_TYPE_POINTER); + lv_indev_set_display(p_GUITask_State->Touch, p_GUITask_State->Display); + lv_indev_set_read_cb(p_GUITask_State->Touch, Touch_Read_Callback); + lv_indev_set_user_data(p_GUITask_State->Touch, p_GUITask_State->TouchHandle); + + /* Create LVGL tick timer */ + const esp_timer_create_args_t LVGL_TickTimer_args = { + .callback = &GUI_LVGL_TickTimer_CB, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "lvgl_tick", + .skip_unhandled_events = false, + }; + + ESP_ERROR_CHECK(esp_timer_create(&LVGL_TickTimer_args, &p_GUITask_State->LVGL_TickTimer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(p_GUITask_State->LVGL_TickTimer, CONFIG_GUI_LVGL_TICK_PERIOD_MS * 1000)); + + /* Create LVGL clock update timer. Use a 100 ms interval for smoother updates */ + p_GUITask_State->UpdateTimer[0] = lv_timer_create(GUI_Helper_Timer_ClockUpdate, 100, NULL); + + p_GUITask_State->UpdateTimer[1] = lv_timer_create(GUI_Helper_Timer_SpotUpdate, 2000, NULL); + p_GUITask_State->UpdateTimer[2] = lv_timer_create(GUI_Helper_Timer_SpotmeterUpdate, 5000, NULL); + + return ESP_OK; +} + +void GUI_Helper_Deinit(GUI_Task_State_t *p_GUITask_State) +{ + if (p_GUITask_State->isInitialized == false) { + return; + } + + for (uint32_t i = 0; i < sizeof(p_GUITask_State->UpdateTimer) / sizeof(p_GUITask_State->UpdateTimer[0]); i++) { + if (p_GUITask_State->UpdateTimer[i] != NULL) { + lv_timer_delete(p_GUITask_State->UpdateTimer[i]); + p_GUITask_State->UpdateTimer[i] = NULL; + } + } + + esp_timer_stop(p_GUITask_State->LVGL_TickTimer); + esp_timer_delete(p_GUITask_State->LVGL_TickTimer); + p_GUITask_State->LVGL_TickTimer = NULL; + + if (p_GUITask_State->LVGL_TickTimer != NULL) { + esp_timer_stop(p_GUITask_State->LVGL_TickTimer); + esp_timer_delete(p_GUITask_State->LVGL_TickTimer); + p_GUITask_State->LVGL_TickTimer = NULL; + } + + if (p_GUITask_State->EventGroup != NULL) { + vEventGroupDelete(p_GUITask_State->EventGroup); + p_GUITask_State->EventGroup = NULL; + } + + if (p_GUITask_State->Touch != NULL) { + lv_indev_delete(p_GUITask_State->Touch); + p_GUITask_State->Touch = NULL; + } + + esp_lcd_touch_del(p_GUITask_State->TouchHandle); + + if (p_GUITask_State->Display != NULL) { + lv_display_delete(p_GUITask_State->Display); + p_GUITask_State->Display = NULL; + } + + if (p_GUITask_State->DisplayBuffer1 != NULL) { + heap_caps_free(p_GUITask_State->DisplayBuffer1); + p_GUITask_State->DisplayBuffer1 = NULL; + } + + if (p_GUITask_State->DisplayBuffer2 != NULL) { + heap_caps_free(p_GUITask_State->DisplayBuffer2); + p_GUITask_State->DisplayBuffer2 = NULL; + } + + if (p_GUITask_State->Touch_IO_Handle != NULL) { + esp_lcd_panel_io_del(p_GUITask_State->Touch_IO_Handle); + p_GUITask_State->Touch_IO_Handle = NULL; + } + + if (p_GUITask_State->PanelHandle != NULL) { + esp_lcd_panel_del(p_GUITask_State->PanelHandle); + p_GUITask_State->PanelHandle = NULL; + } +} + +void GUI_Helper_GetSpotTemperature(float Temperature) +{ + char buf[16]; + + snprintf(buf, sizeof(buf), "%.2f °C", Temperature); + lv_label_set_text(ui_Label_Main_Thermal_PixelTemperature, buf); +} + +void GUI_Helper_Timer_ClockUpdate(lv_timer_t *p_Timer) +{ + char buf[9]; + struct tm time_now; + + /* Get current time from TimeManager */ + TimeManager_GetTime(&time_now, NULL); + + snprintf(buf, sizeof(buf), "%02d:%02d:%02d", time_now.tm_hour, time_now.tm_min, time_now.tm_sec); + lv_label_set_text(ui_Label_Main_Time, buf); + + /* Broadcast telemetry to WebSocket clients if server is running */ + if (Server_isRunning()) { + WebSocket_Handler_BroadcastTelemetry(); + } +} + +void GUI_Helper_Timer_SpotUpdate(lv_timer_t *p_Timer) +{ + App_GUI_Screenposition_t ScreenPosition; + + /* Check if thermal image is initialized */ + if ((lv_obj_get_width(ui_Image_Thermal) == 0) || (lv_obj_get_height(ui_Image_Thermal) == 0)) { + ESP_LOGW(TAG, "Thermal image not yet initialized, skipping spot update", + lv_obj_get_width(ui_Image_Thermal), lv_obj_get_height(ui_Image_Thermal)); + return; + } + + /* Get crosshair position relative to its parent (ui_Image_Thermal) */ + ScreenPosition.x = lv_obj_get_x(ui_Label_Main_Thermal_Crosshair) + lv_obj_get_width( + ui_Label_Main_Thermal_Crosshair) / 2; + ScreenPosition.y = lv_obj_get_y(ui_Label_Main_Thermal_Crosshair) + lv_obj_get_height( + ui_Label_Main_Thermal_Crosshair) / 2; + ScreenPosition.Width = lv_obj_get_width(ui_Image_Thermal); + ScreenPosition.Height = lv_obj_get_height(ui_Image_Thermal); + + ESP_LOGD(TAG, "Crosshair center in thermal canvas: (%d,%d), size (%d,%d)", ScreenPosition.x, ScreenPosition.y, ScreenPosition.Width, ScreenPosition.Height); + + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_PIXEL_TEMPERATURE, &ScreenPosition, sizeof(ScreenPosition), portMAX_DELAY); +} + +void GUI_Helper_Timer_SpotmeterUpdate(lv_timer_t *p_Timer) +{ + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_SPOTMETER, NULL, 0, portMAX_DELAY); +} \ No newline at end of file diff --git a/main/Application/Tasks/GUI/Private/guiHelper.h b/main/Application/Tasks/GUI/Private/guiHelper.h new file mode 100644 index 0000000..f8021db --- /dev/null +++ b/main/Application/Tasks/GUI/Private/guiHelper.h @@ -0,0 +1,140 @@ +/* + * guiHelper.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Helper functions for the GUI task. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef GUI_HELPER_H_ +#define GUI_HELPER_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "Application/application.h" +#include "Application/Manager/Network/network_types.h" + +#define STOP_REQUEST BIT0 +#define BATTERY_VOLTAGE_READY BIT1 +#define BATTERY_CHARGING_STATUS_READY BIT2 +#define WIFI_CONNECTION_STATE_CHANGED BIT3 +#define PROVISIONING_STATE_CHANGED BIT7 +#define SD_CARD_STATE_CHANGED BIT8 +#define SD_CARD_MOUNTED BIT9 +#define SD_CARD_MOUNT_ERROR BIT10 +#define LEPTON_UPTIME_READY BIT11 +#define LEPTON_TEMP_READY BIT12 +#define LEPTON_PIXEL_TEMPERATURE_READY BIT13 +#define LEPTON_CAMERA_READY BIT4 +#define LEPTON_SPOTMETER_READY BIT5 + +typedef struct { + bool isInitialized; + bool Running; + bool ChargeStatus; + bool WiFiConnected; + bool ProvisioningActive; + bool RunTask; + bool CardPresent; + TaskHandle_t GUI_Handle; + void *DisplayBuffer1; + void *DisplayBuffer2; + esp_timer_handle_t LVGL_TickTimer; + esp_lcd_panel_handle_t PanelHandle; + esp_lcd_touch_handle_t TouchHandle; + esp_lcd_panel_io_handle_t Panel_IO_Handle; + esp_lcd_panel_io_handle_t Touch_IO_Handle; + lv_display_t *Display; + lv_indev_t *Touch; + lv_img_dsc_t ThermalImageDescriptor; + lv_img_dsc_t GradientImageDescriptor; + lv_timer_t *UpdateTimer[3]; + _lock_t LVGL_API_Lock; + App_Devices_Battery_t BatteryInfo; + App_Lepton_Spotmeter_t SpotmeterInfo; + App_Lepton_Device_t LeptonDeviceInfo; + App_Lepton_Temperatures_t LeptonTemperatures; + Network_IP_Info_t IP_Info; + EventGroupHandle_t EventGroup; + uint8_t *ThermalCanvasBuffer; + uint8_t *GradientCanvasBuffer; + uint8_t *NetworkRGBBuffer; /* RGB888 buffer for network streaming (240x180x3) */ + uint32_t LeptonUptime; + float SpotTemperature; + + /* Network frame for server streaming */ + Network_Thermal_Frame_t NetworkFrame; + + /* ROI control state */ + bool ROI_EditMode; + bool ROI_LongPressActive; /* Flag to prevent CLICKED after LONG_PRESSED */ + uint8_t ROI_ResizeMode; /* 0=move, 1=resize_left, 2=resize_right, 4=resize_top, 8=resize_bottom, combinations for corners */ + int32_t ROI_DragStartX; + int32_t ROI_DragStartY; + int32_t ROI_InitialX; + int32_t ROI_InitialY; + int32_t ROI_InitialW; + int32_t ROI_InitialH; + +#ifdef CONFIG_GUI_TOUCH_DEBUG + /* Touch debug visualization */ + lv_obj_t *TouchDebugOverlay; + lv_obj_t *TouchDebugCircle; + lv_obj_t *TouchDebugLabel; +#endif +} GUI_Task_State_t; + +/** @brief Initialize the GUI helper functions. + * @param p_GUITask_State Pointer to the GUI task state structure. + * @param Touch_Read_Callback LVGL touch read callback function. + */ +esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t Touch_Read_Callback); + +/** @brief Deinitialize the GUI helper functions. + * @param p_GUITask_State Pointer to the GUI task state structure. + */ +void GUI_Helper_Deinit(GUI_Task_State_t *p_GUITask_State); + +void GUI_Helper_GetSpotTemperature(float Temperature); + +/** @brief LVGL timer callback to update the clock display. + * @param p_Timer Pointer to the LVGL timer structure. + */ +void GUI_Helper_Timer_ClockUpdate(lv_timer_t *p_Timer); + +/** @brief LVGL timer callback to update the spotmeter display. + * @param p_Timer Pointer to the LVGL timer structure. + */ +void GUI_Helper_Timer_SpotUpdate(lv_timer_t *p_Timer); + +/** @brief LVGL timer callback to request spotmeter data update. + * @param p_Timer Pointer to the LVGL timer structure. + */ +void GUI_Helper_Timer_SpotmeterUpdate(lv_timer_t *p_Timer); + +#endif /* GUI_HELPER_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp new file mode 100644 index 0000000..41f20aa --- /dev/null +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -0,0 +1,1182 @@ +/* + * guiTask.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: GUI task implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include "guiTask.h" +#include "Export/ui.h" +#include "Application/application.h" +#include "Application/Manager/managers.h" +#include "Application/Manager/Network/Server/server.h" +#include "Private/guiHelper.h" + +#include "lepton.h" + +ESP_EVENT_DEFINE_BASE(GUI_EVENTS); + +/* Touch calibration ranges (based on measurements) + * Adjusted: RAW_X increased to shift touch point up + */ +const int16_t TOUCH_RAW_X_MIN = 47; +const int16_t TOUCH_RAW_X_MAX = 281; +const int16_t TOUCH_RAW_Y_MIN = 30; +const int16_t TOUCH_RAW_Y_MAX = 234; + +static GUI_Task_State_t _GUITask_State; + +static const char *TAG = "gui_task"; + +/** @brief + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_Devices_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "Devices event received: ID=%d", ID); + + switch (ID) { + case DEVICE_EVENT_RESPONSE_BATTERY_VOLTAGE: { + memcpy(&_GUITask_State.BatteryInfo, p_Data, sizeof(App_Devices_Battery_t)); + + xEventGroupSetBits(_GUITask_State.EventGroup, BATTERY_VOLTAGE_READY); + + break; + } + case DEVICE_EVENT_RESPONSE_CHARGING: { + memcpy(&_GUITask_State.ChargeStatus, p_Data, sizeof(bool)); + + xEventGroupSetBits(_GUITask_State.EventGroup, BATTERY_CHARGING_STATUS_READY); + + break; + } + } +} + +/** @brief Time event handler. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_Time_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "Time event received: ID=%d", ID); + + switch (ID) { + case TIME_EVENT_SYNCHRONIZED: { + break; + } + case TIME_EVENT_SOURCE_CHANGED: { + break; + } + } +} + +/** @brief + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "Network event received: ID=%d", ID); + + switch (ID) { + case NETWORK_EVENT_WIFI_CONNECTED: { + break; + } + case NETWORK_EVENT_WIFI_GOT_IP: { + memcpy(&_GUITask_State.IP_Info, p_Data, sizeof(Network_IP_Info_t)); + _GUITask_State.WiFiConnected = true; + + xEventGroupSetBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + + break; + } + case NETWORK_EVENT_WIFI_DISCONNECTED: { + _GUITask_State.WiFiConnected = false; + + xEventGroupSetBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + + break; + } + case NETWORK_EVENT_PROV_STARTED: { + _GUITask_State.ProvisioningActive = true; + _GUITask_State.WiFiConnected = false; + + xEventGroupSetBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + + break; + } + case NETWORK_EVENT_PROV_STOPPED: { + _GUITask_State.ProvisioningActive = false; + _GUITask_State.WiFiConnected = false; + + xEventGroupSetBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + + /* Also trigger WiFi status update to show correct connection state */ + xEventGroupSetBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + + break; + } + case NETWORK_EVENT_PROV_SUCCESS: { + _GUITask_State.ProvisioningActive = false; + + xEventGroupSetBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + + break; + } + case NETWORK_EVENT_PROV_TIMEOUT: { + _GUITask_State.ProvisioningActive = false; + _GUITask_State.WiFiConnected = false; + + xEventGroupSetBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + + /* Also trigger WiFi status update to show correct connection state */ + xEventGroupSetBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + + break; + } + case NETWORK_EVENT_SERVER_STARTED: { + /* Register thermal frame with server (called after server is started) */ + Server_SetThermalFrame(&_GUITask_State.NetworkFrame); + ESP_LOGD(TAG, "Network frame registered with server"); + + break; + } + case NETWORK_EVENT_AP_STA_CONNECTED: { + break; + } + case NETWORK_EVENT_AP_STA_DISCONNECTED: { + break; + } + } +} + +/** @brief SD card event handler. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_SD_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "SD card event received: ID=%ld", ID); + + switch (ID) { + case SD_EVENT_CARD_CHANGED: { + _GUITask_State.CardPresent = *(bool *)p_Data; + ESP_LOGI(TAG, "SD card %s", (_GUITask_State.CardPresent) ? "inserted" : "removed"); + + xEventGroupSetBits(_GUITask_State.EventGroup, SD_CARD_STATE_CHANGED); + + break; + } + case SD_EVENT_MOUNTED: { + ESP_LOGI(TAG, "SD card mounted successfully event"); + + xEventGroupSetBits(_GUITask_State.EventGroup, SD_CARD_MOUNTED); + + break; + } + case SD_EVENT_MOUNT_ERROR: { + ESP_LOGE(TAG, "SD card mount error event"); + + xEventGroupSetBits(_GUITask_State.EventGroup, SD_CARD_MOUNT_ERROR); + + break; + } + default: { + ESP_LOGW(TAG, "Unknown SD event ID: %ld", ID); + break; + } + } +} + +/** @brief + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_Lepton_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "Lepton event received: ID=%d", ID); + + switch (ID) { + case LEPTON_EVENT_CAMERA_READY: { + memcpy(&_GUITask_State.LeptonDeviceInfo, ((App_Lepton_Device_t *)p_Data), sizeof(App_Lepton_Device_t)); + + xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_CAMERA_READY); + + break; + } + case LEPTON_EVENT_CAMERA_ERROR: { + break; + } + case LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP: { + memcpy(&_GUITask_State.LeptonTemperatures, p_Data, sizeof(App_Lepton_Temperatures_t)); + + xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_TEMP_READY); + + break; + } + case LEPTON_EVENT_RESPONSE_SPOTMETER: { + memcpy(&_GUITask_State.SpotmeterInfo, p_Data, sizeof(App_Lepton_Spotmeter_t)); + + xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_SPOTMETER_READY); + + break; + } + case LEPTON_EVENT_RESPONSE_UPTIME: { + memcpy(&_GUITask_State.LeptonUptime, p_Data, sizeof(uint32_t)); + + xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_UPTIME_READY); + + break; + } + case LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE: { + memcpy(&_GUITask_State.SpotTemperature, p_Data, sizeof(float)); + + xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); + + break; + } + default: { + ESP_LOGW(TAG, "Unhandled Lepton event ID: %d", ID); + break; + } + } +} + +/** @brief Update the information screen labels. + */ +static void GUI_Update_Info(void) +{ + uint8_t mac[6]; + char mac_str[19]; + + esp_efuse_mac_get_default(mac); + snprintf(mac_str, sizeof(mac_str), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + lv_label_set_text(ui_Label_Info_Lepton_Serial, _GUITask_State.LeptonDeviceInfo.SerialNumber); + lv_label_set_text(ui_Label_Info_Lepton_Part, _GUITask_State.LeptonDeviceInfo.PartNumber); + lv_label_set_text(ui_Label_Info_MAC, mac_str); +} + +/** @brief Update the ROI rectangle on the GUI and on the Lepton. + * @param x X position of the ROI (in Lepton coordinates 0-159) + * @param y Y position (in Lepton coordinates 0-119) + * @param w Width of the ROI + * @param h Height of the ROI + */ +static void GUI_Update_ROI(int32_t x, int32_t y, int32_t w, int32_t h) +{ + App_Settings_ROI_t ROI; + + /* Clamp values to Lepton sensor dimensions */ + if (x < 0) { + x = 0; + } + + if (y < 0) { + y = 0; + } + + if (x + w > 160) { + w = 160 - x; + } + + if (y + h > 120) { + h = 120 - y; + } + + /* Minimum size constraints */ + if (w < 10) { + w = 10; + } else if (h < 10) { + h = 10; + } + + ROI = { + .x = (uint16_t)x, + .y = (uint16_t)y, + .w = (uint16_t)w, + .h = (uint16_t)h + }; + + /* Update visual rectangle on display (convert Lepton coords to display coords) */ + if (ui_Image_Main_Thermal_ROI != NULL) { + int32_t display_width; + int32_t display_height; + + ESP_LOGD(TAG, "Updating ROI rectangle - Start: (%ld,%ld), End: (%ld,%ld), Size: %ldx%ld", + ROI.x, ROI.y, ROI.x + ROI.w, ROI.y + ROI.h, ROI.w, ROI.h); + + display_width = lv_obj_get_width(ui_Image_Thermal); + display_height = lv_obj_get_height(ui_Image_Thermal); + + int32_t disp_x = (x * display_width) / 160; + int32_t disp_y = (y * display_height) / 120; + int32_t disp_w = (w * display_width) / 160; + int32_t disp_h = (h * display_height) / 120; + + /* Remove alignment to allow manual positioning */ + lv_obj_set_align(ui_Image_Main_Thermal_ROI, LV_ALIGN_TOP_LEFT); + lv_obj_set_pos(ui_Image_Main_Thermal_ROI, disp_x, disp_y); + lv_obj_set_size(ui_Image_Main_Thermal_ROI, disp_w, disp_h); + } + + /* Send ROI update to Lepton task */ + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_ROI, &ROI, sizeof(App_Settings_ROI_t), portMAX_DELAY); +} + +/** @brief Event handler for ROI reset button. + * Handles both LONG_PRESSED (reset) and CLICKED (toggle visibility). + */ +static void ROI_Clicked_Event_Handler(lv_event_t *e) +{ + lv_event_code_t code = lv_event_get_code(e); + + if (code == LV_EVENT_LONG_PRESSED) { + ESP_LOGD(TAG, "ROI reset - long press detected"); + + /* Set flag to prevent subsequent CLICKED event */ + _GUITask_State.ROI_LongPressActive = true; + + /* Reset ROI to center with default size */ + GUI_Update_ROI(60, 40, 40, 40); + } else if (code == LV_EVENT_CLICKED) { + /* Check if this click came after a long press */ + if (_GUITask_State.ROI_LongPressActive) { + ESP_LOGD(TAG, "ROI click suppressed after long press"); + _GUITask_State.ROI_LongPressActive = false; + return; + } + + ESP_LOGD(TAG, "ROI toggle visibility"); + /* Toggle ROI visibility on normal click */ + if (lv_obj_has_flag(ui_Image_Main_Thermal_ROI, LV_OBJ_FLAG_HIDDEN)) { + lv_obj_clear_flag(ui_Image_Main_Thermal_ROI, LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_add_flag(ui_Image_Main_Thermal_ROI, LV_OBJ_FLAG_HIDDEN); + } + } +} + +/** @brief Event handler for ROI rectangle touch interactions. + * - Normal drag at edges: Immediate resize + * - Long press inside center: Activate move mode + */ +static void ROI_Rectangle_Event_Handler(lv_event_t *e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t *obj = (lv_obj_t *)lv_event_get_target(e); + + if (code == LV_EVENT_PRESSED) { + lv_indev_t *indev = lv_indev_get_act(); + lv_point_t point; + lv_area_t roi_area; + + lv_indev_get_point(indev, &point); + + /* Store initial touch position and ROI state */ + _GUITask_State.ROI_DragStartX = point.x; + _GUITask_State.ROI_DragStartY = point.y; + _GUITask_State.ROI_InitialX = lv_obj_get_x(obj); + _GUITask_State.ROI_InitialY = lv_obj_get_y(obj); + _GUITask_State.ROI_InitialW = lv_obj_get_width(obj); + _GUITask_State.ROI_InitialH = lv_obj_get_height(obj); + + /* Get absolute position of ROI on screen */ + lv_obj_get_coords(obj, &roi_area); + + /* Calculate touch position relative to ROI (not screen) */ + int32_t rel_x = point.x - roi_area.x1; + int32_t rel_y = point.y - roi_area.y1; + int32_t edge_threshold = 20; /* pixels from edge to trigger resize */ + + bool near_left = rel_x < edge_threshold; + bool near_right = rel_x > _GUITask_State.ROI_InitialW - edge_threshold; + bool near_top = rel_y < edge_threshold; + bool near_bottom = rel_y > _GUITask_State.ROI_InitialH - edge_threshold; + + /* Determine resize mode - allow combining edges (e.g., corner resize) */ + _GUITask_State.ROI_ResizeMode = 0; + if (near_left) { + _GUITask_State.ROI_ResizeMode |= 1; /* Left edge */ + } else if (near_right) { + _GUITask_State.ROI_ResizeMode |= 2; /* Right edge */ + } else if (near_top) { + _GUITask_State.ROI_ResizeMode |= 4; /* Top edge */ + } else if (near_bottom) { + _GUITask_State.ROI_ResizeMode |= 8; /* Bottom edge */ + } + + /* If touch is at edge/corner, activate resize immediately */ + if (_GUITask_State.ROI_ResizeMode != 0) { + _GUITask_State.ROI_EditMode = true; + ESP_LOGD(TAG, "ROI RESIZE activated - mode=%d (1=left, 2=right, 4=top, 8=bottom) rel_pos=(%ld,%ld)", + _GUITask_State.ROI_ResizeMode, rel_x, rel_y); + } else { + /* Touch is in center - wait for long press to activate move mode */ + _GUITask_State.ROI_EditMode = false; + ESP_LOGD(TAG, "ROI center pressed - waiting for long press to activate MOVE mode"); + } + } else if (code == LV_EVENT_LONG_PRESSED) { + /* Long press detected - only activate move mode if touch was in center (ResizeMode == 0) */ + if (_GUITask_State.ROI_ResizeMode == 0) { + _GUITask_State.ROI_EditMode = true; + ESP_LOGD(TAG, "ROI MOVE mode ACTIVATED after long press"); + } + } else if (code == LV_EVENT_PRESSING && _GUITask_State.ROI_EditMode) { + lv_indev_t *indev = lv_indev_get_act(); + lv_point_t point; + lv_indev_get_point(indev, &point); + + /* Calculate drag delta */ + int32_t delta_x = point.x - _GUITask_State.ROI_DragStartX; + int32_t delta_y = point.y - _GUITask_State.ROI_DragStartY; + + int32_t img_width = lv_obj_get_width(ui_Image_Thermal); + int32_t img_height = lv_obj_get_height(ui_Image_Thermal); + int32_t min_size = 15; /* Minimum ROI size in display pixels */ + + if (_GUITask_State.ROI_ResizeMode == 0) { + /* Move mode */ + int32_t new_x = _GUITask_State.ROI_InitialX + delta_x; + int32_t new_y = _GUITask_State.ROI_InitialY + delta_y; + + if (new_x < 0) { + new_x = 0; + } else if (new_y < 0) { + new_y = 0; + } else if (new_x + _GUITask_State.ROI_InitialW > img_width) { + new_x = img_width - _GUITask_State.ROI_InitialW; + } else if (new_y + _GUITask_State.ROI_InitialH > img_height) { + new_y = img_height - _GUITask_State.ROI_InitialH; + } + + lv_obj_set_pos(obj, new_x, new_y); + } else { + /* Resize mode */ + int32_t new_x = _GUITask_State.ROI_InitialX; + int32_t new_y = _GUITask_State.ROI_InitialY; + int32_t new_w = _GUITask_State.ROI_InitialW; + int32_t new_h = _GUITask_State.ROI_InitialH; + + /* Resize left edge */ + if (_GUITask_State.ROI_ResizeMode & 1) { + new_x = _GUITask_State.ROI_InitialX + delta_x; + new_w = _GUITask_State.ROI_InitialW - delta_x; + if (new_x < 0) { + new_w += new_x; + new_x = 0; + } else if (new_w < min_size) { + new_x = _GUITask_State.ROI_InitialX + _GUITask_State.ROI_InitialW - min_size; + new_w = min_size; + } + } + + /* Resize right edge */ + if (_GUITask_State.ROI_ResizeMode & 2) { + new_w = _GUITask_State.ROI_InitialW + delta_x; + if (new_x + new_w > img_width) { + new_w = img_width - new_x; + } else if (new_w < min_size) { + new_w = min_size; + } + } + + /* Resize top edge */ + if (_GUITask_State.ROI_ResizeMode & 4) { + new_y = _GUITask_State.ROI_InitialY + delta_y; + new_h = _GUITask_State.ROI_InitialH - delta_y; + if (new_y < 0) { + new_h += new_y; + new_y = 0; + } else if (new_h < min_size) { + new_y = _GUITask_State.ROI_InitialY + _GUITask_State.ROI_InitialH - min_size; + new_h = min_size; + } + } + + /* Resize bottom edge */ + if (_GUITask_State.ROI_ResizeMode & 8) { + new_h = _GUITask_State.ROI_InitialH + delta_y; + if (new_y + new_h > img_height) { + new_h = img_height - new_y; + } else if (new_h < min_size) { + new_h = min_size; + } + } + + lv_obj_set_pos(obj, new_x, new_y); + lv_obj_set_size(obj, new_w, new_h); + } + } else if (code == LV_EVENT_RELEASED) { + /* Only process if edit mode was active (after long press) */ + if (_GUITask_State.ROI_EditMode) { + _GUITask_State.ROI_EditMode = false; + + /* Convert display coordinates back to Lepton coordinates */ + int32_t disp_x = lv_obj_get_x(obj); + int32_t disp_y = lv_obj_get_y(obj); + int32_t disp_w = lv_obj_get_width(obj); + int32_t disp_h = lv_obj_get_height(obj); + + int32_t img_width = lv_obj_get_width(ui_Image_Thermal); + int32_t img_height = lv_obj_get_height(ui_Image_Thermal); + + int32_t lepton_x = (disp_x * 160) / img_width; + int32_t lepton_y = (disp_y * 120) / img_height; + int32_t lepton_w = (disp_w * 160) / img_width; + int32_t lepton_h = (disp_h * 120) / img_height; + + /* Update ROI on Lepton camera */ + GUI_Update_ROI(lepton_x, lepton_y, lepton_w, lepton_h); + + ESP_LOGD(TAG, "ROI edit mode DEACTIVATED - changes saved"); + } else { + ESP_LOGD(TAG, "ROI released without edit mode (short press ignored)"); + } + } +} + +/** @brief Create temperature gradient canvas for palette visualization. + * Generates a vertical gradient from hot (top) to cold (bottom). + */ +static void UI_Canvas_AddTempGradient(void) +{ + /* Generate gradient pixel by pixel */ + uint16_t *buffer = (uint16_t *)_GUITask_State.GradientCanvasBuffer; + + for (uint32_t y = 0; y < _GUITask_State.GradientImageDescriptor.header.h; y++) { + uint32_t index; + + /* Map y position to palette index (0 = top/hot = white, 179 = bottom/cold = black) + * Iron palette: index 0 = black (cold), index 255 = white (hot) + * So we need to invert: top (y=0) should be index 255, bottom (y=179) should be index 0 + */ + index = 255 - (y * 255 / (_GUITask_State.GradientImageDescriptor.header.h - 1)); + + /* Get RGB888 values from palette */ + uint8_t r8 = Lepton_Palette_Iron[index][0]; + uint8_t g8 = Lepton_Palette_Iron[index][1]; + uint8_t b8 = Lepton_Palette_Iron[index][2]; + + /* Convert RGB888 to RGB565 */ + uint16_t r5 = (r8 >> 3) & 0x1F; + uint16_t g6 = (g8 >> 2) & 0x3F; + uint16_t b5 = (b8 >> 3) & 0x1F; + + /* Fill entire row with same color */ + for (uint32_t x = 0; x < _GUITask_State.GradientImageDescriptor.header.w; x++) { + buffer[y * _GUITask_State.GradientImageDescriptor.header.w + x] = (r5 << 11) | (g6 << 5) | b5; + } + } +} + +/** @brief LVGL touch read callback for XPT2046 touch controller. + */ +static void XPT2046_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data) +{ + uint8_t Count = 0; + esp_lcd_touch_point_data_t Data[1]; + esp_lcd_touch_handle_t Touch; + esp_err_t Error; + + Touch = (esp_lcd_touch_handle_t)lv_indev_get_user_data(p_Indev); + esp_lcd_touch_read_data(Touch); + + Error = esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])); + + if ((Error == ESP_OK) && (Count > 0)) { + uint16_t raw_x = Data[0].x; + uint16_t raw_y = Data[0].y; + + /* Clamp raw values to calibrated range */ + int16_t clamped_x = (raw_x < TOUCH_RAW_X_MIN) ? TOUCH_RAW_X_MIN : (raw_x > TOUCH_RAW_X_MAX) ? TOUCH_RAW_X_MAX : raw_x; + int16_t clamped_y = (raw_y < TOUCH_RAW_Y_MIN) ? TOUCH_RAW_Y_MIN : (raw_y > TOUCH_RAW_Y_MAX) ? TOUCH_RAW_Y_MAX : raw_y; + + /* Swap axes and scale: Display X from Raw Y, Display Y from Raw X */ + p_Data->point.x = (clamped_y - TOUCH_RAW_Y_MIN) * (CONFIG_GUI_WIDTH - 1) / (TOUCH_RAW_Y_MAX - TOUCH_RAW_Y_MIN); + p_Data->point.y = (clamped_x - TOUCH_RAW_X_MIN) * (CONFIG_GUI_HEIGHT - 1) / (TOUCH_RAW_X_MAX - TOUCH_RAW_X_MIN); + p_Data->state = LV_INDEV_STATE_PRESSED; + + ESP_LOGD(TAG, "Touch RAW: (%d, %d) -> MAPPED: (%d, %d)", raw_x, raw_y, p_Data->point.x, p_Data->point.y); + +#ifdef CONFIG_GUI_TOUCH_DEBUG + /* Update touch debug visualization */ + if (_GUITask_State.TouchDebugCircle != NULL) { + lv_obj_set_pos(_GUITask_State.TouchDebugCircle, p_Data->point.x - 10, p_Data->point.y - 10); + lv_obj_clear_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_HIDDEN); + } + + if (_GUITask_State.TouchDebugLabel != NULL) { + char buf[64]; + + snprintf(buf, sizeof(buf), "Raw: %u,%u\nMap: %li,%li", raw_x, raw_y, p_Data->point.x, p_Data->point.y); + lv_label_set_text(_GUITask_State.TouchDebugLabel, buf); + lv_obj_clear_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); + } +#endif + } else { + p_Data->state = LV_INDEV_STATE_RELEASED; + +#ifdef CONFIG_GUI_TOUCH_DEBUG + /* Hide touch debug visualization when released */ + if (_GUITask_State.TouchDebugCircle != NULL) { + lv_obj_add_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_HIDDEN); + } + + if (_GUITask_State.TouchDebugLabel != NULL) { + lv_obj_add_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); + } +#endif + } +} + +void Task_GUI(void *p_Parameters) +{ + App_Context_t *App_Context; + + esp_task_wdt_add(NULL); + + App_Context = reinterpret_cast(p_Parameters); + ESP_LOGD(TAG, "GUI Task started on core %d", xPortGetCoreID()); + + /* Show splash screen first */ + /* Initialization process: */ + /* - Loading the settings */ + /* - Waiting for the Lepton */ + do { + EventBits_t EventBits; + + esp_task_wdt_reset(); + + EventBits = xEventGroupGetBits(_GUITask_State.EventGroup); + if (EventBits & LEPTON_CAMERA_READY) { + + lv_bar_set_value(ui_SplashScreen_LoadingBar, 100, LV_ANIM_OFF); + xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_CAMERA_READY); + } + + // TODO: Add timeout + + lv_timer_handler(); + vTaskDelay(100 / portTICK_PERIOD_MS); + } while (lv_bar_get_value(ui_SplashScreen_LoadingBar) < lv_bar_get_max_value(ui_SplashScreen_LoadingBar)); + + lv_disp_load_scr(ui_Main); + + /* Process layout changes after loading new screen */ + lv_timer_handler(); + + /* Set the initial ROI FIRST to give it a size */ + GUI_Update_ROI(App_Context->Settings.Lepton.SpotmeterROI.x, App_Context->Settings.Lepton.SpotmeterROI.y, + App_Context->Settings.Lepton.SpotmeterROI.w, App_Context->Settings.Lepton.SpotmeterROI.h); + lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_PRESSED, NULL); + lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_PRESSING, NULL); + lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_RELEASED, NULL); + + GUI_Update_Info(); + + _GUITask_State.RunTask = true; + while (_GUITask_State.RunTask) { + EventBits_t EventBits; + App_Lepton_FrameReady_t LeptonEvent; + + esp_task_wdt_reset(); + + /* Check for new thermal frame */ + if (xQueueReceive(App_Context->Lepton_FrameEventQueue, &LeptonEvent, 0) == pdTRUE) { + uint8_t *dst; + uint32_t Image_Width; + uint32_t Image_Height; + + /* Scale from source (160x120) to destination (240x180) using bilinear interpolation */ + dst = _GUITask_State.ThermalCanvasBuffer; + Image_Width = lv_obj_get_width(ui_Image_Thermal); + Image_Height = lv_obj_get_height(ui_Image_Thermal); + + /* Skip if image widget not properly initialized yet */ + if ((Image_Width == 0) || (Image_Height == 0)) { + ESP_LOGW(TAG, "Image widget not ready yet (size: %ux%u), skipping frame", Image_Width, Image_Height); + continue; + } + + /* Pre-calculate scaling factors (fixed-point 16.16) */ + uint32_t x_ratio = ((LeptonEvent.Width - 1) << 16) / Image_Width; + uint32_t y_ratio = ((LeptonEvent.Height - 1) << 16) / Image_Height; + + for (uint32_t dst_y = 0; dst_y < Image_Height; dst_y++) { + uint32_t src_y_fixed = dst_y * y_ratio; + uint32_t y0 = src_y_fixed >> 16; + uint32_t y1 = (y0 + 1 < LeptonEvent.Height) ? y0 + 1 : y0; + uint32_t y_frac = (src_y_fixed >> 8) & 0xFF; /* 8-bit fractional part */ + uint32_t y_inv = 256 - y_frac; + + for (uint32_t dst_x = 0; dst_x < Image_Width; dst_x++) { + uint32_t src_x_fixed = dst_x * x_ratio; + uint32_t x0 = src_x_fixed >> 16; + uint32_t x1 = (x0 + 1 < LeptonEvent.Width) ? x0 + 1 : x0; + uint32_t x_frac = (src_x_fixed >> 8) & 0xFF; /* 8-bit fractional part */ + uint32_t x_inv = 256 - x_frac; + + /* Get the four surrounding pixels */ + uint32_t idx00 = (y0 * LeptonEvent.Width + x0) * 3; + uint32_t idx10 = (y0 * LeptonEvent.Width + x1) * 3; + uint32_t idx01 = (y1 * LeptonEvent.Width + x0) * 3; + uint32_t idx11 = (y1 * LeptonEvent.Width + x1) * 3; + + /* Bilinear interpolation using fixed-point arithmetic (8.8 format) */ + /* Weight: (256-x_frac)*(256-y_frac), x_frac*(256-y_frac), etc. */ + uint32_t w00 = (x_inv * y_inv) >> 8; + uint32_t w10 = (x_frac * y_inv) >> 8; + uint32_t w01 = (x_inv * y_frac) >> 8; + uint32_t w11 = (x_frac * y_frac) >> 8; + + uint32_t r = (LeptonEvent.Buffer[idx00 + 0] * w00 + + LeptonEvent.Buffer[idx10 + 0] * w10 + + LeptonEvent.Buffer[idx01 + 0] * w01 + + LeptonEvent.Buffer[idx11 + 0] * w11) >> 8; + + uint32_t g = (LeptonEvent.Buffer[idx00 + 1] * w00 + + LeptonEvent.Buffer[idx10 + 1] * w10 + + LeptonEvent.Buffer[idx01 + 1] * w01 + + LeptonEvent.Buffer[idx11 + 1] * w11) >> 8; + + uint32_t b_val = (LeptonEvent.Buffer[idx00 + 2] * w00 + + LeptonEvent.Buffer[idx10 + 2] * w10 + + LeptonEvent.Buffer[idx01 + 2] * w01 + + LeptonEvent.Buffer[idx11 + 2] * w11) >> 8; + + /* Destination pixel index (rotated 180 degrees) */ + uint32_t rot_y = Image_Height - 1 - dst_y; + uint32_t rot_x = Image_Width - 1 - dst_x; + uint32_t dst_idx = rot_y * Image_Width + rot_x; + + /* Convert to RGB565 - LVGL handles swapping with RGB565_SWAPPED */ + uint16_t rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b_val >> 3); + + /* Low byte first */ + dst[dst_idx * 2 + 0] = rgb565 & 0xFF; + + /* High byte second */ + dst[dst_idx * 2 + 1] = (rgb565 >> 8) & 0xFF; + } + } + + /* Trigger LVGL to redraw the image */ + lv_obj_invalidate(ui_Image_Thermal); + ESP_LOGD(TAG, "Updated thermal image display (src: %ux%u -> dst: %ux%u)", LeptonEvent.Width, LeptonEvent.Height, + Image_Width, Image_Height); + + /* Update network frame for server streaming (if server is running) */ + if (Server_isRunning()) { + if (xSemaphoreTake(_GUITask_State.NetworkFrame.mutex, 0) == pdTRUE) { + /* Convert scaled RGB565 buffer to RGB888 for network transmission */ + uint8_t *rgb888_dst = _GUITask_State.NetworkRGBBuffer; + for (uint32_t i = 0; i < Image_Width * Image_Height; i++) { + /* Read RGB565 value (little endian) */ + uint16_t rgb565 = dst[i * 2 + 0] | (dst[i * 2 + 1] << 8); + + /* Convert RGB565 to RGB888 */ + uint8_t r = ((rgb565 >> 11) & 0x1F) * 255 / 31; + uint8_t g = ((rgb565 >> 5) & 0x3F) * 255 / 63; + uint8_t b = (rgb565 & 0x1F) * 255 / 31; + + /* Store as RGB888 */ + rgb888_dst[i * 3 + 0] = r; + rgb888_dst[i * 3 + 1] = g; + rgb888_dst[i * 3 + 2] = b; + } + + _GUITask_State.NetworkFrame.buffer = _GUITask_State.NetworkRGBBuffer; + _GUITask_State.NetworkFrame.width = Image_Width; + _GUITask_State.NetworkFrame.height = Image_Height; + _GUITask_State.NetworkFrame.timestamp = esp_timer_get_time() / 1000; + + /* Update temperatures from spotmeter data */ + _GUITask_State.NetworkFrame.temp_min = _GUITask_State.SpotmeterInfo.Min; + _GUITask_State.NetworkFrame.temp_max = _GUITask_State.SpotmeterInfo.Max; + _GUITask_State.NetworkFrame.temp_avg = _GUITask_State.SpotmeterInfo.AverageTemperature; + + xSemaphoreGive(_GUITask_State.NetworkFrame.mutex); + } + + /* Notify Websocket handler that a new frame is ready (non-blocking) */ + if (WebSocket_Handler_HasClients()) { + WebSocket_Handler_NotifyFrameReady(); + } + } + } + + /* Process the recieved system events */ + EventBits = xEventGroupGetBits(_GUITask_State.EventGroup); + if (EventBits & STOP_REQUEST) { + + xEventGroupClearBits(_GUITask_State.EventGroup, STOP_REQUEST); + break; + } else if (EventBits & BATTERY_VOLTAGE_READY) { + char buf[8]; + + if (_GUITask_State.BatteryInfo.Percentage == 100) { + lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0x00FF00), 0); + lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_FULL); + } else if (_GUITask_State.BatteryInfo.Percentage >= 75) { + lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0x00FF00), 0); + lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_3); + } else if (_GUITask_State.BatteryInfo.Percentage >= 50) { + lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0xFFFF00), 0); + lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_2); + } else if (_GUITask_State.BatteryInfo.Percentage >= 25) { + lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0xFFFF00), 0); + lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_1); + } else { + lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0xFF0000), 0); + lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_EMPTY); + } + + /* Update percentage text */ + snprintf(buf, sizeof(buf), "%d%%", _GUITask_State.BatteryInfo.Percentage); + lv_label_set_text(ui_Label_Main_Battery_Remaining, buf); + + xEventGroupClearBits(_GUITask_State.EventGroup, BATTERY_VOLTAGE_READY); + } else if ( EventBits & BATTERY_CHARGING_STATUS_READY) { + xEventGroupClearBits(_GUITask_State.EventGroup, BATTERY_CHARGING_STATUS_READY); + } else if (EventBits & WIFI_CONNECTION_STATE_CHANGED) { + if (_GUITask_State.WiFiConnected) { + char ip_buf[16]; + + snprintf(ip_buf, sizeof(ip_buf), "%lu.%lu.%lu.%lu", + (_GUITask_State.IP_Info.IP >> 0) & 0xFF, + (_GUITask_State.IP_Info.IP >> 8) & 0xFF, + (_GUITask_State.IP_Info.IP >> 16) & 0xFF, + (_GUITask_State.IP_Info.IP >> 24) & 0xFF); + + lv_label_set_text(ui_Label_Info_IP, ip_buf); + lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0x00FF00), LV_PART_MAIN); + lv_obj_remove_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); + } else { + lv_label_set_text(ui_Label_Info_IP, "Not connected"); + lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0xFF0000), LV_PART_MAIN); + lv_obj_add_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); + } + + xEventGroupClearBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + } else if (EventBits & PROVISIONING_STATE_CHANGED) { + xEventGroupClearBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + } else if (EventBits & SD_CARD_STATE_CHANGED) { + ESP_LOGI(TAG, "SD card state changed: %s", _GUITask_State.CardPresent ? "present" : "removed"); + + xEventGroupClearBits(_GUITask_State.EventGroup, SD_CARD_STATE_CHANGED); + } else if (EventBits & SD_CARD_MOUNTED) { + ESP_LOGI(TAG, "SD card mounted - updating GUI"); + + xEventGroupClearBits(_GUITask_State.EventGroup, SD_CARD_MOUNTED); + } else if (EventBits & SD_CARD_MOUNT_ERROR) { + ESP_LOGE(TAG, "SD card mount failed - keeping card present status"); + + xEventGroupClearBits(_GUITask_State.EventGroup, SD_CARD_MOUNT_ERROR); + } else if (EventBits & LEPTON_SPOTMETER_READY) { + char temp_buf[16]; + + /* Max temperature (top of gradient) */ + float temp_max_celsius = _GUITask_State.SpotmeterInfo.Max; + snprintf(temp_buf, sizeof(temp_buf), "%.1f°C", temp_max_celsius); + lv_label_set_text(ui_Label_TempScaleMax, temp_buf); + + /* Min temperature (bottom of gradient) */ + float temp_min_celsius = _GUITask_State.SpotmeterInfo.Min;; + snprintf(temp_buf, sizeof(temp_buf), "%.1f°C", temp_min_celsius); + lv_label_set_text(ui_Label_TempScaleMin, temp_buf); + + ESP_LOGD(TAG, "Updated spotmeter temperatures on GUI: Min=%.2f K, Max=%.2f K, Avg=%.2f K", + _GUITask_State.SpotmeterInfo.Min, + _GUITask_State.SpotmeterInfo.Max, + _GUITask_State.SpotmeterInfo.AverageTemperature); + + xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_SPOTMETER_READY); + } else if (EventBits & LEPTON_UPTIME_READY) { + char buf[32]; + uint32_t uptime_sec; + + uptime_sec = _GUITask_State.LeptonUptime / 1000; + + snprintf(buf, sizeof(buf), "%02lu:%02lu:%02lu", uptime_sec / 3600, (uptime_sec % 3600) / 60, uptime_sec % 60); + lv_label_set_text(ui_Label_Info_Lepton_Uptime, buf); + + xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_UPTIME_READY); + } else if (EventBits & LEPTON_TEMP_READY) { + char buf[32]; + + snprintf(buf, sizeof(buf), "%.2f °C", _GUITask_State.LeptonTemperatures.FPA); + lv_label_set_text(ui_Label_Info_Lepton_FPA, buf); + snprintf(buf, sizeof(buf), "%.2f °C", _GUITask_State.LeptonTemperatures.AUX); + lv_label_set_text(ui_Label_Info_Lepton_AUX, buf); + + xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_TEMP_READY); + } else if (EventBits & LEPTON_PIXEL_TEMPERATURE_READY) { + GUI_Helper_GetSpotTemperature(_GUITask_State.SpotTemperature); + + xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); + } + + _lock_acquire(&_GUITask_State.LVGL_API_Lock); + uint32_t time_till_next = lv_timer_handler(); + _lock_release(&_GUITask_State.LVGL_API_Lock); + uint32_t delay_ms = (time_till_next > 0) ? time_till_next : 10; + + /* Reset watchdog at end of loop to prevent timeout during long operations */ + esp_task_wdt_reset(); + + vTaskDelay(delay_ms / portTICK_PERIOD_MS); + } + + esp_task_wdt_delete(NULL); + vTaskDelete(NULL); +} + +esp_err_t GUI_Task_Init(void) +{ + if (_GUITask_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + ESP_ERROR_CHECK(GUI_Helper_Init(&_GUITask_State, XPT2046_LVGL_ReadCallback)); + + /* Initialize the UI elements and trigger a redraw to make all elements accessibile */ + ui_init(); + + /* Use the event loop to receive control signals from other tasks */ + esp_event_handler_register(DEVICE_EVENTS, ESP_EVENT_ANY_ID, on_Devices_Event_Handler, NULL); + esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL); + esp_event_handler_register(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler, NULL); + esp_event_handler_register(TIME_EVENTS, ESP_EVENT_ANY_ID, on_Time_Event_Handler, NULL); + esp_event_handler_register(SD_EVENTS, ESP_EVENT_ANY_ID, on_SD_Event_Handler, NULL); + + _GUITask_State.ThermalCanvasBuffer = (uint8_t *)heap_caps_malloc(240 * 180 * 2, MALLOC_CAP_SPIRAM); + _GUITask_State.GradientCanvasBuffer = (uint8_t *)heap_caps_malloc(20 * 180 * 2, MALLOC_CAP_SPIRAM); + _GUITask_State.NetworkRGBBuffer = (uint8_t *)heap_caps_malloc(240 * 180 * 3, MALLOC_CAP_SPIRAM); + + if (_GUITask_State.ThermalCanvasBuffer == NULL) { + ESP_LOGE(TAG, "Failed to allocate thermal canvas buffer!"); + return ESP_ERR_NO_MEM; + } + + if (_GUITask_State.GradientCanvasBuffer == NULL) { + ESP_LOGE(TAG, "Failed to allocate gradient canvas buffer!"); + heap_caps_free(_GUITask_State.ThermalCanvasBuffer); + return ESP_ERR_NO_MEM; + } + + if (_GUITask_State.NetworkRGBBuffer == NULL) { + ESP_LOGE(TAG, "Failed to allocate network RGB buffer!"); + heap_caps_free(_GUITask_State.ThermalCanvasBuffer); + heap_caps_free(_GUITask_State.GradientCanvasBuffer); + return ESP_ERR_NO_MEM; + } + + /* Initialize buffers with black pixels (RGB565 = 0x0000) */ + memset(_GUITask_State.ThermalCanvasBuffer, 0x00, 240 * 180 * 2); + memset(_GUITask_State.GradientCanvasBuffer, 0x00, 20 * 180 * 2); + + /* Now configure the image descriptors with allocated buffers */ + _GUITask_State.ThermalImageDescriptor.header.cf = LV_COLOR_FORMAT_RGB565; + _GUITask_State.ThermalImageDescriptor.header.w = 240; + _GUITask_State.ThermalImageDescriptor.header.h = 180; + _GUITask_State.ThermalImageDescriptor.data = _GUITask_State.ThermalCanvasBuffer; + _GUITask_State.ThermalImageDescriptor.data_size = 240 * 180 * 2; + + _GUITask_State.GradientImageDescriptor.header.cf = LV_COLOR_FORMAT_RGB565; + _GUITask_State.GradientImageDescriptor.header.w = 20; + _GUITask_State.GradientImageDescriptor.header.h = 180; + _GUITask_State.GradientImageDescriptor.data = _GUITask_State.GradientCanvasBuffer; + _GUITask_State.GradientImageDescriptor.data_size = 20 * 180 * 2; + + UI_Canvas_AddTempGradient(); + + /* Set the images */ + lv_img_set_src(ui_Image_Thermal, &_GUITask_State.ThermalImageDescriptor); + lv_img_set_src(ui_Image_Gradient, &_GUITask_State.GradientImageDescriptor); + +#ifdef CONFIG_GUI_TOUCH_DEBUG + /* Create touch debug visualization overlay on main screen */ + _GUITask_State.TouchDebugOverlay = lv_obj_create(ui_Main); + lv_obj_set_size(_GUITask_State.TouchDebugOverlay, CONFIG_GUI_WIDTH, CONFIG_GUI_HEIGHT); + lv_obj_set_pos(_GUITask_State.TouchDebugOverlay, 0, 0); + lv_obj_set_style_bg_opa(_GUITask_State.TouchDebugOverlay, LV_OPA_TRANSP, 0); + lv_obj_set_style_border_width(_GUITask_State.TouchDebugOverlay, 0, 0); + lv_obj_remove_flag(_GUITask_State.TouchDebugOverlay, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_add_flag(_GUITask_State.TouchDebugOverlay, LV_OBJ_FLAG_FLOATING); + lv_obj_add_flag(_GUITask_State.TouchDebugOverlay, LV_OBJ_FLAG_CLICKABLE); + lv_obj_move_to_index(_GUITask_State.TouchDebugOverlay, -1); /* Move to top layer */ + + /* Create touch indicator circle */ + _GUITask_State.TouchDebugCircle = lv_obj_create(_GUITask_State.TouchDebugOverlay); + lv_obj_set_size(_GUITask_State.TouchDebugCircle, 20, 20); + lv_obj_set_style_radius(_GUITask_State.TouchDebugCircle, LV_RADIUS_CIRCLE, 0); + lv_obj_set_style_bg_color(_GUITask_State.TouchDebugCircle, lv_color_hex(0xFF0000), 0); + lv_obj_set_style_bg_opa(_GUITask_State.TouchDebugCircle, LV_OPA_70, 0); + lv_obj_set_style_border_color(_GUITask_State.TouchDebugCircle, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_border_width(_GUITask_State.TouchDebugCircle, 2, 0); + lv_obj_add_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_CLICKABLE); + lv_obj_remove_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_SCROLLABLE); + + /* Create coordinate label */ + _GUITask_State.TouchDebugLabel = lv_label_create(_GUITask_State.TouchDebugOverlay); + lv_obj_set_pos(_GUITask_State.TouchDebugLabel, 5, 5); + lv_label_set_text(_GUITask_State.TouchDebugLabel, "Touch Debug"); + lv_obj_set_style_text_color(_GUITask_State.TouchDebugLabel, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_bg_color(_GUITask_State.TouchDebugLabel, lv_color_hex(0x000000), 0); + lv_obj_set_style_bg_opa(_GUITask_State.TouchDebugLabel, LV_OPA_70, 0); + lv_obj_set_style_pad_all(_GUITask_State.TouchDebugLabel, 3, 0); + lv_obj_add_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); + lv_obj_remove_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_CLICKABLE); + + ESP_LOGI(TAG, "Touch debug visualization enabled on ui_Main screen"); +#endif + + /* Register event handler for ROI touch interactions (drag & resize) */ + lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_PRESSED, NULL); + lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_LONG_PRESSED, NULL); + lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_PRESSING, NULL); + lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_RELEASED, NULL); + + /* Register ROI button events: long-press for reset, click for toggle */ + lv_obj_add_event_cb(ui_Button_Main_ROI, ROI_Clicked_Event_Handler, LV_EVENT_LONG_PRESSED, NULL); + lv_obj_add_event_cb(ui_Button_Main_ROI, ROI_Clicked_Event_Handler, LV_EVENT_CLICKED, NULL); + + ESP_LOGI(TAG, "ROI event handlers registered and configured for touch interaction"); + + _GUITask_State.ROI_EditMode = false; + _GUITask_State.ROI_LongPressActive = false; + + /* Initialize network frame for server streaming */ + _GUITask_State.NetworkFrame.mutex = xSemaphoreCreateMutex(); + if (_GUITask_State.NetworkFrame.mutex == NULL) { + ESP_LOGE(TAG, "Failed to create NetworkFrame mutex!"); + return ESP_ERR_NO_MEM; + } + + _GUITask_State.isInitialized = true; + + return ESP_OK; +} + +void GUI_Task_Deinit(void) +{ + if (_GUITask_State.isInitialized == false) { + return; + } + + esp_event_handler_unregister(DEVICE_EVENTS, ESP_EVENT_ANY_ID, on_Devices_Event_Handler); + esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); + esp_event_handler_unregister(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler); + esp_event_handler_unregister(TIME_EVENTS, ESP_EVENT_ANY_ID, on_Time_Event_Handler); + esp_event_handler_unregister(SD_EVENTS, ESP_EVENT_ANY_ID, on_SD_Event_Handler); + + ui_destroy(); + + GUI_Helper_Deinit(&_GUITask_State); + + if (_GUITask_State.NetworkFrame.mutex != NULL) { + vSemaphoreDelete(_GUITask_State.NetworkFrame.mutex); + _GUITask_State.NetworkFrame.mutex = NULL; + } + + _GUITask_State.Display = NULL; + _GUITask_State.isInitialized = false; +} + +esp_err_t GUI_Task_Start(App_Context_t *p_AppContext) +{ + BaseType_t ret; + + if (p_AppContext == NULL) { + return ESP_ERR_INVALID_ARG; + } else if (_GUITask_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (_GUITask_State.Running) { + ESP_LOGW(TAG, "Task already running"); + return ESP_OK; + } + + ESP_LOGD(TAG, "Starting GUI Task"); + + ret = xTaskCreatePinnedToCore( + Task_GUI, + "Task_GUI", + CONFIG_GUI_TASK_STACKSIZE, + p_AppContext, + CONFIG_GUI_TASK_PRIO, + &_GUITask_State.GUI_Handle, + CONFIG_GUI_TASK_CORE + ); + + if (ret != pdPASS) { + ESP_LOGE(TAG, "Failed to create GUI task: %d!", ret); + return ESP_ERR_NO_MEM; + } + + _GUITask_State.Running = true; + + return ESP_OK; +} + +esp_err_t GUI_Task_Stop(void) +{ + if (_GUITask_State.Running == false) { + return ESP_OK; + } + + vTaskDelete(_GUITask_State.GUI_Handle); + + _GUITask_State.GUI_Handle = NULL; + _GUITask_State.Running = false; + + return ESP_OK; +} + +bool GUI_Task_isRunning(void) +{ + return _GUITask_State.Running; +} \ No newline at end of file diff --git a/main/Application/Tasks/GUI/guiTask.h b/main/Application/Tasks/GUI/guiTask.h new file mode 100644 index 0000000..e9b04f3 --- /dev/null +++ b/main/Application/Tasks/GUI/guiTask.h @@ -0,0 +1,52 @@ +/* + * guiTask.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: GUI task implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef GUI_TASK_H_ +#define GUI_TASK_H_ + +#include +#include + +#include + +#include "Application/application.h" + +ESP_EVENT_DECLARE_BASE(GUI_EVENTS); + +esp_err_t GUI_Task_Init(void); + +void GUI_Task_Deinit(void); + +esp_err_t GUI_Task_Start(App_Context_t *p_AppContext); + +esp_err_t GUI_Task_Stop(void); + +bool GUI_Task_isRunning(void); + +/** @brief Toggle ROI (Region of Interest) edit mode. + * When enabled, shows a draggable rectangle overlay on the thermal image + * that can be moved by touch to adjust the spotmeter region. + */ +void GUI_Toggle_ROI_EditMode(void); + +#endif /* GUI_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp new file mode 100644 index 0000000..2c4c5d2 --- /dev/null +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -0,0 +1,532 @@ +/* + * leptonTask.c + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Main lepton task implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "lepton.h" +#include "leptonTask.h" +#include "Application/application.h" + +#define LEPTON_TASK_STOP_REQUEST BIT0 +#define LEPTON_TASK_UPDATE_ROI_REQUEST BIT1 +#define LEPTON_TASK_UPDATE_TEMP_REQUEST BIT2 +#define LEPTON_TASK_UPDATE_UPTIME_REQUEST BIT3 +#define LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE BIT4 +#define LEPTON_TASK_UPDATE_SPOTMETER BIT5 + +ESP_EVENT_DEFINE_BASE(LEPTON_EVENTS); + +typedef struct { + bool isInitialized; + bool Running; + bool RunTask; + TaskHandle_t TaskHandle; + EventGroupHandle_t EventGroup; + uint8_t *RGB_Buffer[2]; + uint8_t CurrentReadBuffer; + uint8_t InitializationRetries; + SemaphoreHandle_t BufferMutex; + QueueHandle_t RawFrameQueue; + Lepton_FrameBuffer_t RawFrame; + Lepton_Conf_t LeptonConf; + Lepton_t Lepton; + Lepton_ROI_t ROI; + App_GUI_Screenposition_t ScreenPosition; +} Lepton_Task_State_t; + +static Lepton_Task_State_t _LeptonTask_State; + +static const char *TAG = "lepton_task"; + +static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "GUI event received: ID=%d", ID); + + switch (ID) { + case GUI_EVENT_REQUEST_ROI: { + _LeptonTask_State.ROI.Start_Col = ((App_Settings_ROI_t *)p_Data)->x; + _LeptonTask_State.ROI.Start_Row = ((App_Settings_ROI_t *)p_Data)->y; + _LeptonTask_State.ROI.End_Col = ((App_Settings_ROI_t *)p_Data)->x + ((App_Settings_ROI_t *)p_Data)->w - 1; + _LeptonTask_State.ROI.End_Row = ((App_Settings_ROI_t *)p_Data)->y + ((App_Settings_ROI_t *)p_Data)->h - 1; + + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_ROI_REQUEST); + + break; + } + case GUI_EVENT_REQUEST_FPA_AUX_TEMP: { + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_TEMP_REQUEST); + break; + } + case GUI_EVENT_REQUEST_UPTIME: { + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_UPTIME_REQUEST); + + break; + } + case GUI_EVENT_REQUEST_PIXEL_TEMPERATURE: { + _LeptonTask_State.ScreenPosition = *(App_GUI_Screenposition_t *)p_Data; + + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); + + break; + } + case GUI_EVENT_REQUEST_SPOTMETER: { + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SPOTMETER); + + break; + } + default: { + ESP_LOGW(TAG, "Unhandled GUI event ID: %d", ID); + break; + } + } +} + +/** @brief Lepton camera task main loop. + * @param p_Parameters Pointer to App_Context_t structure + */ +static void Task_Lepton(void *p_Parameters) +{ + App_Context_t *App_Context; + App_Lepton_Device_t DeviceInfo; + + esp_task_wdt_add(NULL); + App_Context = reinterpret_cast(p_Parameters); + + ESP_LOGD(TAG, "Lepton task started on core %d", xPortGetCoreID()); + + /* Format serial number as readable string: XXXX-XXXX-XXXX-XXXX */ + snprintf(DeviceInfo.SerialNumber, sizeof(DeviceInfo.SerialNumber), + "%02X%02X-%02X%02X-%02X%02X-%02X%02X", + _LeptonTask_State.Lepton.SerialNumber[0], _LeptonTask_State.Lepton.SerialNumber[1], + _LeptonTask_State.Lepton.SerialNumber[2], _LeptonTask_State.Lepton.SerialNumber[3], + _LeptonTask_State.Lepton.SerialNumber[4], _LeptonTask_State.Lepton.SerialNumber[5], + _LeptonTask_State.Lepton.SerialNumber[6], _LeptonTask_State.Lepton.SerialNumber[7]); + memcpy(DeviceInfo.PartNumber, _LeptonTask_State.Lepton.PartNumber, sizeof(DeviceInfo.PartNumber)); + + ESP_LOGD(TAG, " Part number: %s", DeviceInfo.PartNumber); + ESP_LOGD(TAG, " Serial number: %s", DeviceInfo.SerialNumber); + + /* Wait for Lepton to stabilize after configuration */ + ESP_LOGD(TAG, "Waiting for Lepton to stabilize..."); + for (uint8_t i = 0; i < 50; i++) { + esp_task_wdt_reset(); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + /* Wait for initial warm-up period */ + ESP_LOGD(TAG, "Waiting for initial warm-up period..."); + for (uint8_t i = 0; i < 50; i++) { + esp_task_wdt_reset(); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_READY, &DeviceInfo, sizeof(App_Lepton_Device_t), portMAX_DELAY); + + ESP_LOGD(TAG, "Start image capturing..."); + + if (Lepton_StartCapture(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrameQueue) != LEPTON_ERR_OK) { + ESP_LOGE(TAG, "Can not start image capturing!"); + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); + } + + _LeptonTask_State.RunTask = true; + while (_LeptonTask_State.RunTask) { + EventBits_t EventBits; + + esp_task_wdt_reset(); + + /* Wait for a new raw frame with longer timeout to avoid busy waiting */ + if (xQueueReceive(_LeptonTask_State.RawFrameQueue, &_LeptonTask_State.RawFrame, 500 / portTICK_PERIOD_MS) == pdTRUE) { + uint8_t WriteBufferIdx; + uint8_t *WriteBuffer; + Lepton_Telemetry_t Telemetry; + + if (_LeptonTask_State.RawFrame.Telemetry_Buffer != NULL) { + memcpy(&Telemetry, _LeptonTask_State.RawFrame.Telemetry_Buffer, sizeof(Lepton_Telemetry_t)); + ESP_LOGD(TAG, "Telemetry - FrameCounter: %u, FPA_Temp: %uK, Housing_Temp: %uK", + Telemetry.FrameCounter, + Telemetry.FPA_Temp, + Telemetry.Housing_Temp); + } + + ESP_LOGD(TAG, "Processing frame..."); + + /* Determine which buffer to write to (ping-pong) */ + if (xSemaphoreTake(_LeptonTask_State.BufferMutex, 100 / portTICK_PERIOD_MS) == pdTRUE) { + /* Find a buffer that's not currently being read */ + WriteBufferIdx = (_LeptonTask_State.CurrentReadBuffer + 1) % 2; + WriteBuffer = _LeptonTask_State.RGB_Buffer[WriteBufferIdx]; + xSemaphoreGive(_LeptonTask_State.BufferMutex); + } else { + ESP_LOGW(TAG, "Failed to acquire mutex for buffer selection!"); + continue; + } + + Lepton_Raw14ToRGB(_LeptonTask_State.RawFrame.Image_Buffer, WriteBuffer, _LeptonTask_State.RawFrame.Width, + _LeptonTask_State.RawFrame.Height); + + /* Mark buffer as ready and update read buffer index */ + if (xSemaphoreTake(_LeptonTask_State.BufferMutex, 100 / portTICK_PERIOD_MS) == pdTRUE) { + _LeptonTask_State.CurrentReadBuffer = WriteBufferIdx; + xSemaphoreGive(_LeptonTask_State.BufferMutex); + } else { + ESP_LOGW(TAG, "Failed to acquire mutex for buffer ready!"); + continue; + } + + /* Send frame notification to network task */ + App_Lepton_FrameReady_t FrameEvent = { + .Buffer = WriteBuffer, + .Width = _LeptonTask_State.RawFrame.Width, + .Height = _LeptonTask_State.RawFrame.Height, + .Channels = 3 + }; + + /* Use xQueueOverwrite to always have the latest frame */ + xQueueOverwrite(App_Context->Lepton_FrameEventQueue, &FrameEvent); + ESP_LOGD(TAG, "Frame sent to queue successfully"); + } else { + /* Timeout waiting for frame */ + ESP_LOGW(TAG, "No raw frame received from VoSPI"); + } + + EventBits = xEventGroupGetBits(_LeptonTask_State.EventGroup); + if (EventBits & LEPTON_TASK_UPDATE_ROI_REQUEST) { + ESP_LOGD(TAG, "Before SetSpotmeterROI - I2C Dev: %p", + _LeptonTask_State.Lepton.Internal.CCI.I2C_Dev_Handle); + + if (Lepton_SetSpotmeterROI(&_LeptonTask_State.Lepton, &_LeptonTask_State.ROI) == LEPTON_ERR_OK) { + Lepton_ROI_t CurrentROI; + + Lepton_GetSpotmeterROI(&_LeptonTask_State.Lepton, &CurrentROI); + ESP_LOGD(TAG, "Current Lepton ROI - Start_Col: %u, Start_Row: %u, End_Col: %u, End_Row: %u", + CurrentROI.Start_Col, + CurrentROI.Start_Row, + CurrentROI.End_Col, + CurrentROI.End_Row); + } else { + ESP_LOGW(TAG, "Failed to update Lepton ROI!"); + } + + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_ROI_REQUEST); + } else if (EventBits & LEPTON_TASK_UPDATE_TEMP_REQUEST) { + uint16_t FPA_Temp; + uint16_t AUX_Temp; + App_Lepton_Temperatures_t Temperatures; + + Lepton_GetTemp(&_LeptonTask_State.Lepton, &FPA_Temp, &AUX_Temp); + + Temperatures.FPA = (static_cast(FPA_Temp) * 0.01f) - 273.0f; + Temperatures.AUX = (static_cast(AUX_Temp) * 0.01f) - 273.0f; + + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP, &Temperatures, sizeof(App_Lepton_Temperatures_t), 0); + + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_TEMP_REQUEST); + } else if (EventBits & LEPTON_TASK_UPDATE_UPTIME_REQUEST) { + uint32_t Uptime; + + Uptime = Lepton_GetUptime(&_LeptonTask_State.Lepton); + + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_UPTIME, &Uptime, sizeof(uint32_t), 0); + + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_UPTIME_REQUEST); + } else if (EventBits & LEPTON_TASK_STOP_REQUEST) { + ESP_LOGI(TAG, "Stop request received"); + + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_STOP_REQUEST); + + break; + } else if (EventBits & LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE) { + int16_t x; + int16_t y; + float Temperature; + + if (_LeptonTask_State.RawFrame.Width == 0 || _LeptonTask_State.RawFrame.Height == 0) { + ESP_LOGW(TAG, "Invalid Lepton frame dimensions, cannot get pixel temperature"); + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); + continue; + } + + /* Convert the screen position to the Lepton frame coordinates */ + x = (_LeptonTask_State.ScreenPosition.x * _LeptonTask_State.RawFrame.Width) / _LeptonTask_State.ScreenPosition.Width; + y = (_LeptonTask_State.ScreenPosition.y * _LeptonTask_State.RawFrame.Height) / _LeptonTask_State.ScreenPosition.Height; + + ESP_LOGD(TAG, "Crosshair center in Lepton Frame: (%d,%d), size (%d,%d)", x, y, _LeptonTask_State.RawFrame.Width, _LeptonTask_State.RawFrame.Height); + + if (Lepton_GetPixelTemperature(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrame.Image_Buffer[(y * _LeptonTask_State.RawFrame.Width) + x], + &Temperature) == LEPTON_ERR_OK) { + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE, &Temperature, sizeof(float), 0); + } else { + ESP_LOGW(TAG, "Failed to get pixel temperature!"); + } + + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); + } else if (EventBits & LEPTON_TASK_UPDATE_SPOTMETER) { + Lepton_Spotmeter_Float_t Spotmeter; + + ESP_LOGD(TAG, "Getting spotmeter - I2C Bus: %p, I2C Dev: %p", + _LeptonTask_State.Lepton.Internal.CCI.I2C_Bus_Handle, + _LeptonTask_State.Lepton.Internal.CCI.I2C_Dev_Handle); + + if (Lepton_GetSpotmeter(&_LeptonTask_State.Lepton, &Spotmeter) == LEPTON_ERR_OK) { + App_Lepton_Spotmeter_t App_Lepton_Spotmeter; + + ESP_LOGD(TAG, "Spotmeter: Spot=%uK, Min=%uK, Max=%uK", + Spotmeter.Value, + Spotmeter.Min, + Spotmeter.Max); + + App_Lepton_Spotmeter.Min = Spotmeter.Min - 273.0f; + App_Lepton_Spotmeter.Max = Spotmeter.Max - 273.0f; + App_Lepton_Spotmeter.AverageTemperature = Spotmeter.Value - 273.0f; + + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_SPOTMETER, &App_Lepton_Spotmeter, sizeof(App_Lepton_Spotmeter_t), + 0); + } else { + ESP_LOGW(TAG, "Failed to read spotmeter!"); + } + + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SPOTMETER); + } + } + + ESP_LOGD(TAG, "Lepton task shutting down"); + Lepton_Deinit(&_LeptonTask_State.Lepton); + + _LeptonTask_State.Running = false; + _LeptonTask_State.TaskHandle = NULL; + + esp_task_wdt_delete(NULL); + vTaskDelete(NULL); +} + +esp_err_t Lepton_Task_Init(void) +{ + Lepton_Error_t Lepton_Error; + + if (_LeptonTask_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + ESP_LOGI(TAG, "Initializing Lepton Task"); + _LeptonTask_State.CurrentReadBuffer = 0; + _LeptonTask_State.InitializationRetries = 0; + + Lepton_Error = LEPTON_ERR_OK; + + /* Create event group */ + _LeptonTask_State.EventGroup = xEventGroupCreate(); + if (_LeptonTask_State.EventGroup == NULL) { + ESP_LOGE(TAG, "Failed to create event group!"); + return ESP_ERR_NO_MEM; + } + + /* Create mutex for buffer synchronization */ + _LeptonTask_State.BufferMutex = xSemaphoreCreateMutex(); + if (_LeptonTask_State.BufferMutex == NULL) { + ESP_LOGE(TAG, "Failed to create buffer mutex!"); + vEventGroupDelete(_LeptonTask_State.EventGroup); + return ESP_ERR_NO_MEM; + } + + /* Allocate 2 RGB buffers for ping-pong buffering */ + _LeptonTask_State.RGB_Buffer[0] = reinterpret_cast(heap_caps_malloc(LEPTON_IMAGE_WIDTH * LEPTON_IMAGE_HEIGHT + * 3, MALLOC_CAP_SPIRAM)); + _LeptonTask_State.RGB_Buffer[1] = reinterpret_cast(heap_caps_malloc(LEPTON_IMAGE_WIDTH * LEPTON_IMAGE_HEIGHT + * 3, MALLOC_CAP_SPIRAM)); + if ((_LeptonTask_State.RGB_Buffer[0] == NULL) || (_LeptonTask_State.RGB_Buffer[1] == NULL)) { + ESP_LOGE(TAG, "Can not allocate RGB buffers!"); + + if (_LeptonTask_State.RGB_Buffer[0]) { + heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); + } + + if (_LeptonTask_State.RGB_Buffer[1]) { + heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); + } + + vSemaphoreDelete(_LeptonTask_State.BufferMutex); + vEventGroupDelete(_LeptonTask_State.EventGroup); + + return ESP_ERR_NO_MEM; + } + + /* Create internal queue to receive raw frames from VoSPI capture task */ + _LeptonTask_State.RawFrameQueue = xQueueCreate(1, sizeof(Lepton_FrameBuffer_t)); + if (_LeptonTask_State.RawFrameQueue == NULL) { + ESP_LOGE(TAG, "Failed to create raw frame queue!"); + + heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); + heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); + vSemaphoreDelete(_LeptonTask_State.BufferMutex); + vEventGroupDelete(_LeptonTask_State.EventGroup); + + return ESP_ERR_NO_MEM; + } + + _LeptonTask_State.LeptonConf = LEPTON_DEFAULT_CONF; + LEPTON_ASSIGN_FUNC(_LeptonTask_State.LeptonConf, NULL, NULL, I2CM_Write, I2CM_Read); + LEPTON_ASSIGN_I2C_HANDLE(_LeptonTask_State.LeptonConf, DevicesManager_GetI2CBusHandle()); + + ESP_LOGI(TAG, "I2C Bus Handle before init: %p", _LeptonTask_State.LeptonConf.CCI.I2C_Bus_Handle); + + Lepton_Error = Lepton_Init(&_LeptonTask_State.Lepton, &_LeptonTask_State.LeptonConf); + if (Lepton_Error != LEPTON_ERR_OK) { + ESP_LOGE(TAG, "Lepton initialization failed with error: %d!", Lepton_Error); + + vQueueDelete(_LeptonTask_State.RawFrameQueue); + heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); + heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); + vSemaphoreDelete(_LeptonTask_State.BufferMutex); + vEventGroupDelete(_LeptonTask_State.EventGroup); + + return ESP_FAIL; + } + + ESP_LOGI(TAG, "I2C Bus Handle after init: %p", _LeptonTask_State.Lepton.Internal.CCI.I2C_Bus_Handle); + ESP_LOGI(TAG, "I2C Dev Handle after init: %p", _LeptonTask_State.Lepton.Internal.CCI.I2C_Dev_Handle); + + /* Use the event loop to receive control signals from other tasks */ + esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL); + + ESP_LOGI(TAG, "Lepton Task initialized"); + + _LeptonTask_State.isInitialized = true; + + return ESP_OK; +} + +void Lepton_Task_Deinit(void) +{ + if (_LeptonTask_State.isInitialized == false) { + return; + } + + if (_LeptonTask_State.Running) { + Lepton_Task_Stop(); + } + + ESP_LOGI(TAG, "Deinitializing Lepton Task"); + + if (_LeptonTask_State.EventGroup != NULL) { + vEventGroupDelete(_LeptonTask_State.EventGroup); + _LeptonTask_State.EventGroup = NULL; + } + + esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); + + Lepton_Deinit(&_LeptonTask_State.Lepton); + + if (_LeptonTask_State.BufferMutex != NULL) { + vSemaphoreDelete(_LeptonTask_State.BufferMutex); + _LeptonTask_State.BufferMutex = NULL; + } + + if (_LeptonTask_State.RGB_Buffer[0] != NULL) { + heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); + _LeptonTask_State.RGB_Buffer[0] = NULL; + } + + if (_LeptonTask_State.RGB_Buffer[1] != NULL) { + heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); + _LeptonTask_State.RGB_Buffer[1] = NULL; + } + + if (_LeptonTask_State.RawFrameQueue != NULL) { + vQueueDelete(_LeptonTask_State.RawFrameQueue); + _LeptonTask_State.RawFrameQueue = NULL; + } + + _LeptonTask_State.isInitialized = false; +} + +esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext) +{ + BaseType_t Ret; + + if (p_AppContext == NULL) { + return ESP_ERR_INVALID_ARG; + } else if (_LeptonTask_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (_LeptonTask_State.Running) { + ESP_LOGW(TAG, "Task already Running"); + return ESP_OK; + } + + ESP_LOGD(TAG, "Starting Lepton Task"); + Ret = xTaskCreatePinnedToCore( + Task_Lepton, + "Task_Lepton", + CONFIG_LEPTON_TASK_STACKSIZE, + p_AppContext, + CONFIG_LEPTON_TASK_PRIO, + &_LeptonTask_State.TaskHandle, + CONFIG_LEPTON_TASK_CORE + ); + + if (Ret != pdPASS) { + ESP_LOGE(TAG, "Failed to create Lepton Task: %d!", Ret); + return ESP_ERR_NO_MEM; + } + + _LeptonTask_State.Running = true; + + return ESP_OK; +} + +esp_err_t Lepton_Task_Stop(void) +{ + if (_LeptonTask_State.Running == false) { + return ESP_OK; + } + + ESP_LOGI(TAG, "Stopping Lepton Task"); + + /* Signal task to stop */ + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_STOP_REQUEST); + + /* Wait for task to set Running = false before deleting itself */ + for (int i = 0; i < 20 && _LeptonTask_State.Running; i++) { + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + _LeptonTask_State.TaskHandle = NULL; + _LeptonTask_State.Running = false; + + return ESP_OK; +} + +bool Lepton_Task_isRunning(void) +{ + return _LeptonTask_State.Running; +} \ No newline at end of file diff --git a/main/Application/Tasks/Lepton/leptonTask.h b/main/Application/Tasks/Lepton/leptonTask.h new file mode 100644 index 0000000..b301874 --- /dev/null +++ b/main/Application/Tasks/Lepton/leptonTask.h @@ -0,0 +1,51 @@ +/* + * leptonTask.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Lepton camera task for thermal image processing. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef LEPTON_TASK_H_ +#define LEPTON_TASK_H_ + +#include +#include + +#include + +#include "Application/application.h" +#include "Application/Manager/Devices/devices.h" + +esp_err_t Lepton_Task_Init(void); + +void Lepton_Task_Deinit(void); + +esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext); + +/** @brief Stop the Lepton task + * @return ESP_OK on success, error code otherwise + */ +esp_err_t Lepton_Task_Stop(void); + +/** @brief Check if the Lepton task is currently running + * @return true if running, false otherwise + */ +bool Lepton_Task_isRunning(void); + +#endif /* LEPTON_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp new file mode 100644 index 0000000..5b313e1 --- /dev/null +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -0,0 +1,437 @@ +/* + * networkTask.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Network task implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include "networkTask.h" +#include "Application/Manager/managers.h" +#include "Application/Tasks/GUI/guiTask.h" + +#define NETWORK_TASK_STOP_REQUEST BIT0 +#define NETWORK_TASK_BROADCAST_FRAME BIT1 +#define NETWORK_TASK_PROV_SUCCESS BIT2 +#define NETWORK_TASK_WIFI_CONNECTED BIT3 +#define NETWORK_TASK_WIFI_DISCONNECTED BIT4 +#define NETWORK_TASK_PROV_TIMEOUT BIT5 +#define NETWORK_TASK_OPEN_WIFI_REQUEST BIT6 + +typedef struct { + bool isInitialized; + bool Running; + TaskHandle_t TaskHandle; + EventGroupHandle_t EventGroup; + uint32_t StartTime; + bool RunTask; + bool isConnected; + Network_State_t State; + Network_WiFiMode_t WiFi_Mode; +} Network_Task_State_t; + +static Network_Task_State_t _NetworkTask_State; + +static const char *TAG = "network_task"; + +/** @brief Network event handler for task coordination. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + switch (ID) { + case NETWORK_EVENT_WIFI_CONNECTED: { + ESP_LOGD(TAG, "WiFi connected"); + + /* Notify Time Manager that network is available */ + TimeManager_OnNetworkConnected(); + + break; + } + case NETWORK_EVENT_WIFI_DISCONNECTED: { + ESP_LOGD(TAG, "WiFi disconnected"); + + /* Notify Time Manager that network is unavailable */ + TimeManager_OnNetworkDisconnected(); + + _NetworkTask_State.State = NETWORK_STATE_DISCONNECTED; + _NetworkTask_State.isConnected = false; + + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_DISCONNECTED); + + break; + } + case NETWORK_EVENT_WIFI_GOT_IP: { + _NetworkTask_State.State = NETWORK_STATE_CONNECTED; + _NetworkTask_State.isConnected = true; + + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CONNECTED); + + break; + } + case NETWORK_EVENT_PROV_SUCCESS: { + ESP_LOGI(TAG, "Provisioning success"); + + /* Signal task to handle WiFi restart with new credentials */ + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); + + break; + } + case NETWORK_EVENT_PROV_FAILED: { + ESP_LOGE(TAG, "Provisioning failed!"); + + /* Fall back to AP mode if configured */ + if ((_NetworkTask_State.WiFi_Mode == NETWORK_WIFI_MODE_AP) || + (_NetworkTask_State.WiFi_Mode == NETWORK_WIFI_MODE_APSTA)) { + ESP_LOGI(TAG, "Falling back to AP mode"); + NetworkManager_StartAP(); + } + + break; + } + case NETWORK_EVENT_PROV_TIMEOUT: { + ESP_LOGW(TAG, "Provisioning timeout - stopping provisioning"); + + /* Stop provisioning in task context (not timer context) */ + Provisioning_Stop(); + + /* Fall back to AP mode if configured */ + if ((_NetworkTask_State.WiFi_Mode == NETWORK_WIFI_MODE_AP) || + (_NetworkTask_State.WiFi_Mode == NETWORK_WIFI_MODE_APSTA)) { + ESP_LOGI(TAG, "Falling back to AP mode"); + NetworkManager_StartAP(); + } + break; + } + case NETWORK_EVENT_OPEN_WIFI_REQUEST: { + ESP_LOGI(TAG, "Open WiFi request received"); + + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); + + break; + } + default: { + break; + } + } +} + +/** @brief Network task main loop. + * @param p_Parameters Pointer to App_Context_t structure + */ +static void Task_Network(void *p_Parameters) +{ + App_Context_t *App_Context; + + esp_task_wdt_add(NULL); + + App_Context = reinterpret_cast(p_Parameters); + ESP_LOGD(TAG, "Network task started on core %d", xPortGetCoreID()); + + /* + do { + EventBits_t EventBits; + + esp_task_wdt_reset(); + + EventBits = xEventGroupGetBits(_NetworkTask_State.EventGroup); + if (EventBits & NETWORK_TASK_OPEN_WIFI_REQUEST) { + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); + break; + } + + vTaskDelay(100 / portTICK_PERIOD_MS); + } while (true);*/ + + /* Try to load stored WiFi credentials */ + NetworkManager_LoadCredentials(); + if ((App_Context->Network_Config.Prov_Method != NETWORK_PROV_NONE) && (Provisioning_isProvisioned() == false) && + ((strlen(App_Context->Network_Config.STA_Config.ssid) == 0))) { + + /* No credentials, start provisioning */ + ESP_LOGI(TAG, "No credentials found, starting provisioning"); + + Provisioning_Start(); + + _NetworkTask_State.State = NETWORK_STATE_PROVISIONING; + } else { + /* Start WiFi based on mode */ + switch (App_Context->Network_Config.WiFi_Mode) { + case NETWORK_WIFI_MODE_STA: + NetworkManager_StartSTA(); + break; + case NETWORK_WIFI_MODE_AP: + NetworkManager_StartAP(); + break; + case NETWORK_WIFI_MODE_APSTA: + NetworkManager_StartAPSTA(); + break; + } + } + + _NetworkTask_State.RunTask = true; + while (_NetworkTask_State.RunTask) { + uint32_t NotificationValue = 0; + EventBits_t EventBits; + + esp_task_wdt_reset(); + + /* Check for task notifications (from timer callbacks) */ + if (xTaskNotifyWait(0, 0xFFFFFFFF, &NotificationValue, 0) == pdTRUE) { + if (NotificationValue & 0x01) { + /* Provisioning timeout notification */ + ESP_LOGW(TAG, "Provisioning timeout"); + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); + } + } + + EventBits = xEventGroupGetBits(_NetworkTask_State.EventGroup); + if (EventBits & NETWORK_TASK_STOP_REQUEST) { + ESP_LOGD(TAG, "Stop request received"); + + _NetworkTask_State.RunTask = false; + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_STOP_REQUEST); + + break; + } else if (EventBits & NETWORK_TASK_WIFI_CONNECTED) { + ESP_LOGD(TAG, "Handling WiFi connection"); + + if (NetworkManager_StartServer(&App_Context->Server_Config) == ESP_OK) { + ESP_LOGI(TAG, "HTTP/WebSocket server started"); + + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SERVER_STARTED, NULL, 0, portMAX_DELAY); + } else { + ESP_LOGE(TAG, "Failed to start HTTP/WebSocket server"); + + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SERVER_ERROR, NULL, 0, portMAX_DELAY); + } + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CONNECTED); + } else if (EventBits & NETWORK_TASK_WIFI_DISCONNECTED) { + ESP_LOGD(TAG, "Handling WiFi disconnection"); + + Provisioning_Start(); + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_DISCONNECTED); + } else if (EventBits & NETWORK_TASK_PROV_SUCCESS) { + ESP_LOGD(TAG, "Handling provisioning success"); + + Provisioning_Stop(); + + /* Restart WiFi in STA mode with new credentials */ + NetworkManager_Stop(); + NetworkManager_StartSTA(); + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); + } else if (EventBits & NETWORK_TASK_PROV_TIMEOUT) { + ESP_LOGW(TAG, "Handling provisioning timeout"); + + Provisioning_Stop(); + + /* Post event for GUI */ + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_TIMEOUT, NULL, 0, portMAX_DELAY); + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); + } + + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + ESP_LOGD(TAG, "Network task shutting down"); + Provisioning_Stop(); + NetworkManager_Stop(); + + _NetworkTask_State.Running = false; + _NetworkTask_State.TaskHandle = NULL; + + esp_task_wdt_delete(NULL); + vTaskDelete(NULL); +} + +esp_err_t Network_Task_Init(App_Context_t *p_AppContext) +{ + esp_err_t Error; + + if (p_AppContext == NULL) { + return ESP_ERR_INVALID_ARG; + } else if (_NetworkTask_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; + } + + ESP_LOGD(TAG, "Initializing network task"); + + /* Initialize NVS */ + Error = nvs_flash_init(); + if ((Error == ESP_ERR_NVS_NO_FREE_PAGES) || (Error == ESP_ERR_NVS_NEW_VERSION_FOUND)) { + ESP_ERROR_CHECK(nvs_flash_erase()); + Error = nvs_flash_init(); + } + + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to init NVS flash: %d!", Error); + return Error; + } + + /* Create event group */ + _NetworkTask_State.EventGroup = xEventGroupCreate(); + if (_NetworkTask_State.EventGroup == NULL) { + ESP_LOGE(TAG, "Failed to create event group!"); + return ESP_ERR_NO_MEM; + } + + /* Register event handler for network events */ + Error = esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to register event handler: %d!", Error); + + vEventGroupDelete(_NetworkTask_State.EventGroup); + + return Error; + } + + Error = NetworkManager_Init(&p_AppContext->Network_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to init WiFi manager: %d!", Error); + + esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); + vEventGroupDelete(_NetworkTask_State.EventGroup); + + return Error; + } + + Error = Provisioning_Init(p_AppContext->Network_Config.Prov_Method, &p_AppContext->Network_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to init provisioning: %d!", Error); + /* Continue anyway, provisioning is optional */ + } + + _NetworkTask_State.State = NETWORK_STATE_IDLE; + _NetworkTask_State.WiFi_Mode = p_AppContext->Network_Config.WiFi_Mode; + _NetworkTask_State.isInitialized = true; + + ESP_LOGI(TAG, "Network Task initialized"); + + return ESP_OK; +} + +void Network_Task_Deinit(void) +{ + if (_NetworkTask_State.isInitialized == false) { + return; + } + + ESP_LOGI(TAG, "Deinitializing Network Task"); + + Network_Task_Stop(); + Provisioning_Deinit(); + NetworkManager_Deinit(); + + esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); + + if (_NetworkTask_State.EventGroup != NULL) { + vEventGroupDelete(_NetworkTask_State.EventGroup); + _NetworkTask_State.EventGroup = NULL; + } + + _NetworkTask_State.isInitialized = false; +} + +/** @brief Start the network task. + * @param p_AppContext Pointer to application context + * @return ESP_OK on success, error code otherwise + */ +esp_err_t Network_Task_Start(App_Context_t *p_AppContext) +{ + BaseType_t Ret; + + if (_NetworkTask_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (_NetworkTask_State.Running) { + ESP_LOGW(TAG, "Task already Running"); + return ESP_OK; + } + + ESP_LOGI(TAG, "Starting Network Task"); + Ret = xTaskCreatePinnedToCore( + Task_Network, + "Task_Network", + CONFIG_NETWORK_TASK_STACKSIZE, + p_AppContext, + CONFIG_NETWORK_TASK_PRIO, + &_NetworkTask_State.TaskHandle, + CONFIG_NETWORK_TASK_CORE + ); + + if (Ret != pdPASS) { + ESP_LOGE(TAG, "Failed to create network task!"); + return ESP_ERR_NO_MEM; + } + + /* Register task handle with provisioning for timeout notification */ + Provisioning_SetNetworkTaskHandle(_NetworkTask_State.TaskHandle); + _NetworkTask_State.Running = true; + _NetworkTask_State.StartTime = xTaskGetTickCount() * portTICK_PERIOD_MS / 1000; + + return ESP_OK; +} + +esp_err_t Network_Task_Stop(void) +{ + if (_NetworkTask_State.Running == false) { + return ESP_OK; + } + + ESP_LOGI(TAG, "Stopping Network Task"); + + /* Signal task to stop */ + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_STOP_REQUEST); + + /* Wait for task to set Running = false before deleting itself */ + for (uint8_t i = 0; i < 20 && _NetworkTask_State.Running; i++) { + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + _NetworkTask_State.TaskHandle = NULL; + _NetworkTask_State.Running = false; + + return ESP_OK; +} + +bool Network_Task_isRunning(void) +{ + return _NetworkTask_State.Running; +} \ No newline at end of file diff --git a/main/Application/Tasks/Network/networkTask.h b/main/Application/Tasks/Network/networkTask.h new file mode 100644 index 0000000..d99d309 --- /dev/null +++ b/main/Application/Tasks/Network/networkTask.h @@ -0,0 +1,45 @@ +/* + * networkTask.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Network task for WiFi and HTTP server management. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef NETWORK_TASK_H_ +#define NETWORK_TASK_H_ + +#include +#include + +#include + +#include "Application/application.h" +#include "Application/Manager/Network/network_types.h" + +esp_err_t Network_Task_Init(App_Context_t *p_AppContext); + +void Network_Task_Deinit(void); + +esp_err_t Network_Task_Start(App_Context_t *p_AppContext); + +esp_err_t Network_Task_Stop(void); + +bool Network_Task_isRunning(void); + +#endif /* NETWORK_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/tasks.h b/main/Application/Tasks/tasks.h new file mode 100644 index 0000000..58a9fc1 --- /dev/null +++ b/main/Application/Tasks/tasks.h @@ -0,0 +1,32 @@ +/* + * tasks.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Task includes for all application tasks. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef TASKS_H_ +#define TASKS_H_ + +#include "Lepton/leptonTask.h" +#include "Network/networkTask.h" +#include "Devices/devicesTask.h" +#include "GUI/guiTask.h" + +#endif /* TASKS_H_ */ \ No newline at end of file diff --git a/main/Application/application.h b/main/Application/application.h new file mode 100644 index 0000000..276034a --- /dev/null +++ b/main/Application/application.h @@ -0,0 +1,134 @@ +/* + * application.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Application header file. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef APPLICATION_H_ +#define APPLICATION_H_ + +#include +#include +#include + +#include "Manager/managers.h" + +#include + +ESP_EVENT_DECLARE_BASE(LEPTON_EVENTS); +ESP_EVENT_DECLARE_BASE(DEVICE_EVENTS); +ESP_EVENT_DECLARE_BASE(GUI_EVENTS); +ESP_EVENT_DECLARE_BASE(SD_EVENTS); + +/** @brief Lepton camera event identifiers. + */ +enum { + LEPTON_EVENT_CAMERA_READY, /**< Lepton camera is ready. */ + LEPTON_EVENT_CAMERA_ERROR, /**< Lepton camera error occurred. + Data is transmitted in a App_Lepton_Device_t structure. */ + LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP, /**< FPA and AUX temperatures are ready. + Data is transmitted in a App_Lepton_Temperatures_t structure. */ + LEPTON_EVENT_RESPONSE_SPOTMETER, /**< Spotmeter data is ready. + Data is transmitted in a App_Lepton_Spotmeter_t structure. */ + LEPTON_EVENT_RESPONSE_UPTIME, /**< Uptime data is ready. + Data is transmitted as a uint32_t representing uptime in milliseconds. */ + LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE, /**< Pixel temperature data is ready. + Data is transmitted as a float. */ +}; + +/** @brief Device status event identifiers. + */ +enum { + DEVICE_EVENT_RESPONSE_BATTERY_VOLTAGE, /**< New battery voltage reading available. + Data is transmitted in a App_Devices_Battery_t structure. */ + DEVICE_EVENT_RESPONSE_CHARGING, /**< Charging state changed. + Data is transmitted as a bool. */ + DEVICE_EVENT_RESPONSE_TIME, /**< Device RTC time has been updated. + Data is transmitted in a struct tm structure. */ +}; + +/** @brief GUI event identifiers. + */ +enum { + GUI_EVENT_INIT_DONE, /**< GUI task initialization done. */ + GUI_EVENT_REQUEST_ROI, /**< Update the ROI rectangle on the GUI. */ + GUI_EVENT_REQUEST_FPA_AUX_TEMP, /**< Request update of the FPA and AUX temperature. */ + GUI_EVENT_REQUEST_UPTIME, /**< Request update of the uptime. */ + GUI_EVENT_UPDATE_INFO, /**< Update the information screen. */ + GUI_EVENT_REQUEST_PIXEL_TEMPERATURE, /**< Request update of pixel temperature. + Data is transmitted in a App_GUI_Screenposition_t structure. */ + GUI_EVENT_REQUEST_SPOTMETER, /**< Request update of spotmeter data. */ +}; + +/** @brief Structure representing a screen position. + */ +typedef struct { + int16_t x; /**< X coordinate. */ + int16_t y; /**< Y coordinate. */ + int32_t Width; /**< Width of the screen element where the position is related to. */ + int32_t Height; /**< Height of the screen element where the position is related to. */ +} App_GUI_Screenposition_t; + +/** @brief Structure representing battery information. + */ +typedef struct { + int Voltage; /**< Battery voltage in millivolts. */ + int Percentage; /**< Battery percentage (0-100%). */ +} App_Devices_Battery_t; + +/** @brief Structure representing a ready frame from the Lepton camera. + */ +typedef struct { + uint8_t *Buffer; + uint32_t Width; + uint32_t Height; + uint32_t Channels; +} App_Lepton_FrameReady_t; + +/** @brief Structure representing FPA and AUX temperature from the Lepton camera. + */ +typedef struct { + float FPA; /**< Focal Plane Array temperature in Degree Celsius. */ + float AUX; /**< Auxiliary temperature in Degree Celsius. */ +} App_Lepton_Temperatures_t; + +/** @brief Structure representing the Lepton camera device status. + */ +typedef struct { + char PartNumber[33]; /**< Lepton device part number. */ + char SerialNumber[24]; /**< Lepton device serial number formatted as "XXXX-XXXX-XXXX-XXXX". */ +} App_Lepton_Device_t; + +/** @brief Structure representing the spotmeter results from the Lepton camera. + */ +typedef struct { + float Max; /**< Maximum temperature value in Degree Celsius within the spotmeter ROI. */ + float Min; /**< Minimum temperature value in Degree Celsius within the spotmeter ROI. */ + float AverageTemperature; /**< Average temperature value in Degree Celsius within the spotmeter ROI. */ +} App_Lepton_Spotmeter_t; + +/** @brief Application context aggregating shared resources. + */ +typedef struct { + QueueHandle_t Lepton_FrameEventQueue; + Network_Config_t Network_Config; + Server_Config_t Server_Config; + App_Settings_t Settings; +} App_Context_t; + +#endif /* APPLICATION_H_ */ \ No newline at end of file diff --git a/main/Application/bitmap.h b/main/Application/bitmap.h new file mode 100644 index 0000000..db35beb --- /dev/null +++ b/main/Application/bitmap.h @@ -0,0 +1,122 @@ +/*****************************************************************************/ +/** +* @file bitmap.h +* +* Bitmap file format definitions. +* +* Copyright (C) Daniel Kampert, 2026 +* Website: www.kampis-elektroecke.de +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +* Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date        Changes
+* ----- ---  --------    -----------------------------------------------
+* 1.00  dk   11.12.2022  First release
+*
+* 
+******************************************************************************/ + +#ifndef BITMAP_H_ +#define BITMAP_H_ + +#include + +/** @brief Magic number for the \ref Bitmap_BMP_Header_t.bType field. + * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. + */ +#define BITMAP_MAGIC 0x4D42 + +/** @brief Byte offset for the blue color channel. + */ +#define BITMAP_BLUE_OFFSET 0 + +/** @brief Byte offset for the green color channel. + */ +#define BITMAP_GREEN_OFFSET 1 + +/** @brief Byte offset for the red color channel. + */ +#define BITMAP_RED_OFFSET 2 + +/** @brief Bitmap compressions of the \ref Bitmap_DIB_Header_t.biCompression field. + * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. + */ +typedef enum { + BITMAP_COMP_RGB = 0x00, /**< Uncompressed image data. */ + BITMAP_COMP_RLE8 = 0x01, /**< Run length coded for 8 bpp. Only allowed then \ref Bitmap_DIB_Header_t.biBitCount = 8 and \ref biBitCount.biHeight > 0. */ + BITMAP_COMP_RLE4 = 0x02, /**< Run length coded for 4 bpp. Only allowed then \ref Bitmap_DIB_Header_t.biBitCount = 4 and \ref biBitCount.biHeight > 0. */ + BITMAP_COMP_BITFIELDS = 0x03 /**< Uncompressed and customized image data. Only allowed then \ref Bitmap_DIB_Header_t.biBitCount = 16 or 32. */ +} Bitmap_Compression_t; + +/** @brief 16 bpp pixel object. + * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. + */ +typedef union { + struct { + uint8_t Blue: 5; /**< Blue color channel. */ + uint8_t Green: 6; /**< Green color channel. */ + uint8_t Red: 5; /**< Red color channel. */ + } BGR; + uint16_t Raw; /**< RGB raw data. */ +} __attribute__((packed)) Bitmap_16bpp_t; + +/** @brief 24 bpp pixel object. + * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. + */ +typedef union { + struct { + uint8_t Blue; /**< Blue color channel. */ + uint8_t Green; /**< Green color channel. */ + uint8_t Red; /**< Red color channel. */ + } BGR; + uint8_t Raw[3]; /**< RGB raw data. */ +} __attribute__((packed)) Bitmap_24bpp_t; + +/** @brief Bitmap file header. + * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. + */ +typedef struct { + uint16_t bType; /**< Contains the characters "BM". */ + uint32_t bfSize; /**< Size of the bitmap in bytes. */ + uint16_t bReserved; /**< Reserved. Default 0. */ + uint16_t bReserved1; /**< Reserved. Default 0. */ + uint32_t bfOffBits; /**< Image data offset. */ +} __attribute__((packed)) Bitmap_BMP_Header_t; + +/** @brief Bitmap information header. + * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. + */ +typedef struct { + uint32_t biSize; /**< Size of the \ref Bitmap_DIB_Header_t in bytes. */ + int32_t biWidth; /**< Width of the bitmap in pixel. The first byte contains the LSB, the last byte contains the MSB. */ + int32_t biHeight; /**< Height of the bitmap in pixel. The first byte contains the LSB, the last byte contains the MSB. + - Positive value: The image data start with the bottom row (bottom-up). + - Negative value: The image data start with the top row (top-down). */ + uint16_t biPlanes; /**< Always 1. */ + uint16_t biBitCount; /**< Color depth of the bitmap in bpp. */ + uint32_t biCompression; /**< Bitmap compression. See \ref Bitmap_Compression_t for more information. */ + uint32_t biSizeImage; /**< When \ref Bitmap_DIB_Header_t.biBitCount = BI_RGB: 0 or image size in bytes. + Else: Image size in bytes. */ + int32_t biXPelsPerMeter; /**< Horizontal resolution of the target output device. Is set to 0 mostly. */ + int32_t biYPelsPerMeter; /**< Vertical resolution of the target output device. Is set to 0 mostly. */ + uint32_t biClrUsed; /**< When \ref Bitmap_DIB_Header_t.biBitCount = 1: 0. + When \ref Bitmap_DIB_Header_t.biBitCount = 4 or 8: Color table entry count. If value is 0 the maximum count (2, 16 or 256) is used. + Else: Color table entry count (0 = no color table). */ + uint32_t biClrImportant; /**< When \ref Bitmap_DIB_Header_t.biBitCount = 1, 4 or 8: Number of colors used in the image. All colors of the color table when 0. + Else: When: Number of colors when a color table with all used colors is available. + Else: 0. */ +} __attribute__((packed)) Bitmap_DIB_Header_t; + +#endif /* BITMAP_H_ */ \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt new file mode 100644 index 0000000..070d80a --- /dev/null +++ b/main/CMakeLists.txt @@ -0,0 +1,13 @@ +FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/main/*.*) + +idf_component_register(SRCS ${app_sources} + REQUIRES esp_http_server esp_timer esp_wifi json nvs_flash driver +) + +target_add_binary_data(${COMPONENT_TARGET} "../LICENSE" TEXT) + +target_compile_definitions(${COMPONENT_LIB} PUBLIC + PYROVISION_VERSION_MAJOR=1 + PYROVISION_VERSION_MINOR=0 + PYROVISION_VERSION_BUILD=0 +) \ No newline at end of file diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild new file mode 100644 index 0000000..3dd3f78 --- /dev/null +++ b/main/Kconfig.projbuild @@ -0,0 +1,237 @@ +menu "PyroVision" + menu "Network" + menu "Task" + config NETWORK_TASK_STACKSIZE + int "Stack size" + default 8192 + + config NETWORK_TASK_PRIO + int "Task prio" + default 16 + + config NETWORK_TASK_CORE + int "Task core" + default 1 + endmenu + + menu "VISA" + config NETWORK_VISA_DEVICE_MANUFACTURER + string "Device manufacturer" + default "PyroVision" + + config NETWORK_VISA_DEVICE_MODEL + string "Device model" + default "PyroVision" + + config NETWORK_VISA_DEVICE_SERIAL + string "Device manufacturer" + default "0000001" + endmenu + endmenu + + menu "Lepton" + menu "Task" + config LEPTON_TASK_STACKSIZE + int "Stack size" + default 4096 + + config LEPTON_TASK_PRIO + int "Task prio" + default 12 + + config LEPTON_TASK_CORE + int "Task core" + default 1 + endmenu + endmenu + + menu "Devices" + menu "I2C" + config DEVICES_I2C_HOST + int "I2C interface" + range 0 2 + default 1 + + config DEVICES_I2C_SCL + int "SCL pin number" + range 0 48 + default 21 + + config DEVICES_I2C_SDA + int "SDA pin number" + range 0 48 + default 47 + endmenu + + menu "SPI" + config SPI_SCLK + int "SCLK GPIO number" + range 0 48 + default 46 + + config SPI_MOSI + int "MOSI GPIO number" + range 0 48 + default 48 + + config SPI_MISO + int "MISO GPIO number" + range 0 48 + default 9 + + config SPI_TRANSFER_SIZE + int "Max. transfer size in bytes" + default 4096 + + menu "Touch" + choice + prompt "Touch SPI Bus" + default TOUCH_SPI3_HOST + help + Select the SPI Bus the Touch Controller is attached to. + + config TOUCH_SPI2_HOST + bool "SPI2_HOST" + config TOUCH_SPI3_HOST + bool "SPI3_HOST" + endchoice + + config TOUCH_CLOCK + int "Touch SPI clock" + default 2000000 + + config TOUCH_IRQ + int "Touch interrupt GPIO number" + range -1 48 + default 38 + + config TOUCH_RST + int "Touch reset GPIO number" + range -1 48 + default -1 + + config TOUCH_CS + int "Touch chip select GPIO number" + range 0 48 + default 41 + endmenu + + menu "SD-Card" + choice + prompt "SD-Card SPI Bus" + default SD_CARD_SPI3_HOST + help + Select the SPI Bus the SD-Card is attached to. + + config SD_CARD_SPI2_HOST + bool "SPI2_HOST" + config SD_CARD_SPI3_HOST + bool "SPI3_HOST" + endchoice + + config SD_CARD_CLOCK + int "SD-Card SPI clock" + default 2000000 + + config SD_CARD_FORMAT_CARD + bool "Format the card if mount failed" + default n + + config SD_CARD_PIN_CS + int "Card select GPIO" + default 4 + + config SD_CARD_PIN_CD + int "Card detection GPIO" + default 17 + endmenu + + menu "LCD" + choice + prompt "Display Bus" + default LCD_SPI3_HOST + help + Select the SPI Bus the Display is attached to. + + config LCD_SPI2_HOST + bool "SPI2_HOST" + config LCD_SPI3_HOST + bool "SPI3_HOST" + endchoice + + config LCD_CLOCK + int "LCD SPI clock" + default 80000000 + + config LCD_CS + int "LCD Chip Select GPIO" + range 0 48 + default 18 + + config LCD_DC + int "DC GPIO" + range 0 48 + default 3 + + config LCD_RST + int "RST GPIO" + range -1 48 + default 8 + + config LCD_BL + int "Backlight GPIO" + range -1 48 + default -1 + endmenu + endmenu + + menu "Task" + config DEVICES_TASK_STACKSIZE + int "Stack size" + default 4096 + + config DEVICES_TASK_PRIO + int "Task prio" + default 16 + + config DEVICES_TASK_CORE + int "Task core" + default 1 + endmenu + endmenu + + menu "GUI" + config GUI_WIDTH + int "Screen width" + default 320 + + config GUI_HEIGHT + int "Screen Height" + default 240 + + config GUI_TOUCH_DEBUG + bool "Enable touch debug visualization" + default n + help + Show touch input visualization overlay with coordinates and crosshair. + Useful for calibrating touch input. + + config GUI_LVGL_TICK_PERIOD_MS + int "LVGL Tick Period" + default 2 + + menu "Task" + config GUI_TASK_STACKSIZE + int "Stack size" + default 8192 + + config GUI_TASK_PRIO + int "Task prio" + default 2 + + config GUI_TASK_CORE + int "Task core" + default 0 + endmenu + endmenu +endmenu \ No newline at end of file diff --git a/main/idf_component.yml b/main/idf_component.yml new file mode 100644 index 0000000..a7247b7 --- /dev/null +++ b/main/idf_component.yml @@ -0,0 +1,15 @@ +dependencies: + espressif/esp_new_jpeg: + version: "^1.0.0" + espressif/bootloader_support_plus: + version: ">=0.1.0" + espressif/esp_lcd_ili9341: + version: "^2.0.1" + espressif/mdns: + version: "^1.9.1" + espressif/esp32-camera: + version: "^2.1.0" + lvgl/lvgl: + version: "^9.4.0" + atanisoft/esp_lcd_touch_xpt2046: + version: "^1.0.6" \ No newline at end of file diff --git a/main/main.cpp b/main/main.cpp new file mode 100644 index 0000000..8903dc6 --- /dev/null +++ b/main/main.cpp @@ -0,0 +1,101 @@ +/* + * main.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Main application entry point. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include + +#include "Application/Tasks/tasks.h" +#include "Application/application.h" +#include "Application/Manager/Time/timeManager.h" +#include "Application/Manager/Devices/devicesManager.h" +#include "Application/Manager/SD/sdManager.h" + +static App_Context_t _App_Context = { + .Lepton_FrameEventQueue = NULL, + .Network_Config = { + .WiFi_Mode = NETWORK_WIFI_MODE_STA, + .Prov_Method = NETWORK_PROV_BLE, + }, + .Server_Config = { + .http_port = 80, + .max_clients = 4, + .ws_ping_interval_sec = 30, + .enable_cors = true, + .api_key = NULL, + }, + .Settings = {0}, +}; + +static const char *TAG = "main"; + +/** @brief Main application entry point. + * Initializes all managers, tasks, and starts the application. + */ +extern "C" void app_main(void) +{ + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + _App_Context.Lepton_FrameEventQueue = xQueueCreate(1, sizeof(App_Lepton_FrameReady_t)); + if (_App_Context.Lepton_FrameEventQueue == NULL) { + ESP_LOGE(TAG, "Failed to create frame queue!"); + return; + } + + ESP_ERROR_CHECK(SettingsManager_Init()); + + ESP_ERROR_CHECK(SettingsManager_Get(&_App_Context.Settings)); + + ESP_LOGI(TAG, "Initializing application tasks..."); + ESP_ERROR_CHECK(DevicesTask_Init()); + + /* Initialize Time Manager (requires RTC from DevicesManager) */ + void *RtcHandle = NULL; + if (DevicesManager_GetRTCHandle(&RtcHandle) == ESP_OK) { + if (TimeManager_Init(RtcHandle) == ESP_OK) { + TimeManager_SetTimezone("CET-1CEST,M3.5.0,M10.5.0/3"); + ESP_LOGI(TAG, "Time Manager initialized with CET timezone"); + } else { + ESP_LOGW(TAG, "Failed to initialize Time Manager"); + } + } else { + ESP_LOGW(TAG, "RTC not available, Time Manager initialization skipped"); + } + + //SDManager_Init(); + + ESP_ERROR_CHECK(GUI_Task_Init()); + ESP_ERROR_CHECK(Lepton_Task_Init()); + ESP_ERROR_CHECK(Network_Task_Init(&_App_Context)); + ESP_LOGI(TAG, " Initialization successful"); + + ESP_LOGI(TAG, "Starting tasks..."); + ESP_ERROR_CHECK(DevicesTask_Start(&_App_Context)); + ESP_ERROR_CHECK(GUI_Task_Start(&_App_Context)); + ESP_ERROR_CHECK(Lepton_Task_Start(&_App_Context)); + ESP_ERROR_CHECK(Network_Task_Start(&_App_Context)); + ESP_LOGI(TAG, " Tasks started"); + + /* Main task can now be deleted - no need to remove from watchdog as it was never added */ + vTaskDelete(NULL); +} \ No newline at end of file diff --git a/partitions.csv b/partitions.csv new file mode 100644 index 0000000..ffa972d --- /dev/null +++ b/partitions.csv @@ -0,0 +1,8 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x4000, +otadata, data, ota, 0xD000, 0x2000, +phy_init, data, phy, 0xF000, 0x1000, +app0, app, ota_0, 0x10000, 0x2F0000, +app1, app, ota_1, 0x300000, 0x2F0000, +settings, data, nvs, 0x5F0000, 0x10000, +nvs_keys, data, nvs_keys, 0x600000, 0x1000, \ No newline at end of file diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..3e1a419 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,62 @@ +[platformio] +src_dir = main +default_envs = debug + +[env] +platform = espressif32 +framework = espidf + +platform_packages = + +extra_scripts = + pre:scripts/clean.py + scripts/format.py + +build_flags = + # Can not be set via Kconfig and the display requires it + -DLV_COLOR_16_SWAP=1 + +lib_deps = + +board = esp32-s3-devkitc-1 +board_build.flash_mode = dio +board_build.psram_type = opi +board_build.extra_flags = -DBOARD_HAS_PSRAM +board_upload.flash_size = 8MB +board_upload.maximum_size = 8388608 +board_build.partitions = partitions.csv +board_build.embed_txtfiles = LICENSE + +debug_tool = esp-builtin +debug_port = /dev/ttyUSB0 + +upload_speed = 921600 +upload_port = ${sysenv.PIO_UPLOAD_PORT, COM22} + +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder +monitor_port = ${sysenv.PIO_UPLOAD_PORT, COM22} + +[env:debug] +build_type = debug +build_flags = + ${env.build_flags} + -D DEBUG + +lib_deps = + ${env.lib_deps} + +extra_scripts = + ${env.extra_scripts} + +[env:release] +build_type = release +build_flags = + ${env.build_flags} + -D NDEBUG + +lib_deps = + ${env.lib_deps} + +extra_scripts = + ${env.extra_scripts} \ No newline at end of file diff --git a/scripts/astyle.cfg b/scripts/astyle.cfg new file mode 100644 index 0000000..57097a5 --- /dev/null +++ b/scripts/astyle.cfg @@ -0,0 +1,33 @@ +# Configuration file for AStyle +# Config same as in ubxlib +# K&R style +--style=kr +# space padding around operators: a = bar((b - c) * a, d--); +--pad-oper +# space padding between a header (e.g. 'if', 'for', 'while'...) and the following bracket +--pad-header +# Pointer sticks to the name: char *pThing +--align-pointer=name +# Reference sticks to the name: char &thing +--align-reference=name +# Nice long max continuation indent, as long as the line length +--max-continuation-indent=100 +# No minimum conditional indent, align everything wherever it occurs +--min-conditional-indent=0 +# All conditions have braces +--add-braces +# Indent the case in switch statements +--indent-switches +# All tabs become [4] spaces +--convert-tabs +# Max line length +--max-code-length=120 +# When breaking lines, leave the logical operator on the end of the line +--break-after-logical +# Ignore unfound excludes +--ignore-exclude-errors + +# Other config used +--suffix=none +--verbose +--errors-to-stdout \ No newline at end of file diff --git a/scripts/clean.py b/scripts/clean.py new file mode 100644 index 0000000..a9d0768 --- /dev/null +++ b/scripts/clean.py @@ -0,0 +1,6 @@ +import os + +from pathlib import Path + +for path in Path("..").rglob("desktop.ini"): + os.remove(path) diff --git a/scripts/format.py b/scripts/format.py new file mode 100644 index 0000000..616673c --- /dev/null +++ b/scripts/format.py @@ -0,0 +1,83 @@ +""" +format.py + +Copyright (C) Daniel Kampert, 2026 +Website: www.kampis-elektroecke.de +File info: AStyle formatting script for PlatformIO. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" + +Import("env") +import os +import subprocess + +from pathlib import Path + +PATTERNS = ["*.c", "*.cpp", "*.h"] + +def run_astyle(source, target, env): + project_dir = env.get("PROJECT_DIR") + astyle_config = os.path.join(project_dir, "scripts/astyle.cfg") + + try: + subprocess.run(["astyle", "--version"], capture_output = True, check = True) + except (FileNotFoundError, subprocess.CalledProcessError): + print("AStyle not found!") + return + + if(not(os.path.exists(astyle_config))): + print("AStyle config not found: {}".format(astyle_config)) + return + + files_to_format = [] + main_dir = Path(project_dir) / "main" + for pattern in PATTERNS: + files_to_format.extend(main_dir.rglob(pattern)) + + if(not(files_to_format)): + print("No C/C++ files found to format") + return + + print("🎨 Formatting {} files with AStyle...".format(len(files_to_format))) + print(" Config: {}".format(astyle_config)) + + cmd = ["astyle", "--options={}".format(astyle_config)] + [str(f) for f in files_to_format] + + try: + result = subprocess.run(cmd, capture_output = True, text = True, check = True) + + if(result.stdout): + print(result.stdout) + + formatted_count = result.stdout.count("Formatted") + unchanged_count = result.stdout.count("Unchanged") + + print("✅ Done!") + print(" Formatted: {}".format(formatted_count)) + print(" Unchanged: {}".format(unchanged_count)) + + except subprocess.CalledProcessError as e: + print("❌ AStyle failed") + + if(e.stdout): + print(e.stdout) + + if(e.stderr): + print(e.stderr) + + raise + +# Register custom target +env.AlwaysBuild(env.Alias("format", None, run_astyle)) \ No newline at end of file diff --git a/sdkconfig.debug b/sdkconfig.debug new file mode 100644 index 0000000..39bdcb7 --- /dev/null +++ b/sdkconfig.debug @@ -0,0 +1,3495 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) 5.5.0 Project Configuration +# +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y +CONFIG_SOC_PCNT_SUPPORTED=y +CONFIG_SOC_PHY_SUPPORTED=y +CONFIG_SOC_WIFI_SUPPORTED=y +CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_GDMA_SUPPORTED=y +CONFIG_SOC_UHCI_SUPPORTED=y +CONFIG_SOC_AHB_GDMA_SUPPORTED=y +CONFIG_SOC_GPTIMER_SUPPORTED=y +CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y +CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y +CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +CONFIG_SOC_ULP_SUPPORTED=y +CONFIG_SOC_ULP_FSM_SUPPORTED=y +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_USB_OTG_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_EFUSE_SUPPORTED=y +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_CLK_TREE_SUPPORTED=y +CONFIG_SOC_MPU_SUPPORTED=y +CONFIG_SOC_WDT_SUPPORTED=y +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +CONFIG_SOC_RNG_SUPPORTED=y +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +CONFIG_SOC_PM_SUPPORTED=y +CONFIG_SOC_SIMD_INSTRUCTION_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=2 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +CONFIG_SOC_ADC_SHARED_POWER=y +CONFIG_SOC_APB_BACKUP_DMA=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED=y +CONFIG_SOC_CACHE_FREEZE_SUPPORTED=y +CONFIG_SOC_CACHE_ACS_INVALID_STATE_ON_PANIC=y +CONFIG_SOC_CPU_CORES_NUM=2 +CONFIG_SOC_CPU_INTR_NUM=32 +CONFIG_SOC_CPU_HAS_FPU=y +CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_AHB_GDMA_VERSION=1 +CONFIG_SOC_GDMA_NUM_GROUPS_MAX=1 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP=5 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX=5 +CONFIG_SOC_AHB_GDMA_SUPPORT_PSRAM=y +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=49 +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB=y +CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +CONFIG_SOC_GPIO_IN_RANGE_MAX=48 +CONFIG_SOC_GPIO_OUT_RANGE_MAX=48 +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000 +CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y +CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y +CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y +CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_HP_I2C_NUM=2 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_CMD_REG_NUM=8 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS=y +CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE=y +CONFIG_SOC_I2S_NUM=2 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_XTAL=y +CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y +CONFIG_SOC_I2S_SUPPORTS_PCM=y +CONFIG_SOC_I2S_SUPPORTS_PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_SUPPORTS_PCM2PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +CONFIG_SOC_I2S_SUPPORTS_PDM2PCM=y +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2 +CONFIG_SOC_I2S_PDM_MAX_RX_LINES=4 +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_TIMER_NUM=4 +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MCPWM_GROUPS=2 +CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 +CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 +CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 +CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y +CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 +CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3 +CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +CONFIG_SOC_MMU_PERIPH_NUM=1 +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +CONFIG_SOC_PCNT_GROUPS=1 +CONFIG_SOC_PCNT_UNITS_PER_GROUP=4 +CONFIG_SOC_PCNT_CHANNELS_PER_UNIT=2 +CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT=2 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8 +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y +CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_DMA=y +CONFIG_SOC_LCD_I80_SUPPORTED=y +CONFIG_SOC_LCD_RGB_SUPPORTED=y +CONFIG_SOC_LCD_I80_BUSES=1 +CONFIG_SOC_LCD_RGB_PANELS=1 +CONFIG_SOC_LCD_I80_BUS_WIDTH=16 +CONFIG_SOC_LCD_RGB_DATA_WIDTH=16 +CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_I80_NUM_BUSES=1 +CONFIG_SOC_LCDCAM_I80_BUS_WIDTH=16 +CONFIG_SOC_LCDCAM_RGB_NUM_PANELS=1 +CONFIG_SOC_LCDCAM_RGB_DATA_WIDTH=16 +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTCIO_PIN_COUNT=22 +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y +CONFIG_SOC_SDM_GROUPS=1 +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y +CONFIG_SOC_SPI_PERIPH_NUM=3 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y +CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_SUPPORT_OCT=y +CONFIG_SOC_SPI_SCT_SUPPORTED=y +CONFIG_SOC_SPI_SCT_REG_NUM=14 +CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y +CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA +CONFIG_SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SPIRAM_SUPPORTED=y +CONFIG_SOC_SPIRAM_XIP_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 +CONFIG_SOC_TOUCH_SENSOR_VERSION=2 +CONFIG_SOC_TOUCH_SENSOR_NUM=15 +CONFIG_SOC_TOUCH_MIN_CHAN_ID=1 +CONFIG_SOC_TOUCH_MAX_CHAN_ID=14 +CONFIG_SOC_TOUCH_SUPPORT_BENCHMARK=y +CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y +CONFIG_SOC_TOUCH_SUPPORT_WATERPROOF=y +CONFIG_SOC_TOUCH_SUPPORT_PROX_SENSING=y +CONFIG_SOC_TOUCH_SUPPORT_DENOISE_CHAN=y +CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3 +CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y +CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 +CONFIG_SOC_TWAI_MASK_FILTER_NUM=1 +CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y +CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_BRP_MAX=16384 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_HP_NUM=3 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +CONFIG_SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE=y +CONFIG_SOC_UHCI_NUM=1 +CONFIG_SOC_USB_OTG_PERIPH_NUM=1 +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +CONFIG_SOC_SHA_SUPPORT_DMA=y +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SHA_SUPPORT_SHA384=y +CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +CONFIG_SOC_MPI_OPERATIONS_NUM=3 +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y +CONFIG_SOC_CLK_LP_FAST_SUPPORT_XTAL_D2=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_DCACHE=y +CONFIG_SOC_EFUSE_HARD_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +CONFIG_SOC_EFUSE_DIS_ICACHE=y +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE=y +CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY=y +CONFIG_SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM=y +CONFIG_SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_EXTERNAL_COEX_LEADER_TX_LINE=y +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +CONFIG_SOC_SDMMC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_SDMMC_DELAY_PHASE_NUM=4 +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_BLE_50_SUPPORTED=y +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_ULP_HAS_ADC=y +CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TOOLCHAIN="gcc" +CONFIG_IDF_TOOLCHAIN_GCC=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET_ARCH="xtensa" +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_INIT_VERSION="5.4.1" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# Bootloader config +# + +# +# Bootloader manager +# +CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y +CONFIG_BOOTLOADER_PROJECT_VER=1 +# end of Bootloader manager + +# +# Application Rollback +# +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# end of Application Rollback + +# +# Bootloader Rollback +# +# end of Bootloader Rollback + +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set + +# +# Log +# +CONFIG_BOOTLOADER_LOG_VERSION_1=y +CONFIG_BOOTLOADER_LOG_VERSION=1 +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 + +# +# Format +# +# CONFIG_BOOTLOADER_LOG_COLORS is not set +CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y +# end of Format + +# +# Settings +# +CONFIG_BOOTLOADER_LOG_MODE_TEXT_EN=y +CONFIG_BOOTLOADER_LOG_MODE_TEXT=y +# end of Settings +# end of Log + +# +# Serial Flash Configurations +# +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations + +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 +# end of Application manager + +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_USB_OTG_NUM=3 +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +CONFIG_ESP_ROM_HAS_HAL_WDT=y +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y +CONFIG_ESP_ROM_HAS_SPI_FLASH=y +CONFIG_ESP_ROM_HAS_SPI_FLASH_MMAP=y +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y +CONFIG_ESP_ROM_HAS_NEWLIB=y +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG=y +CONFIG_ESP_ROM_HAS_SW_FLOAT=y +CONFIG_ESP_ROM_HAS_VERSION=y +CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y +CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC=y +CONFIG_ESP_ROM_CONSOLE_OUTPUT_SECONDARY=y + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# PyroVision +# + +# +# Network +# + +# +# Task +# +CONFIG_NETWORK_TASK_STACKSIZE=8192 +CONFIG_NETWORK_TASK_PRIO=16 +CONFIG_NETWORK_TASK_CORE=1 +# end of Task + +# +# VISA +# +CONFIG_NETWORK_VISA_DEVICE_MANUFACTURER="PyroVision" +CONFIG_NETWORK_VISA_DEVICE_MODEL="PyroVision" +CONFIG_NETWORK_VISA_DEVICE_SERIAL="0000001" +# end of VISA +# end of Network + +# +# Lepton +# + +# +# Task +# +CONFIG_LEPTON_TASK_STACKSIZE=4096 +CONFIG_LEPTON_TASK_PRIO=16 +CONFIG_LEPTON_TASK_CORE=1 +# end of Task +# end of Lepton + +# +# Devices +# + +# +# I2C +# +CONFIG_DEVICES_I2C_HOST=1 +CONFIG_DEVICES_I2C_SCL=21 +CONFIG_DEVICES_I2C_SDA=47 +# end of I2C + +# +# SPI +# +CONFIG_SPI_SCLK=46 +CONFIG_SPI_MOSI=48 +CONFIG_SPI_MISO=9 +CONFIG_SPI_TRANSFER_SIZE=4096 + +# +# Touch +# +# CONFIG_TOUCH_SPI2_HOST is not set +CONFIG_TOUCH_SPI3_HOST=y +CONFIG_TOUCH_CLOCK=2000000 +CONFIG_TOUCH_IRQ=38 +CONFIG_TOUCH_RST=-1 +CONFIG_TOUCH_CS=41 +# end of Touch + +# +# SD-Card +# +# CONFIG_SD_CARD_SPI2_HOST is not set +CONFIG_SD_CARD_SPI3_HOST=y +CONFIG_SD_CARD_CLOCK=2000000 +CONFIG_SD_CARD_FORMAT_CARD=y +CONFIG_SD_CARD_PIN_CS=4 +CONFIG_SD_CARD_PIN_CD=-1 +# end of SD-Card + +# +# LCD +# +# CONFIG_LCD_SPI2_HOST is not set +CONFIG_LCD_SPI3_HOST=y +CONFIG_LCD_CLOCK=80000000 +CONFIG_LCD_CS=18 +CONFIG_LCD_DC=3 +CONFIG_LCD_RST=8 +CONFIG_LCD_BL=-1 +# end of LCD +# end of SPI + +# +# Task +# +CONFIG_DEVICES_TASK_STACKSIZE=4096 +CONFIG_DEVICES_TASK_PRIO=16 +CONFIG_DEVICES_TASK_CORE=1 +# end of Task +# end of Devices + +# +# GUI +# +CONFIG_GUI_WIDTH=320 +CONFIG_GUI_HEIGHT=240 +# CONFIG_GUI_TOUCH_DEBUG is not set +CONFIG_GUI_LVGL_TICK_PERIOD_MS=2 + +# +# Task +# +CONFIG_GUI_TASK_STACKSIZE=8192 +CONFIG_GUI_TASK_PRIO=2 +CONFIG_GUI_TASK_CORE=0 +# end of Task +# end of GUI +# end of PyroVision + +# +# XPT2046 +# +CONFIG_XPT2046_Z_THRESHOLD=400 +# CONFIG_XPT2046_INTERRUPT_MODE is not set +# CONFIG_XPT2046_VREF_ON_MODE is not set +CONFIG_XPT2046_CONVERT_ADC_TO_COORDS=y +# CONFIG_XPT2046_ENABLE_LOCKING is not set +# end of XPT2046 + +# +# Bootloader config (Custom) +# +# CONFIG_BOOTLOADER_COMPRESSED_ENABLED is not set +# CONFIG_BOOTLOADER_CUSTOM_DEBUG_ON is not set +# CONFIG_SKIP_VALIDATE_CUSTOM_COMPRESSED_HEADER is not set +# CONFIG_SKIP_VALIDATE_CUSTOM_COMPRESSED_DATA is not set +# end of Bootloader config (Custom) + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE=y +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS=y +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +CONFIG_COMPILER_RT_LIB_GCCLIB=y +CONFIG_COMPILER_RT_LIB_NAME="gcc" +CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y +# CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE is not set +# CONFIG_COMPILER_STATIC_ANALYZER is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +# CONFIG_APPTRACE_DEST_UART1 is not set +# CONFIG_APPTRACE_DEST_UART2 is not set +# CONFIG_APPTRACE_DEST_USB_CDC is not set +CONFIG_APPTRACE_DEST_UART_NONE=y +CONFIG_APPTRACE_UART_TASK_PRIO=1 +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLUEDROID_ENABLED is not set +CONFIG_BT_NIMBLE_ENABLED=y +# CONFIG_BT_CONTROLLER_ONLY is not set +CONFIG_BT_CONTROLLER_ENABLED=y +# CONFIG_BT_CONTROLLER_DISABLED is not set + +# +# NimBLE Options +# +# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL is not set +# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL is not set +CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT=y +# CONFIG_BT_NIMBLE_LOG_LEVEL_NONE is not set +# CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR is not set +# CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING is not set +CONFIG_BT_NIMBLE_LOG_LEVEL_INFO=y +# CONFIG_BT_NIMBLE_LOG_LEVEL_DEBUG is not set +CONFIG_BT_NIMBLE_LOG_LEVEL=1 +CONFIG_BT_NIMBLE_MAX_CONNECTIONS=3 +CONFIG_BT_NIMBLE_MAX_BONDS=3 +CONFIG_BT_NIMBLE_MAX_CCCDS=8 +CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=0 +CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=y +# CONFIG_BT_NIMBLE_PINNED_TO_CORE_1 is not set +CONFIG_BT_NIMBLE_PINNED_TO_CORE=0 +CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=4096 +CONFIG_BT_NIMBLE_ROLE_CENTRAL=y +CONFIG_BT_NIMBLE_ROLE_PERIPHERAL=y +CONFIG_BT_NIMBLE_ROLE_BROADCASTER=y +CONFIG_BT_NIMBLE_ROLE_OBSERVER=y +CONFIG_BT_NIMBLE_GATT_CLIENT=y +CONFIG_BT_NIMBLE_GATT_SERVER=y +CONFIG_BT_NIMBLE_NVS_PERSIST=y +# CONFIG_BT_NIMBLE_SMP_ID_RESET is not set +CONFIG_BT_NIMBLE_SECURITY_ENABLE=y +CONFIG_BT_NIMBLE_SM_LEGACY=y +CONFIG_BT_NIMBLE_SM_SC=y +# CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS is not set +CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION=y +CONFIG_BT_NIMBLE_SM_LVL=0 +CONFIG_BT_NIMBLE_SM_SC_ONLY=0 +CONFIG_BT_NIMBLE_PRINT_ERR_NAME=y +# CONFIG_BT_NIMBLE_DEBUG is not set +# CONFIG_BT_NIMBLE_DYNAMIC_SERVICE is not set +CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="nimble" +CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31 +CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=256 +CONFIG_BT_NIMBLE_ATT_MAX_PREP_ENTRIES=64 +CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE=0 + +# +# Memory Settings +# +CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=12 +CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE=256 +CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT=24 +CONFIG_BT_NIMBLE_MSYS_2_BLOCK_SIZE=320 +CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=24 +CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE=255 +CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=70 +CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT=30 +CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT=8 +CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT=1 +# end of Memory Settings + +CONFIG_BT_NIMBLE_GATT_MAX_PROCS=4 +# CONFIG_BT_NIMBLE_HS_FLOW_CTRL is not set +CONFIG_BT_NIMBLE_RPA_TIMEOUT=900 +# CONFIG_BT_NIMBLE_MESH is not set +CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS=y +CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS=2000 +CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=y +CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT=3 +# CONFIG_BT_NIMBLE_HANDLE_REPEAT_PAIRING_DELETION is not set +CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=y +CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY=y +CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY=y +# CONFIG_BT_NIMBLE_EXT_ADV is not set +CONFIG_BT_NIMBLE_EXT_SCAN=y +CONFIG_BT_NIMBLE_ENABLE_PERIODIC_SYNC=y +CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS=0 +# CONFIG_BT_NIMBLE_GATT_CACHING is not set +# CONFIG_BT_NIMBLE_INCL_SVC_DISCOVERY is not set +CONFIG_BT_NIMBLE_WHITELIST_SIZE=12 +# CONFIG_BT_NIMBLE_TEST_THROUGHPUT_TEST is not set +CONFIG_BT_NIMBLE_BLUFI_ENABLE=y +CONFIG_BT_NIMBLE_USE_ESP_TIMER=y +CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE=y +# CONFIG_BT_NIMBLE_BLE_GATT_BLOB_TRANSFER is not set + +# +# BLE Services +# +CONFIG_BT_NIMBLE_PROX_SERVICE=y +CONFIG_BT_NIMBLE_ANS_SERVICE=y +CONFIG_BT_NIMBLE_CTS_SERVICE=y +CONFIG_BT_NIMBLE_HTP_SERVICE=y +CONFIG_BT_NIMBLE_IPSS_SERVICE=y +CONFIG_BT_NIMBLE_TPS_SERVICE=y +CONFIG_BT_NIMBLE_IAS_SERVICE=y +CONFIG_BT_NIMBLE_LLS_SERVICE=y +CONFIG_BT_NIMBLE_SPS_SERVICE=y +CONFIG_BT_NIMBLE_HR_SERVICE=y +# CONFIG_BT_NIMBLE_HID_SERVICE is not set +CONFIG_BT_NIMBLE_BAS_SERVICE=y +# CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY is not set +CONFIG_BT_NIMBLE_DIS_SERVICE=y +# CONFIG_BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME is not set +# CONFIG_BT_NIMBLE_SVC_DIS_SERIAL_NUMBER is not set +# CONFIG_BT_NIMBLE_SVC_DIS_HARDWARE_REVISION is not set +# CONFIG_BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION is not set +# CONFIG_BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION is not set +# CONFIG_BT_NIMBLE_SVC_DIS_SYSTEM_ID is not set +# CONFIG_BT_NIMBLE_SVC_DIS_PNP_ID is not set +# CONFIG_BT_NIMBLE_SVC_DIS_INCLUDED is not set +CONFIG_BT_NIMBLE_GAP_SERVICE=y + +# +# GAP Appearance write permissions +# +# CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE is not set +CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM=0 +CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC=0 +CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN=0 +CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR=0 +# end of GAP Appearance write permissions + +CONFIG_BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP=y +# CONFIG_BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP is not set +# CONFIG_BT_NIMBLE_SVC_GAP_CAR_SUPP is not set +CONFIG_BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION=-1 + +# +# GAP device name write permissions +# +# CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE is not set +# end of GAP device name write permissions + +# +# PPCP settings +# +CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL=0 +CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL=0 +CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY=0 +CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO=0 +# end of PPCP settings + +CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM=0 +CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC=0 +CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN=0 +CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR=0 +# CONFIG_BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL is not set +# CONFIG_BT_NIMBLE_SVC_GAP_RPA_ONLY is not set +# end of BLE Services + +# CONFIG_BT_NIMBLE_VS_SUPPORT is not set +# CONFIG_BT_NIMBLE_ENC_ADV_DATA is not set +# CONFIG_BT_NIMBLE_HIGH_DUTY_ADV_ITVL is not set +# CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN is not set +# CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK is not set +# CONFIG_BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT is not set + +# +# Host-controller Transport +# +CONFIG_UART_HW_FLOWCTRL_DISABLE=y +# CONFIG_UART_HW_FLOWCTRL_CTS_RTS is not set +CONFIG_BT_NIMBLE_HCI_UART_FLOW_CTRL=0 +CONFIG_BT_NIMBLE_HCI_UART_RTS_PIN=19 +CONFIG_BT_NIMBLE_HCI_UART_CTS_PIN=23 +# end of Host-controller Transport + +CONFIG_BT_NIMBLE_EATT_CHAN_NUM=0 +# CONFIG_BT_NIMBLE_SUBRATE is not set +# end of NimBLE Options + +# +# Controller Options +# +CONFIG_BT_CTRL_MODE_EFF=1 +CONFIG_BT_CTRL_BLE_MAX_ACT=6 +CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=6 +CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 +CONFIG_BT_CTRL_PINNED_TO_CORE_0=y +# CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set +CONFIG_BT_CTRL_PINNED_TO_CORE=0 +CONFIG_BT_CTRL_HCI_MODE_VHCI=y +# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set +CONFIG_BT_CTRL_HCI_TL=1 +CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30 +CONFIG_BT_BLE_CCA_MODE_NONE=y +# CONFIG_BT_BLE_CCA_MODE_HW is not set +# CONFIG_BT_BLE_CCA_MODE_SW is not set +CONFIG_BT_BLE_CCA_MODE=0 +CONFIG_BT_CTRL_HW_CCA_VAL=20 +CONFIG_BT_CTRL_HW_CCA_EFF=0 +CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y +# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set +# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set +CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0 +CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y +# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set +CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0 +CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y +# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set +CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0 +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9=y +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P20 is not set +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=11 +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 +CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 +CONFIG_BT_CTRL_BLE_SCAN_DUPL=y +CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE=y +# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA is not set +# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE is not set +CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0 +CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100 +CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD=0 +# CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN is not set +# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0 + +# +# MODEM SLEEP Options +# +# CONFIG_BT_CTRL_MODEM_SLEEP is not set +# end of MODEM SLEEP Options + +CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 +CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 +CONFIG_BT_CTRL_HCI_TL_EFF=1 +# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set +# CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set +# CONFIG_BT_BLE_ADV_DATA_LENGTH_ZERO_AUX is not set +CONFIG_BT_CTRL_CHAN_ASS_EN=y +CONFIG_BT_CTRL_LE_PING_EN=y + +# +# BLE disconnects when Instant Passed (0x28) occurs +# +# CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE is not set +# CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE is not set +# CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE is not set +# end of BLE disconnects when Instant Passed (0x28) occurs + +# CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY is not set +CONFIG_BT_CTRL_DTM_ENABLE=y +CONFIG_BT_CTRL_BLE_MASTER=y +# CONFIG_BT_CTRL_BLE_TEST is not set +CONFIG_BT_CTRL_BLE_SCAN=y +CONFIG_BT_CTRL_BLE_SECURITY_ENABLE=y +CONFIG_BT_CTRL_BLE_ADV=y +# CONFIG_BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS is not set + +# +# Controller debug log Options (Experimental) +# +# end of Controller debug log Options (Experimental) +# end of Controller Options + +# +# Common Options +# +CONFIG_BT_ALARM_MAX_NUM=50 +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# end of Common Options + +# CONFIG_BT_HCI_LOG_DEBUG_EN is not set +# end of Bluetooth + +# CONFIG_BLE_MESH is not set + +# +# Console Library +# +# CONFIG_CONSOLE_SORTED_HELP is not set +# end of Console Library + +# +# Driver Configurations +# + +# +# Legacy TWAI Driver Configurations +# +# CONFIG_TWAI_SKIP_LEGACY_CONFLICT_CHECK is not set +CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y +# end of Legacy TWAI Driver Configurations + +# +# Legacy ADC Driver Configuration +# +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set + +# +# Legacy ADC Calibration Configuration +# +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Driver Configuration + +# +# Legacy MCPWM Driver Configurations +# +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy MCPWM Driver Configurations + +# +# Legacy Timer Group Driver Configurations +# +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Timer Group Driver Configurations + +# +# Legacy RMT Driver Configurations +# +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy RMT Driver Configurations + +# +# Legacy I2S Driver Configurations +# +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2S Driver Configurations + +# +# Legacy I2C Driver Configurations +# +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations + +# +# Legacy PCNT Driver Configurations +# +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy PCNT Driver Configurations + +# +# Legacy SDM Driver Configurations +# +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy SDM Driver Configurations + +# +# Legacy Temperature Sensor Driver Configurations +# +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Temperature Sensor Driver Configurations + +# +# Legacy Touch Sensor Driver Configurations +# +# CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TOUCH_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Touch Sensor Driver Configurations +# end of Driver Configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set +# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ADC and ADC Calibration +# +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# CONFIG_ADC_ENABLE_DEBUG_LOG is not set +# end of ADC and ADC Calibration + +# +# Wireless Coexistence +# +CONFIG_ESP_COEX_ENABLED=y +CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y +# CONFIG_ESP_COEX_POWER_MANAGEMENT is not set +# CONFIG_ESP_COEX_GPIO_DEBUG is not set +# end of Wireless Coexistence + +# +# Common ESP-related +# +# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set +# end of Common ESP-related + +# +# ESP-Driver:GPIO Configurations +# +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations + +# +# ESP-Driver:GPTimer Configurations +# +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_CACHE_SAFE is not set +CONFIG_GPTIMER_OBJ_CACHE_SAFE=y +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations + +# +# ESP-Driver:I2C Configurations +# +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 is not set +CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM=y +# end of ESP-Driver:I2C Configurations + +# +# ESP-Driver:I2S Configurations +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations + +# +# ESP-Driver:LEDC Configurations +# +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations + +# +# ESP-Driver:MCPWM Configurations +# +CONFIG_MCPWM_ISR_HANDLER_IN_IRAM=y +# CONFIG_MCPWM_ISR_CACHE_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +CONFIG_MCPWM_OBJ_CACHE_SAFE=y +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:MCPWM Configurations + +# +# ESP-Driver:PCNT Configurations +# +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:PCNT Configurations + +# +# ESP-Driver:RMT Configurations +# +CONFIG_RMT_ENCODER_FUNC_IN_IRAM=y +CONFIG_RMT_TX_ISR_HANDLER_IN_IRAM=y +CONFIG_RMT_RX_ISR_HANDLER_IN_IRAM=y +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# CONFIG_RMT_TX_ISR_CACHE_SAFE is not set +# CONFIG_RMT_RX_ISR_CACHE_SAFE is not set +CONFIG_RMT_OBJ_CACHE_SAFE=y +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# end of ESP-Driver:RMT Configurations + +# +# ESP-Driver:Sigma Delta Modulator Configurations +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations + +# +# ESP-Driver:SPI Configurations +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations + +# +# ESP-Driver:Touch Sensor Configurations +# +# CONFIG_TOUCH_CTRL_FUNC_IN_IRAM is not set +# CONFIG_TOUCH_ISR_IRAM_SAFE is not set +# CONFIG_TOUCH_ENABLE_DEBUG_LOG is not set +# CONFIG_TOUCH_SKIP_FSM_CHECK is not set +# end of ESP-Driver:Touch Sensor Configurations + +# +# ESP-Driver:Temperature Sensor Configurations +# +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Temperature Sensor Configurations + +# +# ESP-Driver:TWAI Configurations +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# CONFIG_TWAI_ISR_CACHE_SAFE is not set +# CONFIG_TWAI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:TWAI Configurations + +# +# ESP-Driver:UART Configurations +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of ESP-Driver:UART Configurations + +# +# ESP-Driver:UHCI Configurations +# +# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set +# CONFIG_UHCI_ISR_CACHE_SAFE is not set +# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:UHCI Configurations + +# +# ESP-Driver:USB Serial/JTAG Configuration +# +CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y +# end of ESP-Driver:USB Serial/JTAG Configuration + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# CONFIG_ETH_TRANSMIT_MUTEX is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +CONFIG_ESP_GDBSTUB_ENABLED=y +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 +# end of GDB Stub + +# +# ESP HID +# +CONFIG_ESPHID_TASK_SIZE_BT=2048 +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set +CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +CONFIG_HTTPD_WS_SUPPORT=y +# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000 +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set +# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set +CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT=2000 +# CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# Chip revision +# +CONFIG_ESP32S3_REV_MIN_0=y +# CONFIG_ESP32S3_REV_MIN_1 is not set +# CONFIG_ESP32S3_REV_MIN_2 is not set +CONFIG_ESP32S3_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 + +# +# Maximum Supported ESP32-S3 Revision (Rev v0.99) +# +CONFIG_ESP32S3_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199 + +# +# Maximum Supported ESP32-S3 eFuse Block Revision (eFuse Block Rev v1.99) +# +# end of Chip revision + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# CONFIG_ESP_SLEEP_DEBUG is not set +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# end of RTC Clock Config + +# +# Peripheral Control +# +CONFIG_ESP_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control + +# +# GDMA Configurations +# +CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y +CONFIG_GDMA_ISR_HANDLER_IN_IRAM=y +CONFIG_GDMA_OBJ_DRAM_SAFE=y +# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configurations + +# +# Main XTAL Config +# +CONFIG_XTAL_FREQ_40=y +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config + +# +# Power Supplier +# + +# +# Brownout Detector +# +CONFIG_ESP_BROWNOUT_DET=y +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP_BROWNOUT_DET_LVL=7 +CONFIG_ESP_BROWNOUT_USE_INTR=y +# end of Brownout Detector +# end of Power Supplier + +CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y +CONFIG_ESP_INTR_IN_IRAM=y +# end of Hardware Settings + +# +# ESP-Driver:LCD Controller Configurations +# +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set +# end of ESP-Driver:LCD Controller Configurations + +# +# ESP-MM: Memory Management Configurations +# +# CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS is not set +# end of ESP-MM: Memory Management Configurations + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y +# CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set +# CONFIG_ESP_NETIF_L2_TAP is not set +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set +# end of ESP NETIF Adapter + +# +# Partition API Configuration +# +# end of Partition API Configuration + +# +# PHY +# +CONFIG_ESP_PHY_ENABLED=y +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +CONFIG_ESP_PHY_ENABLE_USB=y +# CONFIG_ESP_PHY_ENABLE_CERT_TEST is not set +CONFIG_ESP_PHY_RF_CAL_PARTIAL=y +# CONFIG_ESP_PHY_RF_CAL_NONE is not set +# CONFIG_ESP_PHY_RF_CAL_FULL is not set +CONFIG_ESP_PHY_CALIBRATION_MODE=0 +# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set +# CONFIG_ESP_PHY_RECORD_USED_TIME is not set +CONFIG_ESP_PHY_IRAM_OPT=y +# end of PHY + +# +# Power Management +# +CONFIG_PM_SLEEP_FUNC_IN_IRAM=y +# CONFIG_PM_ENABLE is not set +CONFIG_PM_SLP_IRAM_OPT=y +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP PSRAM +# +CONFIG_SPIRAM=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_MODE_QUAD is not set +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM_SPEED=80 +# CONFIG_SPIRAM_ECC_ENABLE is not set +CONFIG_SPIRAM_BOOT_HW_INIT=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y +# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set +# CONFIG_SPIRAM_USE_MEMMAP is not set +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 +# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set +# end of SPI RAM config +# end of ESP PSRAM + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP-ROM +# +CONFIG_ESP_ROM_PRINT_IN_IRAM=y +# end of ESP-ROM + +# +# ESP Security Specific +# +# end of ESP Security Specific + +# +# ESP System Settings +# +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config + +# +# Memory +# +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory + +# +# Trace memory +# +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# end of Trace memory + +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y +# end of ESP System Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1280 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# ESP Timer (High Resolution Timer) +# +CONFIG_ESP_TIMER_IN_IRAM=y +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of ESP Timer (High Resolution Timer) + +# +# Wi-Fi +# +CONFIG_ESP_WIFI_ENABLED=y +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y +# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 +CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5 +# CONFIG_ESP_WIFI_CSI_ENABLED is not set +CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP_WIFI_TX_BA_WIN=6 +CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP_WIFI_RX_BA_WIN=6 +CONFIG_ESP_WIFI_NVS_ENABLED=y +CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP_WIFI_IRAM_OPT=y +# CONFIG_ESP_WIFI_EXTRA_IRAM_OPT is not set +CONFIG_ESP_WIFI_RX_IRAM_OPT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP_WIFI_ENABLE_SAE_PK=y +CONFIG_ESP_WIFI_ENABLE_SAE_H2E=y +CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +# CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +CONFIG_ESP_WIFI_GMAC_SUPPORT=y +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y +CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y +# CONFIG_ESP_WIFI_WAPI_PSK is not set +# CONFIG_ESP_WIFI_SUITE_B_192 is not set +# CONFIG_ESP_WIFI_11KV_SUPPORT is not set +# CONFIG_ESP_WIFI_MBO_SUPPORT is not set +# CONFIG_ESP_WIFI_DPP_SUPPORT is not set +# CONFIG_ESP_WIFI_11R_SUPPORT is not set +# CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR is not set + +# +# WPS Configuration Options +# +# CONFIG_ESP_WIFI_WPS_STRICT is not set +# CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# end of WPS Configuration Options + +# CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set +CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y +# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +CONFIG_FATFS_VOLUME_COUNT=2 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +# CONFIG_FATFS_SECTOR_512 is not set +CONFIG_FATFS_SECTOR_4096=y +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y +# CONFIG_FATFS_USE_FASTSEEK is not set +CONFIG_FATFS_USE_STRFUNC_NONE=y +# CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV is not set +# CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV is not set +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# CONFIG_FATFS_IMMEDIATE_FSYNC is not set +# CONFIG_FATFS_USE_LABEL is not set +CONFIG_FATFS_LINK_LOCK=y +# CONFIG_FATFS_USE_DYN_BUFFERS is not set + +# +# File system free space calculation behavior +# +CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 +CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 +# end of File system free space calculation behavior +# end of FAT Filesystem support + +# +# FreeRTOS +# + +# +# Kernel +# +# CONFIG_FREERTOS_SMP is not set +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_HZ=100 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_USE_TIMERS=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set +# end of Kernel + +# +# Port +# +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# end of Port + +# +# Extra +# +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y +# end of Extra + +CONFIG_FREERTOS_PORT=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y +CONFIG_FREERTOS_NUMBER_OF_CORES=2 +CONFIG_FREERTOS_IN_IRAM=y +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_WDT_USE_ROM_IMPL=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_TASK_TRACKING is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging + +# +# Log +# +CONFIG_LOG_VERSION_1=y +# CONFIG_LOG_VERSION_2 is not set +CONFIG_LOG_VERSION=1 + +# +# Log Level +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 + +# +# Level Settings +# +# CONFIG_LOG_MASTER_LEVEL is not set +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level + +# +# Format +# +# CONFIG_LOG_COLORS is not set +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Format + +# +# Settings +# +CONFIG_LOG_MODE_TEXT_EN=y +CONFIG_LOG_MODE_TEXT=y +# end of Settings + +CONFIG_LOG_IN_IRAM=y +# end of Log + +# +# LWIP +# +CONFIG_LWIP_ENABLE=y +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_ND6=y +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_DEFAULT_TTL=64 +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_ESP_MLDV6_REPORT=y +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +CONFIG_LWIP_DHCPS_ADD_DNS=y +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV4=y +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 +CONFIG_LWIP_TCP_WND_DEFAULT=5760 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 +CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 +CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# CONFIG_LWIP_PPP_SUPPORT is not set +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 +# end of SNTP + +# +# DNS +# +CONFIG_LWIP_DNS_MAX_HOST_IP=1 +CONFIG_LWIP_DNS_MAX_SERVERS=3 +# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set +# CONFIG_LWIP_USE_ESP_GETADDRINFO is not set +# end of DNS + +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set +CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_NONE=y +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_DEFAULT is not set +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v3.x related +# +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +CONFIG_MBEDTLS_PKCS7_C=y +# end of mbedTLS v3.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA1_C=y +CONFIG_MBEDTLS_SHA512_C=y +# CONFIG_MBEDTLS_SHA3_C is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +CONFIG_MBEDTLS_ERROR_STRINGS=y +CONFIG_MBEDTLS_FS_IO=y +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set +# end of mbedTLS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +# CONFIG_MQTT_PROTOCOL_5 is not set +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# LibC +# +CONFIG_LIBC_NEWLIB=y +CONFIG_LIBC_MISC_IN_IRAM=y +CONFIG_LIBC_LOCKS_PLACE_IN_IRAM=y +CONFIG_LIBC_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_LIBC_STDOUT_LINE_ENDING_LF is not set +# CONFIG_LIBC_STDOUT_LINE_ENDING_CR is not set +# CONFIG_LIBC_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_LIBC_STDIN_LINE_ENDING_LF is not set +CONFIG_LIBC_STDIN_LINE_ENDING_CR=y +# CONFIG_LIBC_NEWLIB_NANO_FORMAT is not set +CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y +# CONFIG_LIBC_TIME_SYSCALL_USE_RTC is not set +# CONFIG_LIBC_TIME_SYSCALL_USE_HRT is not set +# CONFIG_LIBC_TIME_SYSCALL_USE_NONE is not set +# end of LibC + +CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y + +# +# NVS +# +# CONFIG_NVS_ENCRYPTION is not set +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set +# CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM is not set +# end of NVS + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set + +# +# OpenThread Spinel +# +# CONFIG_OPENTHREAD_SPINEL_ONLY is not set +# end of OpenThread Spinel +# end of OpenThread + +# +# Protocomm +# +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y +# end of Protocomm + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# MMU Config +# +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# Main Flash configuration +# + +# +# SPI Flash behavior when brownout +# +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Optional and Experimental Features (READ DOCS FIRST) +# + +# +# Features here require specific hardware (READ DOCS FIRST!) +# +# CONFIG_SPI_FLASH_HPM_ENA is not set +CONFIG_SPI_FLASH_HPM_AUTO=y +# CONFIG_SPI_FLASH_HPM_DIS is not set +CONFIG_SPI_FLASH_HPM_ON=y +CONFIG_SPI_FLASH_HPM_DC_AUTO=y +# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 +# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set +CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM=y +# end of Optional and Experimental Features (READ DOCS FIRST) +# end of Main Flash configuration + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED=y +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# CONFIG_WS_DYNAMIC_BUFFER is not set +# end of Websocket +# end of TCP Transport + +# +# Ultra Low Power (ULP) Co-processor +# +CONFIG_ULP_COPROC_ENABLED=y +# CONFIG_ULP_COPROC_TYPE_FSM is not set +CONFIG_ULP_COPROC_TYPE_RISCV=y +CONFIG_ULP_COPROC_RESERVE_MEM=4096 + +# +# ULP RISC-V Settings +# +# CONFIG_ULP_RISCV_INTERRUPT_ENABLE is not set +CONFIG_ULP_RISCV_UART_BAUDRATE=9600 +CONFIG_ULP_RISCV_I2C_RW_TIMEOUT=500 +# end of ULP RISC-V Settings + +# +# ULP Debugging Options +# +# end of ULP Debugging Options +# end of Ultra Low Power (ULP) Co-processor + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# CONFIG_UNITY_TEST_ORDER_BY_FILE_PATH_AND_LINE is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set + +# +# Hub Driver Configuration +# + +# +# Root Port configuration +# +CONFIG_USB_HOST_DEBOUNCE_DELAY_MS=250 +CONFIG_USB_HOST_RESET_HOLD_MS=30 +CONFIG_USB_HOST_RESET_RECOVERY_MS=30 +CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS=10 +# end of Root Port configuration + +# CONFIG_USB_HOST_HUBS_SUPPORTED is not set +# end of Hub Driver Configuration + +# CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK is not set +CONFIG_USB_OTG_SUPPORTED=y +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SELECT_IN_RAM is not set +CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=8 + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) + +CONFIG_VFS_INITIALIZE_DEV_NULL=y +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# CONFIG_WIFI_PROV_BLE_BONDING is not set +CONFIG_WIFI_PROV_BLE_SEC_CONN=y +# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set +# CONFIG_WIFI_PROV_BLE_NOTIFY is not set +# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set +CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y +# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set +# end of Wi-Fi Provisioning Manager + +# +# ESP32-Lepton +# + +# +# GPIO +# + +# +# V-Sync +# +# CONFIG_LEPTON_GPIO_USE_VSYNC is not set +# end of V-Sync + +# +# Reset +# +CONFIG_LEPTON_GPIO_RESET_PIN=-1 +# end of Reset + +# +# Power-Down +# +CONFIG_LEPTON_GPIO_PWR_PIN=-1 +# end of Power-Down +# end of GPIO + +# +# VoSPI +# +CONFIG_LEPTON_VOSPI_SPI2_HOST=y +# CONFIG_LEPTON_VOSPI_SPI3_HOST is not set +CONFIG_LEPTON_VOSPI_MISO=12 +CONFIG_LEPTON_VOSPI_SCK=13 +CONFIG_LEPTON_VOSPI_CS=14 +CONFIG_LEPTON_VOSPI_FRAME_BUFFERS=2 +# end of VoSPI + +# +# Capture Task +# +CONFIG_LEPTON_CAPTURE_TASK_CORE_AFFINITY=y +CONFIG_LEPTON_CAPTURE_TASK_CORE=0 +CONFIG_LEPTON_CAPTURE_TASK_STACK=8192 +CONFIG_LEPTON_CAPTURE_TASK_PRIORITY=12 +# end of Capture Task + +# +# Misc +# +CONFIG_LEPTON_MISC_ERROR_BASE=0xB000 +# end of Misc +# end of ESP32-Lepton + +# +# CMake Utilities +# +# CONFIG_CU_RELINKER_ENABLE is not set +# CONFIG_CU_DIAGNOSTICS_COLOR_NEVER is not set +CONFIG_CU_DIAGNOSTICS_COLOR_ALWAYS=y +# CONFIG_CU_DIAGNOSTICS_COLOR_AUTO is not set +# CONFIG_CU_GCC_LTO_ENABLE is not set +# CONFIG_CU_GCC_STRING_1BYTE_ALIGN is not set +# end of CMake Utilities + +# +# Camera configuration +# +CONFIG_OV7670_SUPPORT=y +CONFIG_OV7725_SUPPORT=y +CONFIG_NT99141_SUPPORT=y +CONFIG_OV2640_SUPPORT=y +CONFIG_OV3660_SUPPORT=y +CONFIG_OV5640_SUPPORT=y +CONFIG_GC2145_SUPPORT=y +CONFIG_GC032A_SUPPORT=y +CONFIG_GC0308_SUPPORT=y +CONFIG_BF3005_SUPPORT=y +CONFIG_BF20A6_SUPPORT=y +# CONFIG_SC101IOT_SUPPORT is not set +CONFIG_SC030IOT_SUPPORT=y +# CONFIG_SC031GS_SUPPORT is not set +CONFIG_HM1055_SUPPORT=y +CONFIG_HM0360_SUPPORT=y +CONFIG_MEGA_CCM_SUPPORT=y +# CONFIG_SCCB_HARDWARE_I2C_DRIVER_LEGACY is not set +CONFIG_SCCB_HARDWARE_I2C_DRIVER_NEW=y +# CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set +CONFIG_SCCB_HARDWARE_I2C_PORT1=y +CONFIG_SCCB_CLK_FREQ=100000 +# CONFIG_GC_SENSOR_WINDOWING_MODE is not set +CONFIG_GC_SENSOR_SUBSAMPLE_MODE=y +CONFIG_CAMERA_TASK_STACK_SIZE=4096 +CONFIG_CAMERA_CORE0=y +# CONFIG_CAMERA_CORE1 is not set +# CONFIG_CAMERA_NO_AFFINITY is not set +CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768 +# CONFIG_CAMERA_PSRAM_DMA is not set +CONFIG_CAMERA_JPEG_MODE_FRAME_SIZE_AUTO=y +# CONFIG_CAMERA_JPEG_MODE_FRAME_SIZE_CUSTOM is not set +# CONFIG_CAMERA_CONVERTER_ENABLED is not set +# CONFIG_LCD_CAM_ISR_IRAM_SAFE is not set +# end of Camera configuration + +# +# JPEG Decoder +# +CONFIG_JD_USE_ROM=y +# end of JPEG Decoder + +# +# ESP LCD TOUCH +# +CONFIG_ESP_LCD_TOUCH_MAX_POINTS=5 +CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS=1 +# end of ESP LCD TOUCH + +# +# mDNS +# +CONFIG_MDNS_MAX_INTERFACES=3 +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_ACTION_QUEUE_LEN=16 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 + +# +# MDNS Memory Configuration +# +# CONFIG_MDNS_TASK_CREATE_FROM_SPIRAM is not set +CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL=y +# CONFIG_MDNS_MEMORY_ALLOC_SPIRAM is not set +CONFIG_MDNS_MEMORY_ALLOC_INTERNAL=y +# CONFIG_MDNS_MEMORY_CUSTOM_IMPL is not set +# end of MDNS Memory Configuration + +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +# CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES is not set +# CONFIG_MDNS_ENABLE_DEBUG_PRINTS is not set +CONFIG_MDNS_ENABLE_CONSOLE_CLI=y +# CONFIG_MDNS_RESPOND_REVERSE_QUERIES is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y + +# +# MDNS Predefined interfaces +# +CONFIG_MDNS_PREDEF_NETIF_STA=y +CONFIG_MDNS_PREDEF_NETIF_AP=y +CONFIG_MDNS_PREDEF_NETIF_ETH=y +# end of MDNS Predefined interfaces +# end of mDNS + +# +# LVGL configuration +# +CONFIG_LV_CONF_SKIP=y +# CONFIG_LV_CONF_MINIMAL is not set + +# +# Color Settings +# +# CONFIG_LV_COLOR_DEPTH_32 is not set +# CONFIG_LV_COLOR_DEPTH_24 is not set +CONFIG_LV_COLOR_DEPTH_16=y +# CONFIG_LV_COLOR_DEPTH_8 is not set +# CONFIG_LV_COLOR_DEPTH_1 is not set +CONFIG_LV_COLOR_DEPTH=16 +# end of Color Settings + +# +# Memory Settings +# +# CONFIG_LV_USE_BUILTIN_MALLOC is not set +CONFIG_LV_USE_CLIB_MALLOC=y +# CONFIG_LV_USE_MICROPYTHON_MALLOC is not set +# CONFIG_LV_USE_RTTHREAD_MALLOC is not set +# CONFIG_LV_USE_CUSTOM_MALLOC is not set +# CONFIG_LV_USE_BUILTIN_STRING is not set +CONFIG_LV_USE_CLIB_STRING=y +# CONFIG_LV_USE_CUSTOM_STRING is not set +# CONFIG_LV_USE_BUILTIN_SPRINTF is not set +CONFIG_LV_USE_CLIB_SPRINTF=y +# CONFIG_LV_USE_CUSTOM_SPRINTF is not set +# end of Memory Settings + +# +# HAL Settings +# +CONFIG_LV_DEF_REFR_PERIOD=33 +CONFIG_LV_DPI_DEF=130 +# end of HAL Settings + +# +# Operating System (OS) +# +CONFIG_LV_OS_NONE=y +# CONFIG_LV_OS_PTHREAD is not set +# CONFIG_LV_OS_FREERTOS is not set +# CONFIG_LV_OS_CMSIS_RTOS2 is not set +# CONFIG_LV_OS_RTTHREAD is not set +# CONFIG_LV_OS_WINDOWS is not set +# CONFIG_LV_OS_MQX is not set +# CONFIG_LV_OS_SDL2 is not set +# CONFIG_LV_OS_CUSTOM is not set +# end of Operating System (OS) + +# +# Rendering Configuration +# +CONFIG_LV_DRAW_BUF_STRIDE_ALIGN=1 +CONFIG_LV_DRAW_BUF_ALIGN=4 +CONFIG_LV_DRAW_LAYER_SIMPLE_BUF_SIZE=24576 +CONFIG_LV_DRAW_LAYER_MAX_MEMORY=0 +CONFIG_LV_USE_DRAW_SW=y +CONFIG_LV_DRAW_SW_SUPPORT_RGB565=y +CONFIG_LV_DRAW_SW_SUPPORT_RGB565A8=y +CONFIG_LV_DRAW_SW_SUPPORT_RGB888=y +CONFIG_LV_DRAW_SW_SUPPORT_XRGB8888=y +CONFIG_LV_DRAW_SW_SUPPORT_ARGB8888=y +CONFIG_LV_DRAW_SW_SUPPORT_ARGB8888_PREMULTIPLIED=y +CONFIG_LV_DRAW_SW_SUPPORT_L8=y +CONFIG_LV_DRAW_SW_SUPPORT_AL88=y +CONFIG_LV_DRAW_SW_SUPPORT_A8=y +CONFIG_LV_DRAW_SW_SUPPORT_I1=y +CONFIG_LV_DRAW_SW_I1_LUM_THRESHOLD=127 +CONFIG_LV_DRAW_SW_DRAW_UNIT_CNT=1 +# CONFIG_LV_USE_DRAW_ARM2D_SYNC is not set +# CONFIG_LV_USE_NATIVE_HELIUM_ASM is not set +CONFIG_LV_DRAW_SW_COMPLEX=y +# CONFIG_LV_USE_DRAW_SW_COMPLEX_GRADIENTS is not set +CONFIG_LV_DRAW_SW_SHADOW_CACHE_SIZE=0 +CONFIG_LV_DRAW_SW_CIRCLE_CACHE_SIZE=4 +CONFIG_LV_DRAW_SW_ASM_NONE=y +# CONFIG_LV_DRAW_SW_ASM_NEON is not set +# CONFIG_LV_DRAW_SW_ASM_HELIUM is not set +# CONFIG_LV_DRAW_SW_ASM_CUSTOM is not set +CONFIG_LV_USE_DRAW_SW_ASM=0 +# CONFIG_LV_USE_PXP is not set +# CONFIG_LV_USE_G2D is not set +# CONFIG_LV_USE_DRAW_DAVE2D is not set +# CONFIG_LV_USE_DRAW_SDL is not set +# CONFIG_LV_USE_DRAW_VG_LITE is not set +# CONFIG_LV_USE_VECTOR_GRAPHIC is not set +# CONFIG_LV_USE_DRAW_DMA2D is not set +# CONFIG_LV_USE_PPA is not set +# CONFIG_LV_USE_DRAW_EVE is not set +# end of Rendering Configuration + +# +# Feature Configuration +# + +# +# Logging +# +# CONFIG_LV_USE_LOG is not set +# end of Logging + +# +# Asserts +# +CONFIG_LV_USE_ASSERT_NULL=y +CONFIG_LV_USE_ASSERT_MALLOC=y +# CONFIG_LV_USE_ASSERT_STYLE is not set +# CONFIG_LV_USE_ASSERT_MEM_INTEGRITY is not set +# CONFIG_LV_USE_ASSERT_OBJ is not set +CONFIG_LV_ASSERT_HANDLER_INCLUDE="assert.h" +# end of Asserts + +# +# Debug +# +# CONFIG_LV_USE_REFR_DEBUG is not set +# CONFIG_LV_USE_LAYER_DEBUG is not set +# CONFIG_LV_USE_PARALLEL_DRAW_DEBUG is not set +# end of Debug + +# +# Others +# +# CONFIG_LV_ENABLE_GLOBAL_CUSTOM is not set +CONFIG_LV_CACHE_DEF_SIZE=0 +CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT=0 +CONFIG_LV_GRADIENT_MAX_STOPS=2 +CONFIG_LV_COLOR_MIX_ROUND_OFS=128 +# CONFIG_LV_OBJ_STYLE_CACHE is not set +# CONFIG_LV_USE_OBJ_ID is not set +# CONFIG_LV_USE_OBJ_NAME is not set +# CONFIG_LV_USE_OBJ_PROPERTY is not set +# end of Others +# end of Feature Configuration + +# +# Compiler Settings +# +# CONFIG_LV_BIG_ENDIAN_SYSTEM is not set +CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE=1 +CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y +# CONFIG_LV_USE_FLOAT is not set +# CONFIG_LV_USE_MATRIX is not set +# CONFIG_LV_USE_PRIVATE_API is not set +# end of Compiler Settings + +# +# Font Usage +# + +# +# Enable built-in fonts +# +CONFIG_LV_FONT_MONTSERRAT_8=y +CONFIG_LV_FONT_MONTSERRAT_10=y +CONFIG_LV_FONT_MONTSERRAT_12=y +CONFIG_LV_FONT_MONTSERRAT_14=y +# CONFIG_LV_FONT_MONTSERRAT_16 is not set +# CONFIG_LV_FONT_MONTSERRAT_18 is not set +# CONFIG_LV_FONT_MONTSERRAT_20 is not set +# CONFIG_LV_FONT_MONTSERRAT_22 is not set +# CONFIG_LV_FONT_MONTSERRAT_24 is not set +# CONFIG_LV_FONT_MONTSERRAT_26 is not set +# CONFIG_LV_FONT_MONTSERRAT_28 is not set +# CONFIG_LV_FONT_MONTSERRAT_30 is not set +CONFIG_LV_FONT_MONTSERRAT_32=y +# CONFIG_LV_FONT_MONTSERRAT_34 is not set +# CONFIG_LV_FONT_MONTSERRAT_36 is not set +# CONFIG_LV_FONT_MONTSERRAT_38 is not set +# CONFIG_LV_FONT_MONTSERRAT_40 is not set +# CONFIG_LV_FONT_MONTSERRAT_42 is not set +# CONFIG_LV_FONT_MONTSERRAT_44 is not set +# CONFIG_LV_FONT_MONTSERRAT_46 is not set +CONFIG_LV_FONT_MONTSERRAT_48=y +# CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED is not set +# CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW is not set +# CONFIG_LV_FONT_SOURCE_HAN_SANS_SC_14_CJK is not set +# CONFIG_LV_FONT_SOURCE_HAN_SANS_SC_16_CJK is not set +# CONFIG_LV_FONT_UNSCII_8 is not set +# CONFIG_LV_FONT_UNSCII_16 is not set +# end of Enable built-in fonts + +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_10 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12 is not set +CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14=y +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_16 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_18 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_20 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_22 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_24 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_30 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_32 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_34 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_36 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_38 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_40 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_42 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_44 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_46 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_48 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28_COMPRESSED is not set +# CONFIG_LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW is not set +# CONFIG_LV_FONT_DEFAULT_SOURCE_HAN_SANS_SC_14_CJK is not set +# CONFIG_LV_FONT_DEFAULT_SOURCE_HAN_SANS_SC_16_CJK is not set +# CONFIG_LV_FONT_DEFAULT_UNSCII_8 is not set +# CONFIG_LV_FONT_DEFAULT_UNSCII_16 is not set +# CONFIG_LV_FONT_FMT_TXT_LARGE is not set +# CONFIG_LV_USE_FONT_COMPRESSED is not set +CONFIG_LV_USE_FONT_PLACEHOLDER=y + +# +# Enable static fonts +# +# end of Enable static fonts +# end of Font Usage + +# +# Text Settings +# +CONFIG_LV_TXT_ENC_UTF8=y +# CONFIG_LV_TXT_ENC_ASCII is not set +CONFIG_LV_TXT_BREAK_CHARS=" ,.;:-_)}" +CONFIG_LV_TXT_LINE_BREAK_LONG_LEN=0 +CONFIG_LV_TXT_COLOR_CMD="#" +# CONFIG_LV_USE_BIDI is not set +# CONFIG_LV_USE_ARABIC_PERSIAN_CHARS is not set +# end of Text Settings + +# +# Widget Usage +# +CONFIG_LV_WIDGETS_HAS_DEFAULT_VALUE=y +CONFIG_LV_USE_ANIMIMG=y +CONFIG_LV_USE_ARC=y +CONFIG_LV_USE_ARCLABEL=y +CONFIG_LV_USE_BAR=y +CONFIG_LV_USE_BUTTON=y +CONFIG_LV_USE_BUTTONMATRIX=y +# CONFIG_LV_USE_CALENDAR is not set +CONFIG_LV_USE_CANVAS=y +CONFIG_LV_USE_CHART=y +CONFIG_LV_USE_CHECKBOX=y +CONFIG_LV_USE_DROPDOWN=y +CONFIG_LV_USE_IMAGE=y +CONFIG_LV_USE_IMAGEBUTTON=y +CONFIG_LV_USE_KEYBOARD=y +CONFIG_LV_USE_LABEL=y +CONFIG_LV_LABEL_TEXT_SELECTION=y +CONFIG_LV_LABEL_LONG_TXT_HINT=y +CONFIG_LV_LABEL_WAIT_CHAR_COUNT=3 +CONFIG_LV_USE_LED=y +CONFIG_LV_USE_LINE=y +CONFIG_LV_USE_LIST=y +CONFIG_LV_USE_MENU=y +CONFIG_LV_USE_MSGBOX=y +CONFIG_LV_USE_ROLLER=y +CONFIG_LV_USE_SCALE=y +CONFIG_LV_USE_SLIDER=y +CONFIG_LV_USE_SPAN=y +CONFIG_LV_SPAN_SNIPPET_STACK_SIZE=64 +CONFIG_LV_USE_SPINBOX=y +CONFIG_LV_USE_SPINNER=y +CONFIG_LV_USE_SWITCH=y +CONFIG_LV_USE_TEXTAREA=y +CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME=1500 +CONFIG_LV_USE_TABLE=y +CONFIG_LV_USE_TABVIEW=y +CONFIG_LV_USE_TILEVIEW=y +CONFIG_LV_USE_WIN=y +# end of Widget Usage + +# +# Themes +# +CONFIG_LV_USE_THEME_DEFAULT=y +# CONFIG_LV_THEME_DEFAULT_DARK is not set +CONFIG_LV_THEME_DEFAULT_GROW=y +CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME=80 +CONFIG_LV_USE_THEME_SIMPLE=y +# CONFIG_LV_USE_THEME_MONO is not set +# end of Themes + +# +# Layouts +# +CONFIG_LV_USE_FLEX=y +CONFIG_LV_USE_GRID=y +# end of Layouts + +# +# 3rd Party Libraries +# +CONFIG_LV_FS_DEFAULT_DRIVER_LETTER=0 +# CONFIG_LV_USE_FS_STDIO is not set +# CONFIG_LV_USE_FS_POSIX is not set +# CONFIG_LV_USE_FS_WIN32 is not set +# CONFIG_LV_USE_FS_FATFS is not set +# CONFIG_LV_USE_FS_MEMFS is not set +# CONFIG_LV_USE_FS_LITTLEFS is not set +# CONFIG_LV_USE_FS_ARDUINO_ESP_LITTLEFS is not set +# CONFIG_LV_USE_FS_ARDUINO_SD is not set +# CONFIG_LV_USE_FS_UEFI is not set +# CONFIG_LV_USE_FS_FROGFS is not set +# CONFIG_LV_USE_LODEPNG is not set +# CONFIG_LV_USE_LIBPNG is not set +# CONFIG_LV_USE_BMP is not set +# CONFIG_LV_USE_TJPGD is not set +# CONFIG_LV_USE_LIBJPEG_TURBO is not set +# CONFIG_LV_USE_GIF is not set +# CONFIG_LV_BIN_DECODER_RAM_LOAD is not set +# CONFIG_LV_USE_RLE is not set +# CONFIG_LV_USE_QRCODE is not set +# CONFIG_LV_USE_BARCODE is not set +# CONFIG_LV_USE_FREETYPE is not set +# CONFIG_LV_USE_TINY_TTF is not set +# CONFIG_LV_USE_RLOTTIE is not set +# CONFIG_LV_USE_THORVG is not set +# CONFIG_LV_USE_LZ4 is not set +# CONFIG_LV_USE_FFMPEG is not set +# end of 3rd Party Libraries + +# +# Others +# +# CONFIG_LV_USE_SNAPSHOT is not set +# CONFIG_LV_USE_SYSMON is not set +# CONFIG_LV_USE_PROFILER is not set +# CONFIG_LV_USE_MONKEY is not set +# CONFIG_LV_USE_GRIDNAV is not set +# CONFIG_LV_USE_FRAGMENT is not set +# CONFIG_LV_USE_IMGFONT is not set +CONFIG_LV_USE_OBSERVER=y +# CONFIG_LV_USE_IME_PINYIN is not set +# CONFIG_LV_USE_FILE_EXPLORER is not set +# CONFIG_LV_USE_FONT_MANAGER is not set +# CONFIG_LV_USE_TEST is not set +# CONFIG_LV_USE_TRANSLATION is not set +# CONFIG_LV_USE_XML is not set +# CONFIG_LV_USE_COLOR_FILTER is not set +CONFIG_LVGL_VERSION_MAJOR=9 +CONFIG_LVGL_VERSION_MINOR=4 +CONFIG_LVGL_VERSION_PATCH=0 +# end of Others + +# +# Devices +# +# CONFIG_LV_USE_SDL is not set +# CONFIG_LV_USE_X11 is not set +# CONFIG_LV_USE_WAYLAND is not set +# CONFIG_LV_USE_LINUX_FBDEV is not set +# CONFIG_LV_USE_NUTTX is not set +# CONFIG_LV_USE_LINUX_DRM is not set +# CONFIG_LV_USE_TFT_ESPI is not set +# CONFIG_LV_USE_LOVYAN_GFX is not set +# CONFIG_LV_USE_EVDEV is not set +# CONFIG_LV_USE_LIBINPUT is not set +# CONFIG_LV_USE_ST7735 is not set +# CONFIG_LV_USE_ST7789 is not set +# CONFIG_LV_USE_ST7796 is not set +# CONFIG_LV_USE_ILI9341 is not set +# CONFIG_LV_USE_GENERIC_MIPI is not set +# CONFIG_LV_USE_NXP_ELCDIF is not set +# CONFIG_LV_USE_RENESAS_GLCDC is not set +# CONFIG_LV_USE_ST_LTDC is not set +# CONFIG_LV_USE_FT81X is not set +# CONFIG_LV_USE_UEFI is not set +# CONFIG_LV_USE_OPENGLES is not set +# CONFIG_LV_USE_QNX is not set +# end of Devices + +# +# Examples +# +# CONFIG_LV_BUILD_EXAMPLES is not set +# end of Examples + +# +# Demos +# +# CONFIG_LV_BUILD_DEMOS is not set +# end of Demos +# end of LVGL configuration +# end of Component config + +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set + +# Deprecated options for backward compatibility +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_BLUEDROID_ENABLED is not set +CONFIG_NIMBLE_ENABLED=y +# CONFIG_NIMBLE_MEM_ALLOC_MODE_INTERNAL is not set +# CONFIG_NIMBLE_MEM_ALLOC_MODE_EXTERNAL is not set +CONFIG_NIMBLE_MEM_ALLOC_MODE_DEFAULT=y +CONFIG_NIMBLE_MAX_CONNECTIONS=3 +CONFIG_NIMBLE_MAX_BONDS=3 +CONFIG_NIMBLE_MAX_CCCDS=8 +CONFIG_NIMBLE_L2CAP_COC_MAX_NUM=0 +CONFIG_NIMBLE_PINNED_TO_CORE_0=y +# CONFIG_NIMBLE_PINNED_TO_CORE_1 is not set +CONFIG_NIMBLE_PINNED_TO_CORE=0 +CONFIG_NIMBLE_TASK_STACK_SIZE=4096 +CONFIG_BT_NIMBLE_TASK_STACK_SIZE=4096 +CONFIG_NIMBLE_ROLE_CENTRAL=y +CONFIG_NIMBLE_ROLE_PERIPHERAL=y +CONFIG_NIMBLE_ROLE_BROADCASTER=y +CONFIG_NIMBLE_ROLE_OBSERVER=y +CONFIG_NIMBLE_NVS_PERSIST=y +CONFIG_NIMBLE_SM_LEGACY=y +CONFIG_NIMBLE_SM_SC=y +# CONFIG_NIMBLE_SM_SC_DEBUG_KEYS is not set +CONFIG_BT_NIMBLE_SM_SC_LVL=0 +# CONFIG_NIMBLE_DEBUG is not set +CONFIG_NIMBLE_SVC_GAP_DEVICE_NAME="nimble" +CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31 +CONFIG_NIMBLE_ATT_PREFERRED_MTU=256 +CONFIG_NIMBLE_SVC_GAP_APPEARANCE=0 +CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT=12 +CONFIG_BT_NIMBLE_ACL_BUF_COUNT=24 +CONFIG_BT_NIMBLE_ACL_BUF_SIZE=255 +CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 +CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=30 +CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8 +# CONFIG_NIMBLE_HS_FLOW_CTRL is not set +CONFIG_NIMBLE_RPA_TIMEOUT=900 +# CONFIG_NIMBLE_MESH is not set +CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS=y +# CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EN is not set +CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS=y +CONFIG_SW_COEXIST_ENABLE=y +CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y +CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_GDBSTUB_SUPPORT_TASKS=y +CONFIG_GDBSTUB_MAX_TASKS=32 +# CONFIG_OTA_ALLOW_HTTP is not set +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_7=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_REDUCE_PHY_TX_POWER is not set +# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_IPC_TASK_STACK_SIZE=1280 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +CONFIG_WPA_MBEDTLS_CRYPTO=y +CONFIG_WPA_MBEDTLS_TLS_CLIENT=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5760 +CONFIG_TCP_WND_DEFAULT=5760 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/ui/PyroVision.sll b/ui/PyroVision.sll new file mode 100644 index 0000000..a35b13f --- /dev/null +++ b/ui/PyroVision.sll @@ -0,0 +1,37 @@ +{ + "name": "SquareLine_Project.spj", + "depth": 1, + "width": 320, + "height": 240, + "rotation": 90, + "offset_x": 0, + "offset_y": 0, + "shape": "RECTANGLE", + "multilang": "DISABLE", + "description": "", + "board": "ESP WROVER KIT", + "board_version": "2.0.0", + "editor_version": "1.5.4", + "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDgtX0ixtfA/hfUYYNt3ffa/tEm9jv2SBV4JwMD0xWLDDAQrNHux1G4iun1/wD5Jp4J/wC37/0cK5IEg5BxSauEZcsk10L4jsf+fP8A8itS+XYf8+X/AJFaqG9/7zfnRvf+8351n7GPn97/AMzt/tGr/LH/AMAh/wDIl/ZYf8+P/kVqXZp//Ph/5Gas/e/95vzo3v8A3m/Ol7GPn97/AMyfr9XtH/wCH/yJo7dO/wCgf/5Gal26b/0Dv/IzVm73/vN+dG9/7zfnR7CPd/e/8xfXqnaP/gEP/kTTxpn/AEDf/I7Uf8Sz/oGf+R2rM3v/AHm/Oje/95vzpewh3f8A4E/8xfXKnaP/AIBH/I1P+JX/ANAz/wAmGpc6V/0Cv/Jhqyt7/wB5vzo3v/eb86PYQ7v/AMCf+Yvrc+0f/AY/5GrnSv8AoFf+TDUu7SP+gR/5MvWTvf8AvN+dG9/7zfnR9Xh3f/gUv8xfWZ9l/wCAx/yNcNpH/QI/8mXpd+j/APQH/wDJl6x97/3m/Oje/wDeb86X1eHd/wDgUv8AMn6xLsv/AAGP+Rsh9G/6A3/k09HmaN/0Bf8Ayaesbe/95vzo3v8A3m/Oj6tDu/8AwKX+YvbS7L7l/kbXmaL/ANAT/wAm3o83RP8AoB/+Tb1i73/vN+dG9/7zfnR9Wh3f/gUv8xe1fZfcv8jc87Q/+gF/5NvR52hf9AH/AMnHrD3v/eb86N7/AN5vzpfVafd/+BS/zF7R/wBJG752hf8AQA/8nHpfP0H/AKF//wAnJKwd7/3m/Oje/wDeb86PqtPvL/wKX+ZPMb32jQP+he/8nZKX7R4f/wChd/8AJ2SsDe/95vzo3v8A3m/Ol9Up95f+BS/zFc6D7T4e/wChd/8AJ2Sl+0+Hf+hb/wDJ6Sue3v8A3m/Oje/95vzo+qU+8v8AwKX+YrI6L7V4d/6Fv/yeko+1eHP+ha/8n5K53e/95vzo3v8A3m/Oj6pT7y/8Cl/mLlX9NnR/a/Df/Qs/+T8lKLvw1/0LH/k/JXN73/vN+dG9/wC8350vqdPvL/wOX+ZPs4+f3s6T7Z4a/wChX/8AKhJS/bPDP/Qrf+VCSua3v/eb86N7/wB5vzo+p0+8v/A5f5i9lHz+9/5nTfbfDH/Qq/8AlQlpft3hf/oVP/KjLXMb3/vN+dG9/wC8350vqVLvL/wOf/yQvYQ8/vf+ZYu47UyyyQweVGzEpHvLbATwMnritfSNIsbrwP4o1GaDdd2P2T7PJvYbN8hVuAcHI9c1z5JJyTmut0D/AJJp42/7cf8A0ca60rKxsjiaKKKBHba//wAk08E/9v3/AKOFctbQNdXUNuhAeV1RS3QEnHNdTr//ACTTwT/2/f8Ao4Vy9ncfZL63udu/yZFk25xnBzjNAyymjXjeWHjMRfcQsisDtXq2MZx29ajm0+aBHZiNqOidGGdwJBAIBx8pp51ARQrFaRvGoYs3muJM5GMY2gYx7UxdTu13fOhDFSVMSkDbnGBjAxk9PWgBw0yYzPHvjBSfyCSTjdzz06cGln0qeBSzMmBCJujA437OhAOc/pUUt/czEGR1bD7z8i/M3q3HzH65pWvpXWQOfvxiMBFVVADBsYA9RnjHNAEi6VO1zJAHj3pcrbE5ONzFgD06fKf0qNbGV/KwyfvIXnGSfuruyPr8h/SpP7VunuUmlfJWUTHYqoWYHqeOT16g9aiF/ciBYQ67FQxj5FyFJJIzjOOT370AXJNNgFnMwl2XEEaPIhfdjJUdNox94dCay2AVyoYMAcZHQ1ZOo3RiaIupVlCt+7XLAEEAnGT0HWqzMWYscZJycDA/KgQlFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUVZsJrSC9SS9tGurcBg8Ky+WTkEAhsHBBweh6UAXZNDNtqlzY3uo2do0JGJZPMZJQRlWTYjEggggkDginf8I1f/2lc6fmL7TbXCwSpuPy5bbv6fdzgZ/2hxzWxD4ztLVgLax1KAfYBZNLFqQSchZVdW3iLHAGzG37uOeKz7fxQ1nEUtbeQfOxHmzbtyl9x3YUZkIO0uMfL0A60DMe9s3sbkwO6OdiSB0zhlZQykZAPQjqK6bQP+SaeNv+3H/0ca5a5mNxcyzFpDvYnMr72x2y3c+9dToH/JNPG3/bj/6ONAHE0UUUCO21/wD5Jp4J/wC37/0cK5Guu1//AJJp4J/7fv8A0cK5e1mFvcxzNGJNh3BSeCR0z7ZoGWJdKuIbkQSNGv7syM+cqoHXPHUEEEetL/ZM7eX5bxSLLJGkbKThy+4AjI9VIOajTUJkhC5zIHZg554YYYEHqDx+vrU0OsTxFXKo8iTRyplQFXYGwNoGMfN2xQAkekyzRPLFNE6KHOVD4IVcn+Hj8cVM2lxG1l2Pi6iRGaPfuJ3FRjG0AfeHc1RW9mVZAvlrvyCViUHBGCAcZAx6U46jdGFojINrKFYhFDMAQRlsZOMDv2oAfdaZLZ/611HUZ2uBkdslcE/TiqVWZb64mGHZCDnIEajJPUnA6+/Wq1AgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArZsvCmuX9lPeQ6Zd/Z4oPtAkMD7ZFyB8pAwTzn6A1jVqJrUo0V9OkVmwNsMqvtZELbmjPHzISA2OMNyOpBALEfhtZNIm1Jda00wwsEdAJy6kjIyBHwD0BOBkEZqtoehXniC+a0szErrGXLSttXqAoz6szKo92FS6Zq1pptpcbbKZ7yaCW3Mn2jERWRSvzR7ckjOR8wGQpxxVeDVGtdGlsYIzHLNOksk4fkqgO1QO3JLHnkhfSgZnkEEgjBHauu0D/kmnjb/tx/8ARxrndVvl1PVJ74QCFp28x0U5G8j5iOBgFskDtnHOK6LQP+SaeNv+3H/0caAOJooooEdtr/8AyTTwT/2/f+jhXJxoHkVS6oCfvN0FdZr/APyTTwT/ANv3/o4Vy1tN9nuY5tivsYNtboaBln+zH8vzRPCYNhfzfmxgEL0xnqwHTvTzotzsiZWjbzJI41A3fecEjkjB6diaSTVZC0xQO/nRiNzcsJWwGB4JAx0/zxiODU7i3kgZBFiF1kC+UoDFem7Aye/vzQA+HS2nZAl1b4kk8qNjuAcjGcfL7jrimDTnNotyZo1jYgZYOMfjtwfwzUYvbgPEyuqmKQyJtRQFY45xj2FH22YxxoxjYR8KWiUkD0yRnHtQBXooooEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVvW/hLUrm5uYYjCRbWC38shYhQjQCYLnHLlTjHqD2BNYNdVL42mkltAtkkdvb6e1oYkkx5shtfs3mscckLjA7AY7kkArx+Db+aVLaC5s5b3dCstqrsHh81lVCxKhSNzoDtJwWGarxeG57m506K2vLSZNQvTYwTKXC7x5eSdyghf3q9s8HjpmWx8ZazY3VpOssEhtpIpMSW6Zl8vGwSMAGcDAxk8YBGCAQReLr+30yG1tkghljuZbjzlt4uC6xqNg2fuyPL6rg89sUDKh0G6GnfbvMh8r7EL3GTu2GfyMdPvbufTHfPFatj4btLdHk1qZY4SLcxSpcmMEyxCUL/AKpySFZc52qD/F0rNi8RXttDDFbOAqWn2SRZo45VdPNMuNrJjG4g85OR1xwEXxLqqzTyGeOQzMrMJbeN1BUbVKqykKQOBtAwOKAK+s6f/ZGuahpvmeZ9kuZLffjG7YxXOPwroNA/5Jp42/7cf/RxrmLy7n1C+uL26k8y4uJGllfAG5mOScDgcmun0D/kmnjb/tx/9HGgDiaKKKBHba//AMk08E/9v3/o4VhW2h393aJdRpCIZCVRpLmOPcR1wGYGt3X/APkmngn/ALfv/RwpbWx+2eFdMJ0m9vwks/NtJs2ZK9flbr+HStaUFNu/9fmUlc52fSL62+0edblfs6q0nzDhWOFI55BJHIyORUEVpPNbz3EaZigCmRsgYycD6/hXUXeoR6Z4thiyi2cdulqyECTy0KgkNnIZlY59Mj8Kj1xNRYW2g+VHNfFjNMtrCi7jg7FwgGcLlv8AgftVulHW3TT+v66MLI5u4tZrUQmZNvnRiVOQcqc4PH0NOexuY5LeN48NcorxDcPmDHAPtyO9dHrXh7WJk0wRabdP5djGj7YydrAtkH35qTUtH1GG50SeSynWKC3gSVyhwjbzwfTqPzodBpvRhymJdeH9Rs45XnW3URZ3qLuIsMdRtDZz7VB/ZN9/aIsPI/0nAbZuHAK7sk5wBjnOeK3/ABNpTLcajcroeoRfv3c3Ty5jILdduwcH69+9bUw1Ua7ia0iGiyRRpPNLCiDyjGu795gMe/fqBV+wjzNa/wBX8kPlPP4rSeeOd4k3LbpvkO4fKuQuffkjpUNdNYiy0my8q+BP9qjYW5zDb5+WTHqWAbHovvWBe2ktheS2s4Akjbaccg+hHsRyKwnDlSZLRBRRRWYgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArrtA/wCSaeNv+3H/ANHGuRrrtA/5Jp42/wC3H/0caBo4miiigR3eo282pfCrw7c2cbTR6ZNdQ3ZQZMRdw6kjsMd/cetcZVvRfEOreHrhp9JvpbV2wG24KtjplTkH8RW//wALW8a/9Br/AMlYf/iKBnK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrRXVf8LW8a/9Br/yVh/+Io/4Wt41/wCg1/5Kw/8AxFAHK0V1X/C1vGv/AEGv/JWH/wCIo/4Wt41/6DX/AJKw/wDxFAHK0V1X/C1vGv8A0Gv/ACVh/wDiKP8Aha3jX/oNf+SsP/xFAHK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrRXVf8LW8a/9Br/yVh/+Io/4Wt41/wCg1/5Kw/8AxFAHK0V1X/C1vGv/AEGv/JWH/wCIo/4Wt41/6DX/AJKw/wDxFAHK0V1X/C1vGv8A0Gv/ACVh/wDiKP8Aha3jX/oNf+SsP/xFAHK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrRXVf8LW8a/9Br/yVh/+Io/4Wt41/wCg1/5Kw/8AxFAHK0V1X/C1vGv/AEGv/JWH/wCIo/4Wt41/6DX/AJKw/wDxFAHK0V1X/C1vGv8A0Gv/ACVh/wDiKP8Aha3jX/oNf+SsP/xFAHK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrRXVf8LW8a/9Br/yVh/+Io/4Wt41/wCg1/5Kw/8AxFAHK0V1X/C1vGv/AEGv/JWH/wCIo/4Wt41/6DX/AJKw/wDxFAHK0V1X/C1vGv8A0Gv/ACVh/wDiKP8Aha3jX/oNf+SsP/xFAHK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrXZ6dbzab8KvEVzeRtDHqc1rDaFxgylHLsQO4x39j6VW/wCFreNf+g1/5Kw//EVga14h1bxDcLPq19LdOuQu7AVc9cKMAfgKAMyilVGdgqKWY8AAZJoZGRirqVYcEEYIp2driOy0fR9D0vwxD4h8QwT3pu5XjsbCKTyxIE4d3ccgA8cfrnh/9v8Agr/oQv8AysTf4Ua//wAk08E/9v3/AKOFcjSGdd/b/gr/AKEL/wArE3+FH9v+Cv8AoQv/ACsTf4VyNFAXOu/t/wAFf9CF/wCVib/Cj+3/AAV/0IX/AJWJv8K5GigLnXf2/wCCv+hC/wDKxN/hR/b/AIK/6EL/AMrE3+FcjRQFzrv7f8Ff9CF/5WJv8KP7f8Ff9CF/5WJv8K5GigLnXf2/4K/6EL/ysTf4Uf2/4K/6EL/ysTf4VyNFAXOu/t/wV/0IX/lYm/wo/t/wV/0IX/lYm/wrkaKAudd/b/gr/oQv/KxN/hR/b/gr/oQv/KxN/hXI0UBc67+3/BX/AEIX/lYm/wAKP7f8Ff8AQhf+Vib/AArkaKAudd/b/gr/AKEL/wArE3+FH9v+Cv8AoQv/ACsTf4VyNFAXOu/t/wAFf9CF/wCVib/Cj+3/AAV/0IX/AJWJv8K5GigLnXf2/wCCv+hC/wDKxN/hR/b/AIK/6EL/AMrE3+FcjRQFzrv7f8Ff9CF/5WJv8KP7f8Ff9CF/5WJv8K5GigLnXf2/4K/6EL/ysTf4Uf2/4K/6EL/ysTf4VyNFAXOu/t/wV/0IX/lYm/wo/t/wV/0IX/lYm/wrkaKAudd/b/gr/oQv/KxN/hR/b/gr/oQv/KxN/hXI0UBc67+3/BX/AEIX/lYm/wAKP7f8Ff8AQhf+Vib/AArkaKAudd/b/gr/AKEL/wArE3+FH9v+Cv8AoQv/ACsTf4VyNFAXOu/t/wAFf9CF/wCVib/Cmaxo+h6p4Ym8Q+HoJ7I2kqR31hLJ5gjD8I6OeSCeOf0xzylddoH/ACTTxt/24/8Ao40Ac3oH/Ibt/wDgX/oJo1//AJDdx/wH/wBBFHh//kN2/wDwL/0E0eIP+Q3cf8B/9BFel/zLf+3/AP20v/l38zpNf/5Jp4J/7fv/AEcK5Guu1/8A5Jp4J/7fv/Rwrka80hhRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACuu0D/kmnjb/tx/9HGuRrrtA/5Jp42/7cf/AEcaBo5vw/8A8hu3/wCBf+gmjxB/yG7j/gP/AKCKPD//ACG7f/gX/oJo8Qf8hu4/4D/6CK9P/mW/9v8A/tpf/Lv5nSa//wAk08E/9v3/AKOFcjXXa/8A8k08E/8Ab9/6OFcjXmEMKKKKBBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV12gf8k08bf8Abj/6ONcjXXaB/wAk08bf9uP/AKONA0c34f8A+Q3b/wDAv/QTR4g/5Ddx/wAB/wDQRR4f/wCQ3b/8C/8AQTR4g/5Ddx/wH/0EV6f/ADLf+3//AG0v/l38zpNf/wCSaeCf+37/ANHCuc0pFk1iyR1DI1xGGVhkEbhwa6PX/wDkmngn/t+/9HCuRrzCDaXT47iwsWNtMoaBy9yuBGpDv97jnoO/TFZMxzKTuRuByi7R09MCo6KBBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV1Wk2V1B4dttQh0qO4uH1NBb+fbCRZwEfcgyPmGRggd/euVooA9BuNIvLjxFaXZ0F5bMwqbvT4bCNJrVJTIhUoiglgFZ1YjIBQnFZ9jpd3p95rOlCyt7vV9PBW2iNqkpfMih2CkHzDt5AIOAxIHGRx1FAztlgth4rnsorO0af7IJ0tvJRl+2/ZwWjA7gSFv3fTcAuD0qC9s531fSLMaZENSu4UN9aRWihlcSuRhAP3ZMaoSABweRzXIUUAaGvRpD4i1OKJFSNLuVVRRgKA5wAOwre0D/kmnjb/ALcf/Rxrka67QP8Akmnjb/tx/wDRxoBHN+H/APkN2/8AwL/0E0eIP+Q3cf8AAf8A0EUeH/8AkN2//Av/AEE0eIP+Q3cf8B/9BFen/wAy3/t//wBtL/5d/M6TX/8Akmngn/t+/wDRwrnNKRZNYskdQyNcRhlYZBG4cGuj1/8A5Jp4J/7fv/Rwrka8wg2Ut7MwXKR7WmtoW3sTkSHj5l+h49xg+tKUsvsgv2hK+aBHwwKhzw2FxxgfMOeMrWLRQBr3aTxSv/o0EVosn7uUwArjt82CWyPrWRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA67w7ZaRq+lH7fayl9NYyTyW8yQk2xyxZgUO8hht6g/vEH0uQNo+oae/iWbSkSSzLCeGB40t/MzmAGHZ8ytnBGRkRuT78LRQM9G0SwW+0GzkiiWV5dRlilubLQYrpQoit8Bt4XYAWboOSWP1l0/TYLqyZ7KxMUcmuXcRe10iLUVjiAh2KXfBVF3Ng98k15pRQB2lvFbT3usfYLWwmvIpJW0+xSMS7QZVBxlcTYTO0Hdxk4pYrTUjbXki6Jbt4gWSIG0+wIWSEq2XFvt25JC5O3gY6bsniqKAO30m3vpjrappllNqsFmzpZx6akjwubi3DHYUIJ2l8AZ2gt92rtrp9y1rdyLo1ufEI0xnazXT0cr/pUCq5g2lVco0gwFHygHHOT53RQB6BYWcTeIfDcOp2lhb391dwpeWT2iqZE89QuUC4jYjdkfLlQODu5fZ2Nw/iqxhu9NuMG0vXiSfw7Bbs7rbuRtiXiUghSAe+PWvPKKAO5srdm8d6VZ6hbRxxzXVoht73Ro7R5kM4yAiKVx1ySRkZHPSnad4RRTq1tLY642/Tt8Rm0fbMGFzACYk8w7vlYgkMMBjXCUUAWtSs20/UJrVo7mMxkfLdQeTJgjI3Jk46+prpNA/wCSaeNv+3H/ANHGuRrrtA/5Jp42/wC3H/0caAOb8P8A/Ibt/wDgX/oJo8Qf8hu4/wCA/wDoIo8P/wDIbt/+Bf8AoJo8Qf8AIbuP+A/+givT/wCZb/2//wC2l/8ALv5nSa//AMk08E/9v3/o4VnqNPsdA0+5l0yG6muHmDtJLIuApXGNrAd60Nf/AOSaeCf+37/0cKyYdVsG0q2sr3Tppzbs7I8dz5edxGcjYfQd64abSvclGhZ6Rp93q+jTRwv9iv2YNbu5JRl4YbhgkdCO/NU9Wtpba0Hm+G/7P3sAsxM3X0G5iKSPxCYtXsbtbREtrLiG1RyAAc5+Y5OSTkmmRajpFtdQXEOk3G6GQSbZLwMrY6AjYO+K0bptWX9beXr2HoW9V0ezttK2W6t/aFhs+3HcSG3+g7bDhTj1p39j2AW2uZUcW8WmrdzpG3zSuZCoAJzjJx+ArKtNVkg1C4urhDcC6WRLhC23eH684ODnB+oqyviB0ltWFsjRRWgtJopGysyZJOcYI6jp0IFClTbvYV0N8/TL64t4YtKFq7TIpKTsyspPIIbJz7gitHXdPNh9tVfDAgtkkZI7otNwN2Fblsc8VmSajpyPC1npRhZJVkZnuC5OD0HAAH1Bp2pajpd/JczpptxFczu0m83YZQxOT8uwfzpc0eV3av6f8D/INDIooornJCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArrtA/5Jp42/7cf/Rxrka67QP+SaeNv+3H/wBHGgaOb8P/APIbt/8AgX/oJo8Qf8hu4/4D/wCgijw//wAhu3/4F/6CaPEH/IbuP+A/+givT/5lv/b/AP7aX/y7+Z0Oj6xoeqeGIfD3iGeeyNpK8ljfxR+YIw/Lo6Dkgnnj9Mcv/sDwV/0Pv/lHm/xriaK8wg7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABpmsaxoel+GJvD3h6ee9N3Kkl9fyx+WJAnKIiHkAHnn9c8cZRQBpeH/APkN2/8AwL/0E0eIP+Q3cf8AAf8A0EVVsbtrG9juVUMUJ+UnGcjH9aL67a+vZLllClyPlBzjAx/Su320PqXsftc1/laxV1yW8zqbLQ9OlsLeR7fLvErMd7ckj61N/wAI/pf/AD6/+RG/xq1p3/IMtP8Arin/AKCKs19hRweHdOLdOOy6I6lCNtjM/wCEf0v/AJ9f/Ijf40f8I/pf/Pr/AORG/wAa06K0+pYb/n3H7kPkj2Mz/hH9L/59f/Ijf40f8I/pf/Pr/wCRG/xrToo+pYb/AJ9x+5ByR7GZ/wAI/pf/AD6/+RG/xo/4R/S/+fX/AMiN/jWnRR9Sw3/PuP3IOSPYzP8AhH9L/wCfX/yI3+NH/CP6X/z6/wDkRv8AGtOgYyM9O+KPqWG/59x+5ByR7GZ/wj+l/wDPr/5Eb/Gj/hH9L/59f/Ijf413EWjaXfWF5NaR6pGtvC0ou7gKIXKj7pAHyk9B8x5rOt9K87w3e6ptlzBcRRAgfJhg2c8dQdvf+L3rBUsG/wDl2t0tl12FaHY5j/hH9L/59f8AyI3+NH/CP6X/AM+v/kRv8a7HRtP0zUPJgNtq1zcucSG2ChYsnA4IORjnJK1FbaPBJqWrWrzmRbKGd0kiIw5Toe/B/wAmj2WDTadNaf3UFo9jk/8AhH9L/wCfX/yI3+NH/CP6X/z6/wDkRv8AGuw03TtObQZtSvYr2ZlulgVLaRU4KlsnKt6UiabZXtpqc9nFeRm2SLyopXV2ZmcKc4UZ68Ch0sIm17JaO2y/rqFo9jkP+Ef0v/n1/wDIjf40f8I/pf8Az6/+RG/xrtz4W+z3M0dzOJEWymmV4CMCWNfmjP0bg+xB71m6Np8WoyXizM6iCzmnXYQMsi5AOR0oVLBOLkoRsvJBaHY5r/hH9L/59f8AyI3+NH/CP6X/AM+v/kRv8a7FvDpmutMgtXYfabIXU8kpG2EbmDMTjhQF/wA5q9deE4je61a6b9quns4oHt1ABaTftLZAHoxPapccCnZwj9y72/NhaHY4D/hH9L/59f8AyI3+NH/CP6X/AM+v/kRv8a6y18Pzi8mj1RJrGG2h+0Tl4zv2ZAAUHGSSQB/9apf7P0jUra6OlPeRXNtE03lXRVhIi8tgqBggZOMHp1qnSwaf8NNd+VWC0Oxx3/CP6X/z6/8AkRv8aP8AhH9L/wCfX/yI3+Nd5D4RW6k0nyryGKO7t1llEtwgkBJYEImQTwBj371UXQVu7SRrSK4S5Ooi0jhmYZVSrH5uByMcngdeKlRwL+xH7kFodjjv+Ef0v/n1/wDIjf40f8I/pf8Az6/+RG/xrtG8PwWiajJcztPDbRwzQy25AWaN5ApIyD2JHsR3xUx8HytrAgS8s/sjN5iubqPzPIxu37M5+583SjlwPWEfuXk/1FaHY4X/AIR/S/8An1/8iN/jR/wj+l/8+v8A5Eb/ABrqIrC0ubDWLuEzBLUoYAzDJVn2/NxycemOatWvh5L2y0mSOYxvdNcGd35SNIgCWAAz0J+vHSrdHBx3pr/wFdr/AJDtDscb/wAI/pf/AD6/+RG/xo/4R/S/+fX/AMiN/jXa2+naHq1x9h02W/jvGB8hrnYUlYDO0gcrntyarLobXOnaQ9mskt3fyzRlMjHyFcY9OpyT6UvZYO9nTS9Yrs3+jC0exyf/AAj+l/8APr/5Eb/Gj/hH9L/59f8AyI3+Ndb4k0i10a5s4rW5NystqsrS/wALMWYHbx935eKxa0p4bCVIqUacbPyX+Q1GL6GZ/wAI/pf/AD6/+RG/xo/4R/S/+fX/AMiN/jWnRV/UsN/z7j9yDkj2Mz/hH9L/AOfX/wAiN/jR/wAI/pf/AD6/+RG/xrToo+pYb/n3H7kHJHsZn/CP6X/z6/8AkRv8aP8AhH9L/wCfX/yI3+NadFH1LDf8+4/cg5I9jM/4R/S/+fX/AMiN/jR/wj+l/wDPr/5Eb/GtOij6lhv+fcfuQckexW07/kGWn/XFP/QRVms6wv7NNOtVa7gVliQEGQAg4FWP7Rsf+fy3/wC/q/40Ua1P2cfeWy6gmrFmiq39o2P/AD+W/wD39X/Gj+0bH/n8t/8Av6v+Nae2pfzL7x3RZoqt/aNj/wA/lv8A9/V/xo/tGx/5/Lf/AL+r/jR7al/MvvC6LNFVv7Rsf+fy3/7+r/jR/aNj/wA/lv8A9/V/xo9tS/mX3hdFmgHBBxmq39o2P/P5b/8Af1f8aP7Rsf8An8t/+/q/40e2pfzL7wujrNb1fTdY8y4MupiZgPKtWK+TCemFOfujsNopi+IIILm0t4IpDpMUJhlhcANMH/1jHk/MTgjnjavpXLf2jY/8/lv/AN/V/wAaP7Rsf+fy3/7+r/jXOoYdRUebReYvdOtTV9Ml0iDTpptTght2cbbYLtuFLEhnBYYbHH8XQUzRr3Q7GK5aeXURLcW8sBSOFGVA3AOS4ycY7DmuV/tGx/5/Lf8A7+r/AI0f2jY/8/lv/wB/V/xocaNnFT380Gnc7LT9a03T9NubC21DWLZXuFmSe3jVXYBCCrASDufU9BTbPxJBpkuqzRS3d7cXMSCCe7UblkBB3N8x6dR15Arj/wC0bH/n8t/+/q/40f2jY/8AP5b/APf1f8aTpYd3vK999V5f5CtE6bRPEC6dYalZ3MbSxXUEixkcmOVlK7uT0IOD9B6VU0bUItOkvGmV2E9nNAuwA4Z1wCcnpWJ/aNj/AM/lv/39X/Gj+0bH/n8t/wDv6v8AjWj+r+97y97fUfunVal4kW40Ky0y0haIpbrFdSn70u0kqo5+6CSfc/SrMuv6XeXOri4F5HBfQ28atHGrMpjCZyCwHJX1rjP7Rsf+fy3/AO/q/wCNH9o2P/P5b/8Af1f8az9nhktJJfPzT/RBaJ0ltf6Zpt1IluLq7sbqEw3KTIsT4yCCpDMMggEZ9MU4ahpOm21yNKS8lubmJoTLdBVEaNw2ApOSRxnjr0rmf7Rsf+fy3/7+r/jR/aNj/wA/lv8A9/V/xq2qL3n667+oadzrZNQ0G8g01rttREtnbLC0cUaBX2sx4ctkfe9KfJ4t36dq6rb7LzULoyhxgiJGBDAHruIO3p0Jrj/7Rsf+fy3/AO/q/wCNH9o2P/P5b/8Af1f8aj2eHe8r/PzuFonTWuvrH4UvtHniZ3k2/ZpB/AN6syn2+XI9yfWlXXYB4fNv5Un9piM2qz8bfs5O4j13dV/3TiuY/tGx/wCfy3/7+r/jR/aNj/z+W/8A39X/ABquXD66re+/UPdOrsLzQLfR7u0mn1LzLtIxIUt4yEZTuOMycjPHaiPxBb2MOmxWkUkyWklyJFnUKJYpcDHBODtB+hx1rlP7Rsf+fy3/AO/q/wCNH9o2P/P5b/8Af1f8aThQbblO9/NdrfkGnc6q21HQ9JuPt2mxX8l4oPkLc7AkTEY3EjlsduBQniRbfwrDplrCy3e6VZLg/wAMbkEqvPfAyfQY71yv9o2P/P5b/wDf1f8AGj+0bH/n8t/+/q/40OGHbvKV/V9r/wCYe6berahFfx6asSuDbWawPuA5YMxyOenzCs2q39o2P/P5b/8Af1f8aP7Rsf8An8t/+/q/41tCpRgrKS+8d0WaKrf2jY/8/lv/AN/V/wAaP7Rsf+fy3/7+r/jVe2pfzL7wuizRVb+0bH/n8t/+/q/40f2jY/8AP5b/APf1f8aPbUv5l94XRZoqt/aNj/z+W/8A39X/ABo/tGx/5/Lf/v6v+NHtqX8y+8Los0VW/tGx/wCfy3/7+r/jR/aNj/z+W/8A39X/ABo9tS/mX3hdH//Z", + "export_temp_image": false, + "force_export_images": false, + "flat_export": false, + "advanced_alpha": false, + "pointfilter": false, + "theme_simplified": false, + "theme_dark": false, + "theme_color1": 5, + "theme_color2": 0, + "custom_variable_prefix": "uic", + "backup_cnt": 67, + "autosave_cnt": 0, + "group_color_cnt": 0, + "lvgl_version": "9.1.0", + "callfuncsexport": "CPP_FILE", + "imageexport": "SOURCE", + "lvgl_include_path": "", + "naming": "Screen_Name", + "naming_force_lowercase": false, + "naming_add_subcomponent": false, + "nidcnt": 1001699 +} \ No newline at end of file diff --git a/ui/PyroVision.slp b/ui/PyroVision.slp new file mode 100644 index 0000000..7d37d79 --- /dev/null +++ b/ui/PyroVision.slp @@ -0,0 +1,12 @@ +{ + "uiExportFolderPath": "C:\\Users\\konta\\Desktop\\ThermalCam\\firmware\\main\\Application\\Tasks\\GUI\\Export", + "projectExportFolderPath": "C:\\Users\\konta\\Desktop\\ThermalCam\\firmware\\main\\Application\\Tasks\\GUI\\Export", + "drive_stdio": "-", + "drive_stdio_path": "", + "drive_posix": "-", + "drive_posix_path": "", + "drive_win32": "-", + "drive_win32_path": "", + "drive_fatfs": "-", + "drive_fatfs_path": "" +} \ No newline at end of file diff --git a/ui/PyroVision.spj b/ui/PyroVision.spj new file mode 100644 index 0000000..7a115b7 --- /dev/null +++ b/ui/PyroVision.spj @@ -0,0 +1,15306 @@ +{ + "root": { + "guid": "GUID93537733-852890S2924354", + "deepid": 0, + "children": [ + { + "guid": "GUID66987770-852891S3274354", + "deepid": 660259650, + "children": [ + { + "guid": "GUID20182961-853099S6974354", + "deepid": -1317681897, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "SplashScreen Logo", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + -80 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "IMAGE/Image", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "IMAGE/Asset", + "strval": "assets/Logo_80x44.png", + "InheritedType": 5 + }, + { + "nid": 1030, + "strtype": "IMAGE/Pivot", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1040, + "strtype": "IMAGE/Rotation", + "InheritedType": 6 + }, + { + "nid": 1050, + "strtype": "IMAGE/Scale", + "integer": 256, + "InheritedType": 6 + }, + { + "nid": 1060, + "strtype": "IMAGE/Inner_align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1070, + "strtype": "IMAGE/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Image, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "IMAGE", + "tree_closed": true + }, + { + "guid": "GUID96239662-853101S6354354", + "deepid": 1934206739, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "SplashScreen LogoText", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + -20 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "IMAGE/Image", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "IMAGE/Asset", + "strval": "assets/Text_218x40.png", + "InheritedType": 5 + }, + { + "nid": 1030, + "strtype": "IMAGE/Pivot", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1040, + "strtype": "IMAGE/Rotation", + "InheritedType": 6 + }, + { + "nid": 1050, + "strtype": "IMAGE/Scale", + "integer": 256, + "InheritedType": 6 + }, + { + "nid": 1060, + "strtype": "IMAGE/Inner_align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1070, + "strtype": "IMAGE/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Image, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "IMAGE" + }, + { + "guid": "GUID34075349-853103S185294354", + "deepid": -2129229824, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "SplashScreen Subtext", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 20 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "OPEN SOURCE THERMAL CAMERA", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID88043540-853107S6554354", + "deepid": 585145805, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "SplashScreen LoadingBar", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 45 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 200, + 5 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "BAR/Bar", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "BAR/Range", + "intarray": [ + 0, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 1030, + "strtype": "BAR/Value", + "integer": 1, + "InheritedType": 6 + }, + { + "nid": 1040, + "strtype": "BAR/Mode", + "strval": "NORMAL", + "InheritedType": 3 + }, + { + "nid": 1050, + "strtype": "BAR/Value_start", + "InheritedType": 6 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 51, + 51, + 51, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1060, + "strtype": "BAR/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Anim1, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.INDICATOR", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1070, + "strtype": "BAR/Style_indicator", + "strval": "lv.PART.INDICATOR, Rectangle", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BAR", + "tree_closed": true + }, + { + "guid": "GUID59878104-853109S3084354", + "deepid": 666115346, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "SplashScreen StatusText", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 65 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Initialize system...", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID86331474-853111S462274354", + "deepid": 321879940, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "SplashScreen FirmwareVersion", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 90 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Firmware 1.0.0\\n(c) 2026 PyroVision Project", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 102, + 102, + 102, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "isPage": true, + "editor_posx": 400, + "editor_posy": -400, + "dont_export": false, + "locked": true, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Splash", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "flags": 1048576, + "strtype": "SCREEN/Screen", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "SCREEN/Temporary", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "SCREEN/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1050, + "strtype": "SCREEN/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "SCREEN" + }, + { + "guid": "GUID63572141-853113S4094354", + "deepid": -737127933, + "children": [ + { + "guid": "GUID10271921-68975S5384354", + "deepid": 1511971373, + "children": [ + { + "guid": "GUID70542204-68979S8364354", + "deepid": 1497257154, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Main WiFi", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 5, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_LEFT", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "W", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID89924559-68981S4954354", + "deepid": 1996386752, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Main Bluetooth", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 25, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_LEFT", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "B", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID85409111-68983S431164354", + "deepid": -1585715219, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Main SDCard", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 45, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_LEFT", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "C", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID59467401-68985S7174354", + "deepid": 1628791549, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Time", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 200, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_LEFT", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "12:34:56", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID78701249-68993S566594354", + "deepid": -314691173, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Main Battery", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 260, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_LEFT", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "B", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID38841759-68991S6814354", + "deepid": 478918629, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Battery Remaining", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 290, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_LEFT", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "75%", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID80595604-430558S178244357", + "deepid": -245967836, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main MinTemp", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 65, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 100, + "strtype": "OBJECT/Hidden", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "-99.99 °C", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 0, + 77, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID52255350-430560S2614357", + "deepid": 1196125914, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main MaxTemp", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 130, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 100, + "strtype": "OBJECT/Hidden", + "strval": "True", + "InheritedType": 2 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "+99.99 °C", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Main StatusBar", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 320, + 8 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 10620, + "strtype": "_style/Bg_Image_opa", + "integer": 180, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID69843562-430548S5034357", + "deepid": 1933161859, + "children": [ + { + "guid": "GUID40000558-68999S1814355", + "deepid": -1577322599, + "children": [ + { + "guid": "GUID34728151-155431S6754356", + "deepid": 1275935300, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Main Thermal ROI", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 60, + 60 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_LEFT", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "OFF", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID49515181-98916S7624362", + "deepid": 869040931, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Thermal Crosshair", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "CH", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "fa", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID79401473-98918S8004362", + "deepid": -262194236, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Thermal PixelTemperature", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + -15 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "101.1", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_14", + "InheritedType": 3 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 255, + 255, + 255, + 127 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Thermal", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 10, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 240, + 180 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "IMAGE/Image", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "IMAGE/Asset", + "strval": "-", + "InheritedType": 5 + }, + { + "nid": 1030, + "strtype": "IMAGE/Pivot", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1040, + "strtype": "IMAGE/Rotation", + "InheritedType": 6 + }, + { + "nid": 1050, + "strtype": "IMAGE/Scale", + "integer": 256, + "InheritedType": 6 + }, + { + "nid": 1060, + "strtype": "IMAGE/Inner_align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 3, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10530, + "strtype": "_style/Bg_gradiens_Color", + "intarray": [ + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10550, + "strtype": "_style/Gradient direction", + "strval": "HOR", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1070, + "strtype": "IMAGE/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Image, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "IMAGE" + }, + { + "guid": "GUID78751988-155420S8764356", + "deepid": -1253876820, + "children": [ + { + "guid": "GUID884834-155424S6724356", + "deepid": 809747492, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label TempScaleMax", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + -80 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 20 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Max", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 10440, + "strtype": "_style/Text_Decor", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID79834816-155425S5454356", + "deepid": -1310920733, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Gradient", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 150 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "IMAGE/Image", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "IMAGE/Asset", + "strval": "-", + "InheritedType": 5 + }, + { + "nid": 1030, + "strtype": "IMAGE/Pivot", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1040, + "strtype": "IMAGE/Rotation", + "InheritedType": 6 + }, + { + "nid": 1050, + "strtype": "IMAGE/Scale", + "integer": 256, + "InheritedType": 6 + }, + { + "nid": 1060, + "strtype": "IMAGE/Inner_align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 3, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10530, + "strtype": "_style/Bg_gradiens_Color", + "intarray": [ + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10550, + "strtype": "_style/Gradient direction", + "strval": "VER", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1070, + "strtype": "IMAGE/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Image, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "IMAGE", + "tree_closed": true + }, + { + "guid": "GUID76026531-155422S4054356", + "deepid": 809747492, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label TempScaleMin", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 90 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 20 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Min", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Gradient", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + -135, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 40, + 190 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Main Thermal", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 10 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 75 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID12873756-430552S3484357", + "deepid": -741119918, + "children": [ + { + "guid": "GUID15522018-73173S422354359", + "deepid": -755641011, + "children": [ + { + "guid": "GUID60809533-73172S422354359", + "deepid": -1351592592, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Button WiFi", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "W", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "fa", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Button Main WiFi", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + -20, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 95 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 50, + 50, + 50, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000441, + "strtype": "_event/EventHandler", + "strval": "CLICKED", + "childs": [ + { + "nid": 1000442, + "strtype": "_event/name", + "strval": "ButtonMainWiFiClicked", + "InheritedType": 10 + }, + { + "nid": 1000443, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000444, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000445, + "strtype": "_event/action", + "strval": "CALL FUNCTION", + "childs": [ + { + "nid": 1000446, + "strtype": "CALL FUNCTION/Name", + "strval": "CALL FUNCTION", + "InheritedType": 10 + }, + { + "nid": 1000447, + "strtype": "CALL FUNCTION/Call", + "strval": "<{Function_name}>( event_struct )", + "InheritedType": 10 + }, + { + "nid": 1000448, + "strtype": "CALL FUNCTION/CallC", + "strval": "<{Function_name}>( e );", + "InheritedType": 10 + }, + { + "nid": 1000449, + "strtype": "CALL FUNCTION/Function_name", + "strval": "ButtonMainWiFiClicked", + "InheritedType": 10 + }, + { + "nid": 1000450, + "strtype": "CALL FUNCTION/Dont_export_function", + "strval": "False", + "InheritedType": 2 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "BUTTON" + }, + { + "guid": "GUID29848968-155427S6724356", + "deepid": -755641011, + "children": [ + { + "guid": "GUID77308716-155429S1584356", + "deepid": -1351592592, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Button ROI", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "R", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "fa", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Button Main ROI", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 100, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 95 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 50, + 50, + 50, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BUTTON" + }, + { + "guid": "GUID61733416-934770S366964356", + "deepid": -211345156, + "children": [ + { + "guid": "GUID96116950-934769S366964356", + "deepid": 986580644, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Button Info", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "I", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "fa", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Button Main Info", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 40, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 95 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 50, + 50, + 50, + 200 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000292, + "strtype": "_event/EventHandler", + "strval": "CLICKED", + "childs": [ + { + "nid": 1000293, + "strtype": "_event/name", + "strval": "ButtonMainInfoClicked", + "InheritedType": 10 + }, + { + "nid": 1000294, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000295, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000296, + "strtype": "_event/action", + "strval": "CHANGE SCREEN", + "childs": [ + { + "nid": 1000297, + "strtype": "CHANGE SCREEN/Name", + "strval": "CHANGE SCREEN", + "InheritedType": 10 + }, + { + "nid": 1000298, + "strtype": "CHANGE SCREEN/Call", + "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", + "InheritedType": 10 + }, + { + "nid": 1000299, + "strtype": "CHANGE SCREEN/CallC", + "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", + "InheritedType": 10 + }, + { + "nid": 1000300, + "strtype": "CHANGE SCREEN/Screen_to", + "strval": "GUID10820859-155348S7984356", + "InheritedType": 9 + }, + { + "nid": 1000301, + "strtype": "CHANGE SCREEN/Fade_mode", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 1000302, + "strtype": "CHANGE SCREEN/Speed", + "InheritedType": 6 + }, + { + "nid": 1000303, + "strtype": "CHANGE SCREEN/Delay", + "InheritedType": 6 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "BUTTON" + }, + { + "guid": "GUID93999632-650710S271964356", + "deepid": -211345156, + "children": [ + { + "guid": "GUID5832432-650712S5674356", + "deepid": 986580644, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Button Menu", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "M", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "fa", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Button Main Menu", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + -80, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 95 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 50, + 50, + 50, + 200 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000268, + "strtype": "_event/EventHandler", + "strval": "CLICKED", + "childs": [ + { + "nid": 1000269, + "strtype": "_event/name", + "strval": "ButtonMainMenuClicked", + "InheritedType": 10 + }, + { + "nid": 1000270, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000271, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000272, + "strtype": "_event/action", + "strval": "CHANGE SCREEN", + "childs": [ + { + "nid": 1000273, + "strtype": "CHANGE SCREEN/Name", + "strval": "CHANGE SCREEN", + "InheritedType": 10 + }, + { + "nid": 1000274, + "strtype": "CHANGE SCREEN/Call", + "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", + "InheritedType": 10 + }, + { + "nid": 1000275, + "strtype": "CHANGE SCREEN/CallC", + "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", + "InheritedType": 10 + }, + { + "nid": 1000276, + "strtype": "CHANGE SCREEN/Screen_to", + "strval": "GUID40629891-934771S164356", + "InheritedType": 9 + }, + { + "nid": 1000277, + "strtype": "CHANGE SCREEN/Fade_mode", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 1000278, + "strtype": "CHANGE SCREEN/Speed", + "InheritedType": 6 + }, + { + "nid": 1000279, + "strtype": "CHANGE SCREEN/Delay", + "InheritedType": 6 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "BUTTON" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Main Buttons", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 11, + 97 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 10 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "isPage": true, + "editor_posx": 800, + "editor_posy": -400, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Main", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "SCREEN/Screen", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "SCREEN/Temporary", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "SCREEN/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1050, + "strtype": "SCREEN/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000248, + "strtype": "_event/EventHandler", + "strval": "SCREEN_LOADED", + "childs": [ + { + "nid": 1000249, + "strtype": "_event/name", + "strval": "ScreenMainLoaded", + "InheritedType": 10 + }, + { + "nid": 1000250, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000251, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000252, + "strtype": "_event/action", + "strval": "CALL FUNCTION", + "childs": [ + { + "nid": 1000253, + "strtype": "CALL FUNCTION/Name", + "strval": "CALL FUNCTION", + "InheritedType": 10 + }, + { + "nid": 1000254, + "strtype": "CALL FUNCTION/Call", + "strval": "<{Function_name}>( event_struct )", + "InheritedType": 10 + }, + { + "nid": 1000255, + "strtype": "CALL FUNCTION/CallC", + "strval": "<{Function_name}>( e );", + "InheritedType": 10 + }, + { + "nid": 1000256, + "strtype": "CALL FUNCTION/Function_name", + "strval": "ScreenMainLoaded", + "InheritedType": 10 + }, + { + "nid": 1000257, + "strtype": "CALL FUNCTION/Dont_export_function", + "strval": "False", + "InheritedType": 2 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "SCREEN" + }, + { + "guid": "GUID40629891-934771S164356", + "deepid": 871077125, + "children": [ + { + "guid": "GUID32876125-838323S38634360", + "deepid": 1097060484, + "children": [ + { + "guid": "GUID67585624-838322S38634360", + "deepid": 894182266, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Menu Header", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "MENU", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_14", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Panel Menu Header", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 320, + 12 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID16541557-838428S3954360", + "deepid": -1892524658, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Menu", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 15 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 210 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "isPage": true, + "editor_posx": 1200, + "editor_posy": -400, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Menu", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "SCREEN/Screen", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "SCREEN/Temporary", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "SCREEN/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1050, + "strtype": "SCREEN/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000316, + "strtype": "_event/EventHandler", + "strval": "GESTURE_RIGHT(GESTURE)", + "childs": [ + { + "nid": 1000317, + "strtype": "_event/name", + "strval": "ScreenMenuSwipeRight", + "InheritedType": 10 + }, + { + "nid": 1000318, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000319, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000320, + "strtype": "_event/action", + "strval": "CHANGE SCREEN", + "childs": [ + { + "nid": 1000321, + "strtype": "CHANGE SCREEN/Name", + "strval": "CHANGE SCREEN", + "InheritedType": 10 + }, + { + "nid": 1000322, + "strtype": "CHANGE SCREEN/Call", + "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", + "InheritedType": 10 + }, + { + "nid": 1000323, + "strtype": "CHANGE SCREEN/CallC", + "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", + "InheritedType": 10 + }, + { + "nid": 1000324, + "strtype": "CHANGE SCREEN/Screen_to", + "strval": "GUID63572141-853113S4094354", + "InheritedType": 9 + }, + { + "nid": 1000325, + "strtype": "CHANGE SCREEN/Fade_mode", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 1000326, + "strtype": "CHANGE SCREEN/Speed", + "InheritedType": 6 + }, + { + "nid": 1000327, + "strtype": "CHANGE SCREEN/Delay", + "InheritedType": 6 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + }, + { + "disabled": false, + "nid": 1000377, + "strtype": "_event/EventHandler", + "strval": "SCREEN_LOADED", + "childs": [ + { + "nid": 1000378, + "strtype": "_event/name", + "strval": "ScreenMenuLoaded", + "InheritedType": 10 + }, + { + "nid": 1000379, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000380, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000388, + "strtype": "_event/action", + "strval": "CALL FUNCTION", + "childs": [ + { + "nid": 1000389, + "strtype": "CALL FUNCTION/Name", + "strval": "CALL FUNCTION", + "InheritedType": 10 + }, + { + "nid": 1000390, + "strtype": "CALL FUNCTION/Call", + "strval": "<{Function_name}>( event_struct )", + "InheritedType": 10 + }, + { + "nid": 1000391, + "strtype": "CALL FUNCTION/CallC", + "strval": "<{Function_name}>( e );", + "InheritedType": 10 + }, + { + "nid": 1000392, + "strtype": "CALL FUNCTION/Function_name", + "strval": "ScreenMenuLoaded", + "InheritedType": 10 + }, + { + "nid": 1000393, + "strtype": "CALL FUNCTION/Dont_export_function", + "strval": "False", + "InheritedType": 2 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "SCREEN" + }, + { + "guid": "GUID10820859-155348S7984356", + "deepid": -1552217072, + "children": [ + { + "guid": "GUID98621717-155354S7474356", + "deepid": 1097060484, + "children": [ + { + "guid": "GUID15718204-155356S9244356", + "deepid": 894182266, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Header", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "SYSTEM INFORMATION", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_14", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Panel Info Header", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 320, + 30 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID28971676-155358S944356", + "deepid": 612547169, + "children": [ + { + "guid": "GUID70698399-430607S5284357", + "deepid": 1127433331, + "children": [ + { + "guid": "GUID72017967-430596S5254357", + "deepid": -467179531, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Device", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 35, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 15 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "DEVICE", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_14", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID64856691-430605S5284357", + "deepid": 1755922259, + "children": [ + { + "guid": "GUID83225215-430600S5254357", + "deepid": 1424256055, + "children": [ + { + "guid": "GUID95020504-430597S5254357", + "deepid": -567540342, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info MAC Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "MAC:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID55120083-47164S4384359", + "deepid": -567540342, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info IP Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "IP:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Container4", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID62902718-430604S5284357", + "deepid": 398216300, + "children": [ + { + "guid": "GUID41923710-430601S5284357", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info MAC", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "AA:BB:CC:DD:EE:FF", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID6232689-47165S95524359", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info IP", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "127.0.0.1\\n", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Container5", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 2, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Info Device", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 50 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 5, + 5, + 0, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Panel Device", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 300, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 6, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 37, + 37, + 37, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 5, + 5, + 5, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID57862356-155360S1954356", + "deepid": 1127433331, + "children": [ + { + "guid": "GUID71204662-155362S3724356", + "deepid": -467179531, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Battery", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 35, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 15 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "BATTERY", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_14", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID64214999-155378S3394356", + "deepid": 1755922259, + "children": [ + { + "guid": "GUID53593748-155370S562344356", + "deepid": 1424256055, + "children": [ + { + "guid": "GUID91214090-155380S114356", + "deepid": -567540342, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Battery Status Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Status:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID48938903-155382S2754356", + "deepid": -422483377, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Battery Voltage Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Voltage:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID95955079-155384S188854356", + "deepid": -1993817609, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Battery Remaining Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Remaining:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Container2", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID61454612-155376S624356", + "deepid": 398216300, + "children": [ + { + "guid": "GUID69353012-155390S9964356", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Battery Status", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Nothing", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID31824688-155392S5694356", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Battery Voltage", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "4.2 V", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID1425477-155393S19884356", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Battery Remaining", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "75%", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Container3", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 2, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Battery", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 50 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 5, + 5, + 0, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID34128925-155388S7674356", + "deepid": -249429836, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Bar2", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 15 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "BOTTOM_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "BAR/Bar", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "BAR/Range", + "intarray": [ + 0, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 1030, + "strtype": "BAR/Value", + "integer": 100, + "InheritedType": 6 + }, + { + "nid": 1040, + "strtype": "BAR/Mode", + "strval": "NORMAL", + "InheritedType": 3 + }, + { + "nid": 1050, + "strtype": "BAR/Value_start", + "InheritedType": 6 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 51, + 51, + 51, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 5, + 5, + 5, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1060, + "strtype": "BAR/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Anim1, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.INDICATOR", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 4, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 255, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10530, + "strtype": "_style/Bg_gradiens_Color", + "intarray": [ + 97, + 255, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 10550, + "strtype": "_style/Gradient direction", + "strval": "HOR", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1070, + "strtype": "BAR/Style_indicator", + "strval": "lv.PART.INDICATOR, Rectangle", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "BAR" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Panel Battery", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 300, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 6, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 37, + 37, + 37, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 5, + 5, + 5, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID44018081-155417S20174356", + "deepid": 1127433331, + "children": [ + { + "guid": "GUID18558271-155406S20134356", + "deepid": -467179531, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 35, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 15 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "LEPTON\\n", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_14", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID43255-155453S4464356", + "deepid": 1865632034, + "children": [ + { + "guid": "GUID70722931-155449S3594356", + "deepid": -969207466, + "children": [ + { + "guid": "GUID7903402-155437S25564356", + "deepid": -567540342, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton Serial Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Serial:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID29520723-155438S25564356", + "deepid": -422483377, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton Part Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Part Number:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID44302939-208082S5004365", + "deepid": -422483377, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton Revision Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Software Revision:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID94008783-430544S7064357", + "deepid": -422483377, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton Uptime Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Uptime:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID52254882-430562S8524357", + "deepid": -422483377, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton FPA Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "FPA Temperature:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID68439637-430563S113094357", + "deepid": -422483377, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton AUX Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "AUX Temperature:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Container1", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID93580312-155451S318044356", + "deepid": 1436268651, + "children": [ + { + "guid": "GUID84647470-155445S108144356", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton Serial", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Nothing", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID97949053-155446S108144356", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton Part", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Nothing", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID43761664-208083S206274365", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton Revision", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Nothing", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID13171702-430545S82544357", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton Uptime", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "0", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID86685667-430564S195944357", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton FPA", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "0", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID453239-430565S279304357", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton AUX", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "0\\n", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Container7", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 2, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 172, + -2 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Lepton", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Panel Lepton", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 80 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 300, + 140 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 6, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 37, + 37, + 37, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 5, + 5, + 5, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Panel Info Content", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 30 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 320, + 210 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "ON", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "VER", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 10, + 10 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 2, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + } + ], + "isPage": true, + "editor_posx": 800, + "editor_posy": -740, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "flags": 1048576, + "strtype": "SCREEN/Screen", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "SCREEN/Temporary", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "SCREEN/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1050, + "strtype": "SCREEN/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000304, + "strtype": "_event/EventHandler", + "strval": "GESTURE_RIGHT(GESTURE)", + "childs": [ + { + "nid": 1000305, + "strtype": "_event/name", + "strval": "ScreenInfoSwipeRight", + "InheritedType": 10 + }, + { + "nid": 1000306, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000307, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000359, + "strtype": "_event/action", + "strval": "CHANGE SCREEN", + "childs": [ + { + "nid": 1000360, + "strtype": "CHANGE SCREEN/Name", + "strval": "CHANGE SCREEN", + "InheritedType": 10 + }, + { + "nid": 1000361, + "strtype": "CHANGE SCREEN/Call", + "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", + "InheritedType": 10 + }, + { + "nid": 1000362, + "strtype": "CHANGE SCREEN/CallC", + "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", + "InheritedType": 10 + }, + { + "nid": 1000363, + "strtype": "CHANGE SCREEN/Screen_to", + "strval": "GUID63572141-853113S4094354", + "InheritedType": 9 + }, + { + "nid": 1000364, + "strtype": "CHANGE SCREEN/Fade_mode", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 1000365, + "strtype": "CHANGE SCREEN/Speed", + "InheritedType": 6 + }, + { + "nid": 1000366, + "strtype": "CHANGE SCREEN/Delay", + "InheritedType": 6 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + }, + { + "disabled": false, + "nid": 1000367, + "strtype": "_event/EventHandler", + "strval": "SCREEN_LOADED", + "childs": [ + { + "nid": 1000368, + "strtype": "_event/name", + "strval": "ScreenInfoLoaded", + "InheritedType": 10 + }, + { + "nid": 1000369, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000370, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000371, + "strtype": "_event/action", + "strval": "CALL FUNCTION", + "childs": [ + { + "nid": 1000372, + "strtype": "CALL FUNCTION/Name", + "strval": "CALL FUNCTION", + "InheritedType": 10 + }, + { + "nid": 1000373, + "strtype": "CALL FUNCTION/Call", + "strval": "<{Function_name}>( event_struct )", + "InheritedType": 10 + }, + { + "nid": 1000374, + "strtype": "CALL FUNCTION/CallC", + "strval": "<{Function_name}>( e );", + "InheritedType": 10 + }, + { + "nid": 1000375, + "strtype": "CALL FUNCTION/Function_name", + "strval": "ScreenInfoLoaded", + "InheritedType": 10 + }, + { + "nid": 1000376, + "strtype": "CALL FUNCTION/Dont_export_function", + "strval": "False", + "InheritedType": 2 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "SCREEN" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 1000201, + "strtype": "STARTEVENTS/Name", + "strval": "___initial_actions0", + "InheritedType": 10 + } + ], + "saved_objtypeKey": "STARTEVENTS" + }, + "animations": [], + "selected_theme": "Default", + "info": { + "name": "SquareLine_Project.spj", + "depth": 1, + "width": 320, + "height": 240, + "rotation": 90, + "offset_x": 0, + "offset_y": 0, + "shape": "RECTANGLE", + "multilang": "DISABLE", + "description": "", + "board": "ESP WROVER KIT", + "board_version": "2.0.0", + "editor_version": "1.5.4", + "image": "", + "export_temp_image": false, + "force_export_images": false, + "flat_export": false, + "advanced_alpha": false, + "pointfilter": false, + "theme_simplified": false, + "theme_dark": false, + "theme_color1": 5, + "theme_color2": 0, + "custom_variable_prefix": "uic", + "backup_cnt": 66, + "autosave_cnt": 0, + "group_color_cnt": 0, + "lvgl_version": "9.1.0", + "callfuncsexport": "CPP_FILE", + "imageexport": "SOURCE", + "lvgl_include_path": "", + "naming": "Screen_Name", + "naming_force_lowercase": false, + "naming_add_subcomponent": false, + "nidcnt": 1001699, + "BitDepth": 16, + "Name": "SquareLine_Project" + } +} \ No newline at end of file diff --git a/ui/PyroVision_events.py b/ui/PyroVision_events.py new file mode 100644 index 0000000..f687e30 --- /dev/null +++ b/ui/PyroVision_events.py @@ -0,0 +1,48 @@ + +def ui_ext_init(event_struct): + return + + +def Test(event_struct): + return + + +def ui_on_Button_ROI_Clicked(event_struct): + return + + +def Update_ScreenInfo(event_struct): + return + + +def Update_ScreenMenu(event_struct): + return + + +def A(event_struct): + return + + +def C(event_struct): + return + + +def ButtonMainWiFiClicked(event_struct): + return + + +def ScreenInfoLoaded(event_struct): + return + + +def ScreenMainLoaded(event_struct): + return + + +def ScreenMenuLoaded(event_struct): + return + + +def Menu(event_struct): + return + diff --git a/ui/Themes.slt b/ui/Themes.slt new file mode 100644 index 0000000..a7bdc7d --- /dev/null +++ b/ui/Themes.slt @@ -0,0 +1,8 @@ +{ + "deftheme": { + "name": "Default", + "properties": [] + }, + "themes": [], + "selected_theme": "Default" +} \ No newline at end of file diff --git a/ui/assets/Font-Awesome b/ui/assets/Font-Awesome new file mode 160000 index 0000000..16ac6af --- /dev/null +++ b/ui/assets/Font-Awesome @@ -0,0 +1 @@ +Subproject commit 16ac6af0d816e1b132bb2e3f06aa59a1bc5c6d23 diff --git a/ui/assets/Logo_80x44.png b/ui/assets/Logo_80x44.png new file mode 100644 index 0000000000000000000000000000000000000000..86f1926929fb1fdbd64f75a3a45ec7ccb17f0e63 GIT binary patch literal 6604 zcmV;-88haIP)o;hg>cr~)72bBW#UYTLWkS@*80x^?S( zYk&9t?g9Rb9Qu=wKVQGS=!g3KWuO0ZKG*!00Pp?#e~m{!asx9vUxDx0`R9Cg@D~l- zoBsBV@SAs%Y+g$0ATcnra1-49%+FnS{Q1moIu?r{UeHs|mNTxL{i_C0PhEBulXt$3 z-Xw>2kOFO0f=c6AA8u@4MY8L3M8TlU>;D|Ti}GI!h4nL^JW5}%;4T`w-hlTJ-YFT7 z0Bs<9eCe}pn(|7+Lqj13(!~B%Qdm!X*_-&%)r(!^j6Dtt}RZIT( zpR;|<3~{uZ3=iR+|1>^u^*8ju#yuR}lM?3o7_0O!u~&&^wK)#E#!Bqi(#yzrKO-aa znV#I6so8ySGd)nxK|Si68wH5-NZSy`hH}%;+ZOs_C?OPpT-OxB?s+ND3ls!O7PeO( zWK=!k49`yom=n+M!U_3R?~s*ueeTcd0~4oj4h=^F3sJ2A5#WIaB0Ih3A#3GRFFso~ z02^*QSO1~Cg`wpAfbgYg~S38-g{Cn zv{a~xkXI-I7I46L7sTB_xqIDq(4IO3uV4@o16DfV0a!JEmLQU*`eJMOXW(cN`cbc- zG0+6@T}_!o^++SULRH_c$~qCg3ET|a{J;eq8LVd|Cd^^25{BRd!H0?u9oQ5V!C1vx z1IB`MLxdXe0nS0Hu+hLAuPo3Gi_-2=V4EmIDp=nEHZg(%BEKb_()rKTxM#SK@2&h0 z@vh_W2Gk4rbKfVg{qSA?CIHpx6^Nb=R1w*U_p5?D+jJlSynqp5lPX3a5Mc<|OFEQpc~}Po3MHUd{4=wbiRJi_<2wNb zCEH#4lQR)@`W98c0nz^fej}M&JT=7`sD8_(W=EyMlA%HNiz0^l%Pg*iEWtBL+PF5Z z^I9k*0D%#vu_z4Swhpf;naN5D1G4)KTl8O=om#$J?ym!nV8jPqTK~e3H&7b(0HuH zj_bCR9&?ro&GutSGkg=?d=o=}rWcVVZvx=9eQsngS&u|1YBG=%FI^&P0um!80TY9X zIdxF^?g4pD>X{`~M@yA{feVHV?>cyjOxnaKu`0F&r_al=v^oN`NmOY8vrlVAB@hs! z_^kYljr+No{sm!cs`bSySpdH;wL89)!)OSc@>st zj^W8V+ln677vi_i&}sptD*40b(leUiwod0azi19~A-E1rpFreo2(KZ_ngqeOxcP{m z@VuY*F&6HFHv(3{Xy^|Q%BgIWa(5_HL7Ik(Xk+pT8YW;)~DwwEtXzqpdcY?~Zl(Xi^e3iDVl4#NV4s|a>WFG2P zkBx-41i)j{I92?TGEyyaHE^grr3FMv7?Yr8HdPuE8Lh|1N$#uTrl;YC334w#hMjYJ znVQN7k_L5}<_=WvMVO!WzLRrawsJLLVH)yrXXRpuVhCfrY4OR?Md)O}p4lnhF*=2# z%;o(NwN}7XGvQM^c9T)!l)UBn&X6>f?~F__sb!|LK%|B;LPZ5dIshuns^C3151Dr4 zk<&k1>Pj)B-LhEQ{SJjiPC(rRUasuvXW_55vSUt_Ii-}5T;M(nc0f9c3hC(3E#P}l ze?SxkECyY7JEO@kIy;IFM{x`8L;FN_j_lUO|N12H=|jx{g5uTW-2R|P1J`iOk~RzO z-^9lF0DP>N77%$nP5xzkALfk>l8NI-@$J;5m$ULEjxc%J8Qj`>ga=ZCl`5||yt*`}_Y62&xYwvbZBLNIN3h z47z^zaK{YUcAagxE4&xG#Auo$gzMEY{=Zq z()MtDV>d&(fILM)gqA2HKqN4raELy|Am|IA8a+iS;gRX1i5(b$SQJwEt?&k#dV_r9 zmP?*3W7Mrevy^snbMGJnzaC@SD{e5Qg`p2&JL>Poxod!RsJ{{KZcGv$oNcmcCS~U* ze$LLN$FgJB2+_lrj`Xg+1$P7lcS7!MXJGpaw0EYM%uzty8qkz1I~ah^z3547ZYLUy zBc&On*5cB}Qq)&Tfz|OAO35NB&M}aMBpK{#O%c+M@%=0!BuyZR;ohW4g@`hSVmE+H zE6j9#o=SHCs@>In-9J^Fr9*4iz4l$eMfCrt1NTC8ww;!4r3HN3KvkbnfHC@+ ziPvvy zw;e>kuVBx4H$GU#P_sfl=%rMcL-l=cAjXhuCb&vS9+l~CF`{$yl-t;X$JR1zG2{LP zPm*PxB!$Dw5>h)tGn`}(Bg77>GRUbm1gY~&CK#7#Vh_vgzVw)_XIxU~*@InBt?GrIDz6kFT67?f z=^O^MN>6bP8#gO`Yc^wTKVE8-!V<+tM<^Mv(S-RR0g^kz9ON=mO6ZKy~>9V z-OAAqti|qLN!jnu2kk>#9E@<8TgNA)ACr|i%`9P)Zsl=F_;I*~SH&lzBetLIn$C)vO)@|8_* zF|=f;^R7Ca*D%6|O6CK6oT2}^o%X%6BtKh6a`P>;lZ@eu-pkY(2a$gA9JU@+=AOm< zJQ`H#kLEBZ=%p`QLanwRgLN3F?oWSh0ewBa^hroACxjVDmSI3#r$W+|MW$vj1%t_3 zOwmA};S;a?Iun&$%w&drvy(a28*a~(pO&s=#wXx%yvEGKl5n}7;TC%nP49_Zf!Avp z7)QyN70TM8S~4y8w&GLpJyNtl_LUgD|cBs0sPxuD|%XI%BE z_=1t#98<<8LH?)xO!3RlhxtH|GJBg=mqupDdoSFJDvjC4@M=}l-=F)2xGGJ>A z29_y1$bz0edR$0fX)oqg2AEUmV~(ARLnxFY0&ht`LQFR|0MJ|>QwlJp09&$9w5*<& z@v{@Z!jz4Pwa6=U8K!3)m*#i!MDcc-3RS7{GP52u<%7D5P4XxWh50&{h#8#B@;C{P zt7EH&tqSYCvQ1$^g&CkOom_dgD_`pRdqi|~lC-iBS9yZ0w5J20)&8!5P5_ll-b1k= zNbJa#43cLPslSP2?^|f^ypI;!rea-99tc;1vvbMpd_qc~u%S{V&K1~qzlAKWH;5`F z78DB%<#SZO`vpREM01M-n@5-e%BVD-2C!KxlB)%TwE$D@SfR-UT(#dQ$j z@L?US<>KlC)TKqs!xA0p5K}^aVIH9^ij#n4#^Pw8wuG z=2_Kx`NGexk#E%Zm#^0kkgJ|Nr{e>?>+8O~8<>BdI8#PJ$gPNhFVP1_GgB17^$= zkt+~)`f^|b?(`|AipQ!Y6G!GfC-B2?lb^&r)&%jXim8FXuRP+bEmsmQtnSUx13>Wg7+>-(%k> zC|aV-V4RR9oj#>&8+-*CK}1m@mL?Pfhzz)ZSOZX)G!4W=sE-&TAoYfp&$!>r5=k#* zgdBzfLV#eq+Ar&R;50WO@7eLnX9SJGzPo8pKM$ke?5ND9i=Pc(Ioe39ClH2jMfDV1 zx_^&g3IpV}KgP@v`_p&%0_q<@<9i@{8RV8div7lg%pCM8N^d)ffni5wCPys}D31*@ zTMFnKtg?45B$v(*4bSqeFJ8`)EJF|Mqx{%bcCJ{O9f2_xWA6r-*ux8IQ8;3xXfT(8D<*C;ZmSaBO-*j zYjM_e@=>FmB5d;e@?Mvt?Q$3(kns0gU~l1iM$=2Vp8_lN0YqO^>uaC2dwc%s)Apu# zUmdP_8$)MLvg7C16V8tb+Yw=9fL!_;3NxG0NkcqRp*>qh>tzO{OwaNY*n8RGEdM`W z=gJE|$ksy0L3^fI*HfahV&C*cROg^(J;JUB-pY!iXVGklxY{T*@m>g2a88IkEPix= zV9UP5ro|mgZ--J1(jv$0T0u)Klfil(4DzV2VboGfmNG@gE#@&CRlMX75j;X0&n6tA zf~vtQI24yXJ8CF~48fqC_QLN0P~Oq=Lw#rce16TJIS}o8&KN|S%sIh21&HSx^OMOF&+sjv=V3nfhr!M zDjh{QX~%HlaVRz#e-=6`R(zF4qZbiRu2AQW+kSsvSU;ScOHaFc8xoNQnDWc9j}5qa;z> ztPnm@V%4WlrtK#A;qv?N^*)#?bI_g|`|eu6R2p+W7{%iU}#{ ztRWe;)VJiA-BKjoS;dbQU@DKFiZD}os0YwA&^BmlA+{J*OuLFyra>Z>OwXq$sdWaB zfC5TjN9Eh;yr%)Inpun%F+geV9kPATi=IU-1P1GKl$r~$3T<(ujee{P+374JctRB_l?@#8ye|`m?M}P;sb&%m)lN00 zlkh#a0n5^>WQ`x<(j?~4C*H~%F~Mcv?+5w|`RpBo^ZiS%zMWkw2Pq%kM`19d-I!)# ztj&16#n^0{Efcdm5ZAdkXtQ%}NM)kV&Ip%3WMTY8RFCR_7k&1Fp9^}|Zsg)dz(6}9 zNCRwUFsUF(fOk0p3Rw}G8mtBcK|q)jY|bDi=za-YL(hcIc(LfCnF5!Q-12vS-T@hMznD zH__9fZX?3a2GF+94hY(Lio=758d~CT-eR34Qo(owcAPW+@l5&BSAY4efP2wJ$C71+ za@kXh_ghtK`FnT<;#CAKl|A=Pv7(M{k~4R@oWSr9(;-X=;4e1!$y2> zx=L4Vyq6b_Hds`T7>{dgU2+glT<}JAr!W}8Qt*||cj-ioeK6OlxN*;Va@SnP-rJ@b zirZ8RDTQ7oDl3Iz2319S66jBGJxyFS!POjT*^|`_Sx-n4GgfEL^oU%w-_8GSGl(x; zauvGiY(U8$^clJSk@xJZ`O}_xsiD#oa<0>(QDbr9 zNh3qOXqhYrO!nlMm|J9Q#Sk0b@H*M_CvW_`FO}uWx6JaNn}oK)5MKmI=F-YGj@K^I*DwC^&6nfrILpl3b5DCe<^4S84$I4r zPicS`J`X{cK%GG_Ou(-IK_7=tVUPeg2nq)jg#pB17{m$=$!efV;9NQDlGt`|z>l!6 zDinrM69x!Cz>79YWw#n@kOi1u^uc`oGP!tBQ*9*=#icgi)J^s-D zj30OY=&$1Ad<-Mc!wOAsp7}Pk(-K{CNZV5A5B$7pzYSL>AaUgk#5xhWr#` zpK!sXu04Bo@8t9PU`ZGNu=*jT9Qfb3-fH_ypiM9YFbM*Sj@uf${X!tJ(FPW+jP(a& zfU1uk)gO0XGL~1~wLfvy7t6$xGnO{&JqM>2G+JU{dFRd@2Qh1QV?IkyOC9+5Q@`){ z=Rf@Z@Y%FEZp_GA`}XPOgwzFN+}_UAf$v4 z5{7A_q~z4*|Hk!JIb(nXzz84~D_jZIXO84?%Rml*lYOlt7M+V2;<@w;>?YrP@RC5) zOA8ymJO{1V^6KASkXK%D`DbnO^B!%i(Evh9a`KRyZ~JBYf4=+HkuzzpOUJycQre`j z<~}PfE~d3>*UtrjX%|oa;MF(&QP8(8tP*T+AqeW|$%Ck;(*_w$i#?BJewtXo^r zok7~Rw#)n{hWsosdFaJy{WdKs+wq?`0RuY*az=GyUB>tI!88b44wzWA$Nc`=f>2d! z*N*KOci!l}Dajc@{k+5kGYdp8bsXG(NZ)&~gddo{t^Q<7*RR|B{r9(*mK|u#Ej+x)cFK?;f8d-ufJ`AM{rKkj;OkDkR{M~oVj->Ylq zAzr^X$T>qetjVgX>P73rz&P13fqviHx*`Skg(_ljQd;s8LM0JfV#ruj)s8`G}5 zdDQrEBQoL>0;9R2P)$uuLs@yvs^v?++P7iD$`ei8fznUoDK)`xsWpqjH%*4;KlVTL z9; z22Ko+5=EuFWa=M7-2vc{>r&f}?xw%hw*$^kPm*z}M*;G6@U(?)p zR;^zD{OD1`A0aeSX#kENE0S-$^KS4je|o0HdHKV$FHC#z*Y|zq@pxmj83RyUT!N>c zdA9w#Z@+OA0OowY_~)HF<-g83CuURXu*r~}yY|e#;reTCY3?3(-TP4Lg_FnM*QHa3 zJ2NvgG6R8t>h*deL=F)_NP+tL2D7ZJtfsQ6`ipPA-S+p*-)`Ue$@_1{STnzS&ty}& zZ!7TmJV7Fg(ZW^LH9IbtFm_x^(}$q{(bx0l%AH_(H|G5sEW1lBqdB!pt`0eR8~>F;k)g-AHVhI)4q#p zGzp8yu+0o-=1CIFGmrx_mWRXH+3~-9_%d~3z-w5x3poRp;GCmNE^ohPx3=t}D-rZE zgIV`tksT4%dGfWr)Dg>88K6kKk8y&@fc4aeu;Np_EPP_CW2$rmf3y# z_I@NWDFJS+#sFkwX7JRM2(MKNK>3sLg_pa&s;DYzE0|9@GWZ;b9P(eYrmd5(o7YlD4I%LqZ8R==+ zj59E>rYS|DUs-ilg&8GAVqz~+Fd_B3R_GC_+5y$Ni2ux

D+1BZMWXE`o))~_j2B^FF%?oiM-J(BH?pLc{&R> z(fjrC)o)LpG~w-xjI?YpMEl@qMQThbId3rpgGs*g$BcaJw(GBd{li(GDNRBk?#u0e zIP(-t3MOB6$we!=bm`oKF$Tv(mlUne{hfCFaen`(kwc$ew0Ox~01yS5uqk`TXOn<> zW;jDZ8NmoQ2Qq8pdYHg3|5;DF4|zYAAr5HF1{ni%0AWIUyu9Md-U&%9`cs|7G(Sm? z6=GnKdyv6UT<%%Ad4F9E07y-OV!%v*Mo3Tz*AEj9CxSe%K?U8engw3cfzmRiG6J&R z0siEb_;6TzV}dFj5ZU1lom`-jF0k3((P6!>N%)yyqk5S)FL_k`OQT^K1xE_z37hIB zvNyi{cYa>(_$UAL!f99Hyg^AFvU9RC$&N!s7GDx7E35S-U$30sNZ4E7lLV3!xtAnB z$k?6w!9S*VA3tu)ALHW#Q8>BpV}}Qv8nfZa0i#5DWo7B6P2WWP7DZ7a=B5RF8EN-) zoY_}jFZjdA5kv1#J*pxbjnmoq?*6$EB<;!=M_yj;FMIdw_QvQ*SHysgbIZ1gY1?kU zQ>Tt;IXO8!oGhNm{Mq9rXAVKGwIiq=5Bl`!{ny*>yt^HTE@R_oPJGOekmAgU!d{tx zmq|c4F*!%tTd#(lwYTUyF{i9XA#%s<>`j>wFWL<3q+Ha}eX^6yDNF#7YPTVDjvWU) zvmAB zuDLsg6;wQ65smGtWD!%&TuEv9qR}{{a0ws8fRBifos|_gb?Qaes-y#OQ}nj}BLPVB z%!sOzYNdaQPxC;hSUpSxaE4GlD*}KSE9-XsYI4%5G`~3>L{Xv>fS(Ht>7Y#n@M&}R zc;@;xUEBEU`!NwK^cWaQt9YpR6c$E-#z4A5q&kj|v}|fS{%6Tr1sbW)gbFSNyv&3k ziTy?LTc@qT9rXvjrew@vWSyIH34;_IIO#v~<4L}*qLwWRNyu(l#>CD!;{4oXqq_=e z`Mi!X&m<|dF1p}DvzcNPf`h4u-izZKf{cq2& zZf;(Zl9H|>TRXU=IA=g{Y3b}H848R?*ElkV*5-)a;u8~6Qc^Bx6tS^MPs#%k;W!Y823ET{dj9wZ+wrwxyCg?kFc}|xpOil z>Kgd`C+Am$Bkvft@8kwNvjglL5MVe^;;TAXneocHW5&8IKkD$o#MmyJw@)=Ee^bo9 z27nnqPa2u!sT;{m=E4{QNJ2=$%DujYPcK!k-g2Nk?CR>=f$bC0{(g=BuR}Y9ZstyU zywhP~$W0PMp1n9}_!En2HaQm^K2o@>ZTq&jGgr{x!Dn`M)&=z>`@-(Bp0-!Y-xbLF5-*L5sgzVf~0E7smQ zb)=}SiVQn05I9d|CbvvHH^^W~RgY}hbiA;0AnnnM#IO6OhyRCbWP{9>{L+%Ll_3>B z9APUXtkF067sIoam)j-@A31=rGsxQ}$@GqG*jS)3`xsQ(#_7|z=CU^|X9K2S_;xRg zk=%-~eJF|zHxL7e1G`E*^B$k?yJPA8!gBX@%Xa}*5LE*J^vN`@_2^8oGGAQjFOqPg zLM?e=DP6VYK)KdnEBkOm@V9wMo@x2XW@3ztBZdT(VPw7>1t0>noqG?>7&>(D ztzMsxM>@Gltz1J1j-PYraPu|_rTkj1j^T)1PbU+@5~y*zqsBcJJQXZC*Q0fY;}}2*3mGc`>Dou|OCY^stWazTfw1 zb0Bldd+&d+XVBmQNNLk124oJorBYZnPLgI(L^%J0o#hp(y;`lyPaxl zV>{|Iq%o}6$6o{LV>-C;2bw)JSDonhil}#OA41GX#Ff|ekN@Q-JL)4H%S#b=X2c1L zJRuh2OBR(YU%j%SHYT7eHJjEar#c7hfYM6k@aOyLiq2$1#3|?$F{_y^a&3TnG`^&@ z>rYk6ZOCL3Y%e(q15QZsQ16^JZM-KcDk7V-sOZGPoV@%S$rZ<8V33RD3!!RBJS1eH5`MeB3LSit*Jui*`h#4y* zgu-Dg`fBN^mhSWA{7+cJU!OygB)8ECW`mfEaFqUz(BWY#*2TgSEF{1~50(4J)=$$pzAID~H}OLZijGOQLjeW@863$ztUFW58&3|MZ;vf(g#x7H zI8y0pHASnw9>+)nNV7u-hI0x6Fb&Gi_ala4UcF}h?2x8MfM7 z>MN&Cicd&LlD2jd5lR{;Jym*i-~Ro_nicVe0aHkrQojVGrriDUoHDM6b?r< zkdW53P9+9^AR#fgUHhK>2MxOOhMTVY>Z&U*sNJ|_`+Lv7^vWc}^;MfqUHhMfTfvkX zGcryIlN|6z!EAw4uDM&-BgVTH>_N@@x!g#cDxh{>lVnQyHaHH>Ow*j5;`%~CNoRz*sbd= z*WYl%(r-3?yy2PW{yL#?ABqlt<1vI_5x~1Pq~TI&9Xh9wA!NE~10*spLP9r8q-WIRR90NmCb zOebXfFwOa1{|wK#9KWd|?CPUo0qI1UvS9ha>L!z|fLVT;K_H!M!C;Mzv@;7?Y}{VL zr6HLmd?*^IwgcQ+sP%S8kbQ90?n9XDIkf`YY9k#o^R4MdO z=Uxo}qbFS!mzbPGUt^HKp3r0JSSLbUG}MT zCy-4B!E6AELrudcYuBz_6V}a`P2~VCAt^W|uji1!fPn*t#RuEu={6t@2Q-pUT2@~4 z;evI$S^}CW(MXfXhz4zv^t|K?y7R_sfA{8_|LD1H-TJ>DJzi8;+YlxPV1_BI4JNEt zYcmscyZRH8d_zZ#dh@pX9?p*nAVV=+n=zuXB*Abc*j825$oh~b9ZeUlfFTIrt!tUM zxHt$KKn?&*X}vaRx?WycRcU3bs4-gFsi)KS%>qr@z;ac?*1#%ER~**G0t%_%4c#R64yeyx-v05HM~-SG~WZKM{5EO}DF~$HUo8~&Y%G<9zcl7O7aQ{Wu z{^G&5dD+88j~z2ICo5}YAP_eu7)(k6S6xh-6PmDn-NazlnDfW{>fP5~e8^g1OLM8F zbVtR&7@)a;wqw&r4Jm0at}rD{i5>y6LLQ7MIC8jPD1a6TksEHl3B*{8rgZKV*0kz^ z9UJz;&I@(4YJ~L#1LIb9iPz_E9cY4}3yO_SGRquQ$?;iY@=mM`CJedrnH^Q1;onp? z98+hF%2EHE<~I`Dtegso+<5cqYx?DEZs#peVj5hBQwhWwj+OeBL)26^3p87MF=+?g zWi(DBG=9eYtE>Vt+PFxl2x&;D4%0{gEuKjB6C26Q*hEz(ttH?Z`>xF7O~M2Fzg<#a zR{F$}V4Jj?8fPh}zBqL3+U=_3)U?6YhGh1F+GhyE8n%ABb#`l;!4#ITq-eAuvLRY4 zOJ>b50IYlKuNJBF+vi_l!KCC#J$v=MH#;})LXX$yac@*-XJ_W*jT|}QQnq2m0wUW) zR16t81>gW)Gh!L^;*t_QJ2$sUw2yI)U|L4!*81xY#E%lh?Q}wliH((%lttLlP&f?T z6t?!F2oKBbq>H%tz?o?@NiiHQvvQKa$(>m1R0ANL!T2{ntL3GgRb?kC_!-m?YeY8LujMtq!lUKo&8m>?+rOXP5Y}zK#O;$v1XDAwVXF56%RIBp zG|iOIbb;dH;0cAq>5V zKSU7R(|hp9QOq%4BR-Sid@nkV7@!rG>~}PUyK07nKQ4Y6fEMk?)U4dmn%T%q71rE^ zG-GLGUUU;?<2kWSR6{nOgW1Sou}pZ=A&3A&0J;ElLEsj#5hXj|{9Ctuihpz2b4qCXN;q?EPW$vKGS*nqfu(-~xn2jx+_@ z?_c@nWq*EW?khb`+9zz@RUcs(wXvnZqfV_6Mb@NHGYX-~^C&EDM7x-M$I z*?>L6GP8g$8j#GxseaQBj%dCd0SOHJ!W=pGf0f|P8!F}U4+?8_0JtnGMID=^-F|tl z_HvS)O%t(r1c6M#u{uuQl*-D7C0qQCZm`Za6pfWL%p2yh`?3CouGs5k1vj_u#C9yVrd zXvR_yk2W1vuk& zez%obUQu2eUa@rPyjV8YBA3XOYswgdW=b@K!mZ4#HzKr{%NHatgme=sG=LO4>A~eE zF);9-0BB409S#4`CjN_darljuaufwyfJ{rPx=9*h_^w1*-(rf74p7KCyb5U@cC?ZL z7|38}E(A{2oxCA0uwr7Sn98|3W5DW6zTZr{F|T3KJxij6Oen3rSWoXrk6^mOXcuY$J zM$^0;GK52S5fPU?{+?&((9Uz?gUNmnkd@y)J2R*4qOLvqR!_co@){yqdgRby03_4X zGm({(GcGZu&DD~t5SFbK!y`4+)qnBL3M(g3NC8bqFvHH`cV)OWCS=wum|1_pl#AX- zO3ip$x(-t_0Gu%-wn_60A9um*9{mOs-gfUjdjSSjRr>_nq~`n$nS{jv&%a6K1Q=yi{PA0-9kqd5~NvtU;9;0M%|-vKWeu{X|dI zUsLY+bV$(rO^Qd4d32q#shA7zB@K$)R;kWyF?M3uzL>O}S>}3df-u=x^=(m^|JI&K zp3S+Q+K!Q9HZ}vs3GhR*wyMklryPrEvqL3LK2hYrl?D2vwVsnRPk5em5|>X`{{HG~ z+h2ICZ+&7g7~kY!bT;7J627#o{M$X7mK{BlSdVUss8F>v8W_QFIpw3f1>efd$?GX> ztz)kROG-^o4yI;YrmD(i9lH095FUnU+NZijl>4#!8LF+J9ox6R>SA?-Fob|9oTOqzw3=p!*j&}q0Zqtgc*4G&Btj^xLnXt0bb;%5h9zRG=kWg&6kP`hiDzWDPwH%-2L+KTk-oc7$- zOx)JSEatHxERt*JoF$8%zy?m8C~DZWVaxSv=Y0^9=s*BWM+h~_>(mVav(-SF2c~cZ z-0gcya^h%V3C0^gZ319i!VjPJlOWA3H@~ll|FDaP4^kBoJtyhXYD9pP!1gjW2U<;w zqvocSqsSzIq$N0<^Orv3?3uOuf2dkjZzNoDMP}fi9em-oY9zzk{YcAba2M+c7D4dTv5R}gTmcF ziwYk?G;^MaAccvdV@G!F*|qQD4_Lu<$sI$%+5aV?E@0EKB^+4nx5=auaZ!vdn)!e#D8Sb ze=YeT3?^q*%t~5uG!B4qAWr|+9&h;g;kwn^8KX7d|U1KXNwr+_ZN2g8Z&M{+^KB#_QH<5iCmyAq7f~6&|Xo zt~;Y=DH3e<&M@H|7*#lj!Wo3?T-&z`XPVzGoca7^w?FuK{~<&En3X=YZLQ8TI8q zUoFryHmZBiF86lm+Wl8)nb~c9oybn_VF9d zB8IpMLkNU4-G07^JGN(_zM-L2ji#9yDsBSO!O%D2nrg;>203;A0feCn| ziO%i2Z$mDwY4LpPLDJEp9U1m zwl<{|KulzuRhjW8fYN`dkF$$wN@o}2$^OCQ*KSVoP8pJ5jtVGZLQo}Axpfbnaa5Wf zsxz=~S3O_%wb^~?!lEs;K;2p2@5HeaC407Sn~<8BtLUM67`hICz!k;PK)L~8gi&8x zd20Xqg=fTE6&*SBk>BIn7}j)1vNV)ptAt~R_BWZB`R}}RaQ-{Ew##|r+fBOcia~j8 z+mBKeWtcZEF3aQbf{45%rL3>3ty4VSCC3Yo?EZ4zyv+wTEk5n932lCWn?s&|dnzME z1qldY!uh?AhT6&&dEphaUNKexF9Ue_ricDKv_r=Z)7p3H6sW7Iz1ZXR03hhPE>y37 zVbQU|+MV0Bt=PP3`NqkbK)+?x$+-YF7^T!s^{jRwQ%-NTs~`?@Jf!ED?iWVSmH+F?PcDhFJhJy-pD`W` z@nic~g@zhhQ0=)DRC^9&=gK*tok@u&Bl1&E4l_<1kwldMDbBT9)liVRghBt0`{Yrem{TUvhT+%laj=YVz=CD|X; z_nP%{49)NXY99@}BO?hxK%6&u Date: Fri, 2 Jan 2026 23:13:15 +0100 Subject: [PATCH 02/26] Working on firmware --- components/ESP32-Lepton | 2 +- main/Application/Manager/Devices/ADC/adc.cpp | 1 + .../Devices/PortExpander/portexpander.cpp | 89 +- main/Application/Manager/Devices/RTC/rtc.cpp | 12 +- main/Application/Manager/Devices/SPI/spi.cpp | 46 +- .../Manager/Devices/devicesManager.cpp | 24 +- .../Manager/Devices/devicesManager.h | 2 +- .../Network/Provisioning/provisioning.cpp | 115 +- .../Network/Provisioning/provisioning.h | 6 +- .../Application/Manager/Network/SNTP/sntp.cpp | 45 +- .../Manager/Network/Server/http_server.cpp | 81 +- .../Manager/Network/Server/image_encoder.cpp | 95 +- .../Manager/Network/Server/image_encoder.h | 26 +- .../Network/Server/websocket_handler.cpp | 59 +- .../Manager/Network/networkManager.cpp | 246 +- .../Manager/Network/networkManager.h | 38 +- .../Manager/Network/network_types.h | 61 +- main/Application/Manager/SD/sdManager.cpp | 9 +- .../Manager/Settings/settingsManager.cpp | 63 +- .../Manager/Settings/settings_types.h | 42 +- .../Application/Tasks/Devices/devicesTask.cpp | 3 - .../Application/Tasks/GUI/Export/project.info | 6 +- .../Tasks/GUI/Export/screens/ui_Info.c | 59 +- .../Tasks/GUI/Export/screens/ui_Info.h | 4 + .../Tasks/GUI/Export/screens/ui_Main.c | 170 +- .../Tasks/GUI/Export/screens/ui_Main.h | 11 +- .../Tasks/GUI/Export/screens/ui_Menu.c | 53 +- .../Tasks/GUI/Export/screens/ui_Menu.h | 4 + .../Tasks/GUI/Export/ui_events.cpp | 5 +- .../Tasks/GUI/Private/guiHelper.cpp | 25 +- .../Application/Tasks/GUI/Private/guiHelper.h | 23 +- main/Application/Tasks/GUI/guiTask.cpp | 477 +- main/Application/Tasks/GUI/guiTask.h | 15 + main/Application/Tasks/Lepton/leptonTask.cpp | 214 +- main/Application/Tasks/Lepton/leptonTask.h | 9 + .../Application/Tasks/Network/networkTask.cpp | 158 +- main/Application/Tasks/Network/networkTask.h | 17 +- main/Application/application.h | 38 +- main/idf_component.yml | 8 +- main/main.cpp | 22 +- sdkconfig.debug | 84 +- ui/PyroVision.sll | 4 +- ui/PyroVision.spj | 6692 +++++++++++------ ui/project.info | 4 +- 44 files changed, 5497 insertions(+), 3670 deletions(-) diff --git a/components/ESP32-Lepton b/components/ESP32-Lepton index 6d6d932..0cafcb1 160000 --- a/components/ESP32-Lepton +++ b/components/ESP32-Lepton @@ -1 +1 @@ -Subproject commit 6d6d932df55577a86c5ad8ea701370ab8ab1edbf +Subproject commit 0cafcb18a299bc3cb9daad1d7fd99501ec40cd16 diff --git a/main/Application/Manager/Devices/ADC/adc.cpp b/main/Application/Manager/Devices/ADC/adc.cpp index 982d0e2..dd0d7cf 100644 --- a/main/Application/Manager/Devices/ADC/adc.cpp +++ b/main/Application/Manager/Devices/ADC/adc.cpp @@ -57,6 +57,7 @@ esp_err_t ADC_Init(void) ESP_ERROR_CHECK(adc_oneshot_new_unit(&_ADC_Init_Config, &_ADC_Handle)); ESP_ERROR_CHECK(adc_oneshot_config_channel(_ADC_Handle, ADC_CHANNEL_0, &config)); + Error = ESP_OK; _ADC_Calib_Done = false; if (_ADC_Calib_Done == false) { diff --git a/main/Application/Manager/Devices/PortExpander/portexpander.cpp b/main/Application/Manager/Devices/PortExpander/portexpander.cpp index fbd6dc1..357e133 100644 --- a/main/Application/Manager/Devices/PortExpander/portexpander.cpp +++ b/main/Application/Manager/Devices/PortExpander/portexpander.cpp @@ -31,29 +31,29 @@ #define ADDR_PCAL6416AHF 0x20 -#define PORT_EXPANDER_ADDR_INPUT0 0x00 -#define PORT_EXPANDER_ADDR_INPUT1 0x01 -#define PORT_EXPANDER_ADDR_OUTPUT0 0x02 -#define PORT_EXPANDER_ADDR_OUTPUT1 0x03 -#define PORT_EXPANDER_ADDR_POL0 0x04 -#define PORT_EXPANDER_ADDR_POL1 0x05 -#define PORT_EXPANDER_ADDR_CONF0 0x06 -#define PORT_EXPANDER_ADDR_CONF1 0x07 -#define PORT_EXPANDER_ADDR_STRENGTH0_0 0x40 -#define PORT_EXPANDER_ADDR_STRENGTH0_1 0x41 -#define PORT_EXPANDER_ADDR_STRENGTH1_0 0x42 -#define PORT_EXPANDER_ADDR_STRENGTH1_1 0x43 -#define PORT_EXPANDER_ADDR_LATCH0 0x44 -#define PORT_EXPANDER_ADDR_LATCH1 0x45 -#define PORT_EXPANDER_ADDR_PULL_EN0 0x46 -#define PORT_EXPANDER_ADDR_PULL_EN1 0x47 -#define PORT_EXPANDER_ADDR_PULL_SEL0 0x48 -#define PORT_EXPANDER_ADDR_PULL_SEL1 0x49 -#define PORT_EXPANDER_ADDR_INT_MASK0 0x4A -#define PORT_EXPANDER_ADDR_INT_MASK1 0x4B -#define PORT_EXPANDER_ADDR_INT_STATUS0 0x4C -#define PORT_EXPANDER_ADDR_INT_STATUS1 0x4D -#define PORT_EXPANDER_ADDR_OUT_CONFIG 0x4F +#define PORT_EXPANDER_REG_INPUT0 0x00 +#define PORT_EXPANDER_REG_INPUT1 0x01 +#define PORT_EXPANDER_REG_OUTPUT0 0x02 +#define PORT_EXPANDER_REG_OUTPUT1 0x03 +#define PORT_EXPANDER_REG_POL0 0x04 +#define PORT_EXPANDER_REG_POL1 0x05 +#define PORT_EXPANDER_REG_CONF0 0x06 +#define PORT_EXPANDER_REG_CONF1 0x07 +#define PORT_EXPANDER_REG_STRENGTH0_0 0x40 +#define PORT_EXPANDER_REG_STRENGTH0_1 0x41 +#define PORT_EXPANDER_REG_STRENGTH1_0 0x42 +#define PORT_EXPANDER_REG_STRENGTH1_1 0x43 +#define PORT_EXPANDER_REG_LATCH0 0x44 +#define PORT_EXPANDER_REG_LATCH1 0x45 +#define PORT_EXPANDER_REG_PULL_EN0 0x46 +#define PORT_EXPANDER_REG_PULL_EN1 0x47 +#define PORT_EXPANDER_REG_PULL_SEL0 0x48 +#define PORT_EXPANDER_REG_PULL_SEL1 0x49 +#define PORT_EXPANDER_REG_INT_MASK0 0x4A +#define PORT_EXPANDER_REG_INT_MASK1 0x4B +#define PORT_EXPANDER_REG_INT_STATUS0 0x4C +#define PORT_EXPANDER_REG_INT_STATUS1 0x4D +#define PORT_EXPANDER_REG_OUT_CONFIG 0x4F #define PORT_EXPANDER_INPUT 0x01 #define PORT_EXPANDER_OUTPUT 0x00 @@ -93,8 +93,9 @@ typedef enum { /** @brief Default input polarity inversion configuration for the Port Expander. */ -static uint8_t DefaultPolarityConfig[] = { // Byte 0 - PORT_EXPANDER_ADDR_POL0, +static uint8_t DefaultPolarityConfig[] = { + // Byte 0 + PORT_EXPANDER_REG_POL0, // Byte 1 (Polarity 0) 0x00, @@ -105,8 +106,9 @@ static uint8_t DefaultPolarityConfig[] = { // Byte 0 /** @brief Default input latch configuration for the Port Expander. */ -static uint8_t DefaultLatchConfig[] = { // Byte 0 - PORT_EXPANDER_ADDR_LATCH0, +static uint8_t DefaultLatchConfig[] = { + // Byte 0 + PORT_EXPANDER_REG_LATCH0, // Byte 1 (Latch 0) 0x00, @@ -117,8 +119,9 @@ static uint8_t DefaultLatchConfig[] = { // Byte 0 /** @brief Default pull-up / pull-down configuration for the Port Expander. */ -static uint8_t DefaultPullConfig[] = { // Byte 0 - PORT_EXPANDER_ADDR_PULL_EN0, +static uint8_t DefaultPullConfig[] = { + // Byte 0 + PORT_EXPANDER_REG_PULL_EN0, // Byte 1 (Enable 0) 0x00, @@ -135,8 +138,9 @@ static uint8_t DefaultPullConfig[] = { // Byte 0 /** @brief Default output pin configuration for the Port Expander. */ -static uint8_t DefaultPortConfiguration[] = { // Byte 0 - PORT_EXPANDER_ADDR_CONF0, +static uint8_t DefaultPortConfiguration[] = { + // Byte 0 + PORT_EXPANDER_REG_CONF0, // Byte 1 (Config 0) (PORT_EXPANDER_OUTPUT << PIN_BATTERY_VOLTAGE_ENABLE) | (PORT_EXPANDER_OUTPUT << PIN_CAMERA) | @@ -148,8 +152,9 @@ static uint8_t DefaultPortConfiguration[] = { // Byte 0 /** @brief Default output pin level for the Port Expander. */ -static uint8_t DefaultPinConfiguration[] = { // Byte 0 - PORT_EXPANDER_ADDR_OUTPUT0, +static uint8_t DefaultPinConfiguration[] = { + // Byte 0 + PORT_EXPANDER_REG_OUTPUT0, // Byte 1 (Output 0) // Enable camera power by default (active high for PIN_CAMERA) @@ -174,17 +179,17 @@ static i2c_master_dev_handle_t _Expander_Dev_Handle; static const char *TAG = "PortExpander"; -/** @brief Set the pin level of the pins of a given port. - * @param Port Target port - * @param Mask Pin mask - * @param Level Pin level - * @return ESP_OK when successful - * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function - * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized +/** @brief Set the pin level of the pins of a given port. + * @param Port Target port + * @param Mask Pin mask + * @param Level Pin level + * @return ESP_OK when successful + * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function + * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized */ static esp_err_t PortExpander_SetPinLevel(PortDefinition_t Port, uint8_t Mask, uint8_t Level) { - return I2CM_ModifyRegister(&_Expander_Dev_Handle, PORT_EXPANDER_ADDR_OUTPUT0 + static_cast(Port), Mask, Level); + return I2CM_ModifyRegister(&_Expander_Dev_Handle, PORT_EXPANDER_REG_OUTPUT0 + static_cast(Port), Mask, Level); } /** @brief Enable the interrupts for given pins. @@ -197,7 +202,7 @@ static esp_err_t PortExpander_SetPinLevel(PortDefinition_t Port, uint8_t Mask, u */ static esp_err_t PortExpander_SetInterruptMask(PortDefinition_t Port, uint8_t Mask, uint8_t EnableMask) { - return I2CM_ModifyRegister(&_Expander_Dev_Handle, PORT_EXPANDER_ADDR_INT_MASK0 + static_cast(Port), Mask, + return I2CM_ModifyRegister(&_Expander_Dev_Handle, PORT_EXPANDER_REG_INT_MASK0 + static_cast(Port), Mask, ~EnableMask); } diff --git a/main/Application/Manager/Devices/RTC/rtc.cpp b/main/Application/Manager/Devices/RTC/rtc.cpp index edabbcf..7f96a86 100644 --- a/main/Application/Manager/Devices/RTC/rtc.cpp +++ b/main/Application/Manager/Devices/RTC/rtc.cpp @@ -104,18 +104,18 @@ static i2c_master_dev_handle_t *_RTC_Dev_Handle = NULL; static const char *TAG = "RTC"; -/** @brief Convert BCD to binary. - * @param BCD BCD value - * @return Binary value +/** @brief Convert BCD to binary. + * @param BCD BCD value + * @return Binary value */ static uint8_t RTC_BCD2Bin(uint8_t BCD) { return ((BCD >> 4) * 10) + (BCD & 0x0F); } -/** @brief Convert binary to BCD. - * @param Bin Binary value - * @return BCD value +/** @brief Convert binary to BCD. + * @param Bin Binary value + * @return BCD value */ static uint8_t RTC_Bin2BCD(uint8_t Bin) { diff --git a/main/Application/Manager/Devices/SPI/spi.cpp b/main/Application/Manager/Devices/SPI/spi.cpp index 8e2cca4..3f5ff29 100644 --- a/main/Application/Manager/Devices/SPI/spi.cpp +++ b/main/Application/Manager/Devices/SPI/spi.cpp @@ -41,22 +41,17 @@ static SPI_Bus_State_t _SPI_State[SOC_SPI_PERIPH_NUM]; static const char *TAG = "spi-manager"; -/** @brief Initialize SPI bus. - * @param p_Config Pointer to SPI bus configuration - * @param Host SPI host device - * @param DMA_Channel DMA channel to use - * @return ESP_OK on success, error code otherwise +/** @brief Initialize SPI bus. + * @param p_Config Pointer to SPI bus configuration + * @param Host SPI host device + * @param DMA_Channel DMA channel to use + * @return ESP_OK on success, error code otherwise */ esp_err_t SPIM_Init(const spi_bus_config_t *p_Config, spi_host_device_t Host, int DMA_Channel) { esp_err_t Error; - if (p_Config == NULL) { - return ESP_ERR_INVALID_ARG; - } - - if (Host >= SOC_SPI_PERIPH_NUM) { - ESP_LOGE(TAG, "Invalid SPI host: %d", Host); + if ((p_Config == NULL) || (Host >= SOC_SPI_PERIPH_NUM)){ return ESP_ERR_INVALID_ARG; } @@ -100,9 +95,7 @@ esp_err_t SPIM_Deinit(spi_host_device_t Host) if (Host >= SOC_SPI_PERIPH_NUM) { return ESP_ERR_INVALID_ARG; - } - - if (_SPI_State[Host].isInitialized == false) { + } else if (_SPI_State[Host].isInitialized == false) { return ESP_OK; } @@ -110,11 +103,6 @@ esp_err_t SPIM_Deinit(spi_host_device_t Host) ESP_LOGW(TAG, "SPI%d still has %d devices attached", Host + 1, _SPI_State[Host].DeviceCount); } - if (_SPI_State[Host].Mutex != NULL) { - vSemaphoreDelete(_SPI_State[Host].Mutex); - _SPI_State[Host].Mutex = NULL; - } - xSemaphoreTake(_SPI_State[Host].Mutex, portMAX_DELAY); Error = spi_bus_free(Host); if (Error != ESP_OK) { @@ -124,6 +112,11 @@ esp_err_t SPIM_Deinit(spi_host_device_t Host) } xSemaphoreGive(_SPI_State[Host].Mutex); + if (_SPI_State[Host].Mutex != NULL) { + vSemaphoreDelete(_SPI_State[Host].Mutex); + _SPI_State[Host].Mutex = NULL; + } + _SPI_State[Host].isInitialized = false; _SPI_State[Host].DeviceCount = 0; @@ -137,7 +130,7 @@ esp_err_t SPIM_AddDevice(spi_host_device_t Host, const spi_device_interface_conf { esp_err_t Error; - if ((p_Dev_Config == NULL) || (p_Handle == NULL)) { + if ((p_Dev_Config == NULL) || (p_Handle == NULL) || (Host >= SOC_SPI_PERIPH_NUM)) { return ESP_ERR_INVALID_ARG; } @@ -171,7 +164,7 @@ esp_err_t SPIM_RemoveDevice(spi_host_device_t Host, spi_device_handle_t Handle) { esp_err_t Error; - if (Handle == NULL) { + if ((Handle == NULL) || (Host >= SOC_SPI_PERIPH_NUM)) { return ESP_ERR_INVALID_ARG; } @@ -183,13 +176,10 @@ esp_err_t SPIM_RemoveDevice(spi_host_device_t Host, spi_device_handle_t Handle) return Error; } - /* Decrement device count for the host (we don't track which host, so decrement all) */ - for (int i = 0; i < SOC_SPI_PERIPH_NUM; i++) { - if (_SPI_State[i].DeviceCount > 0) { - _SPI_State[i].DeviceCount--; - break; - } + if (_SPI_State[Host].DeviceCount > 0) { + _SPI_State[Host].DeviceCount--; } + xSemaphoreGive(_SPI_State[Host].Mutex); ESP_LOGI(TAG, "SPI device removed"); @@ -212,7 +202,7 @@ esp_err_t SPIM_Transmit(spi_host_device_t Host, spi_device_handle_t Handle, uint esp_err_t Error; spi_transaction_t trans; - if (Handle == NULL) { + if ((Handle == NULL) || (Host >= SOC_SPI_PERIPH_NUM)) { return ESP_ERR_INVALID_ARG; } diff --git a/main/Application/Manager/Devices/devicesManager.cpp b/main/Application/Manager/Devices/devicesManager.cpp index 40aa062..19df7d0 100644 --- a/main/Application/Manager/Devices/devicesManager.cpp +++ b/main/Application/Manager/Devices/devicesManager.cpp @@ -94,9 +94,6 @@ static Devices_Manager_State_t _Devices_Manager_State; static const char *TAG = "devices-manager"; -/** @brief Initialize the devices manager. - * @return ESP_OK on success, ESP_FAIL on error - */ esp_err_t DevicesManager_Init(void) { if (_Devices_Manager_State.initialized) { @@ -104,13 +101,11 @@ esp_err_t DevicesManager_Init(void) return ESP_OK; } - /* Initialize I2C bus */ if (I2CM_Init(&_Devices_Manager_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize I2C!"); return ESP_FAIL; } - /* Initialize SPI bus */ if (SPIM_Init(&_Devices_Manager_SPI_Config, SPI3_HOST, SPI_DMA_CH_AUTO) != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize SPI3!"); return ESP_FAIL; @@ -143,9 +138,6 @@ esp_err_t DevicesManager_Init(void) return ESP_OK; } -/** @brief Deinitialize the devices manager. - * @return ESP_OK on success, error code otherwise - */ esp_err_t DevicesManager_Deinit(void) { esp_err_t Error; @@ -169,9 +161,6 @@ esp_err_t DevicesManager_Deinit(void) return Error; } -/** @brief Get the I2C bus handle. - * @return I2C bus handle, or NULL if not initialized - */ i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void) { if (_Devices_Manager_State.initialized == false) { @@ -182,11 +171,6 @@ i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void) return _Devices_Manager_State.I2C_Bus_Handle; } -/** @brief Get battery voltage and percentage. - * @param p_Voltage Pointer to store voltage in millivolts - * @param p_Percentage Pointer to store percentage (0-100) - * @return ESP_OK on success, error code otherwise - */ esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage) { int Raw; @@ -224,11 +208,7 @@ esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage) return ESP_OK; } -/** @brief Get RTC device handle. - * @param p_Handle Pointer to store RTC handle - * @return ESP_OK on success, error code otherwise - */ -esp_err_t DevicesManager_GetRTCHandle(void **p_Handle) +esp_err_t DevicesManager_GetRTCHandle(i2c_master_dev_handle_t *p_Handle) { if (_Devices_Manager_State.initialized == false) { ESP_LOGE(TAG, "Devices Manager not initialized yet!"); @@ -239,7 +219,7 @@ esp_err_t DevicesManager_GetRTCHandle(void **p_Handle) return ESP_ERR_INVALID_ARG; } - *p_Handle = &_Devices_Manager_State.RTC_Handle; + *p_Handle = _Devices_Manager_State.RTC_Handle; return ESP_OK; } \ No newline at end of file diff --git a/main/Application/Manager/Devices/devicesManager.h b/main/Application/Manager/Devices/devicesManager.h index 6477b1a..1a74ced 100644 --- a/main/Application/Manager/Devices/devicesManager.h +++ b/main/Application/Manager/Devices/devicesManager.h @@ -56,7 +56,7 @@ esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage); * @param p_Handle Pointer to store the RTC handle * @return ESP_OK on success */ -esp_err_t DevicesManager_GetRTCHandle(void **p_Handle); +esp_err_t DevicesManager_GetRTCHandle(i2c_master_dev_handle_t *p_Handle); // TODO: Function to get charge status? diff --git a/main/Application/Manager/Network/Provisioning/provisioning.cpp b/main/Application/Manager/Network/Provisioning/provisioning.cpp index 971fd45..c4bd720 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.cpp +++ b/main/Application/Manager/Network/Provisioning/provisioning.cpp @@ -37,12 +37,13 @@ typedef struct { bool isInitialized; bool active; - Network_ProvMethod_t Method; char device_name[32]; char pop[32]; uint32_t timeout_sec; TimerHandle_t timeout_timer; TaskHandle_t network_task_handle; + wifi_sta_config_t WiFi_STA_Config; + bool hasCredentials; } Provisioning_State_t; static Provisioning_State_t _Provisioning_State; @@ -54,7 +55,6 @@ static const char *TAG = "Provisioning"; */ static void on_Timeout_Timer_Handler(TimerHandle_t p_Timer) { - /* Use task notification to signal timeout */ if (_Provisioning_State.network_task_handle != NULL) { xTaskNotify(_Provisioning_State.network_task_handle, 0x01, eSetBits); } @@ -74,34 +74,62 @@ static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t Event break; } case WIFI_PROV_CRED_RECV: { - wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)p_EventData; - ESP_LOGD(TAG, "Received WiFi credentials - SSID: %s", wifi_sta_cfg->ssid); - /* Save credentials */ - NetworkManager_SetCredentials((const char *)wifi_sta_cfg->ssid, (const char *)wifi_sta_cfg->password); - NetworkManager_SaveCredentials(); + wifi_sta_config_t *wifi_cfg = (wifi_sta_config_t *)p_EventData; + + if (wifi_cfg != NULL) { + memcpy(&_Provisioning_State.WiFi_STA_Config.ssid, wifi_cfg->ssid, sizeof(wifi_cfg->ssid)); + memcpy(&_Provisioning_State.WiFi_STA_Config.password, wifi_cfg->password, sizeof(wifi_cfg->password)); + + _Provisioning_State.hasCredentials = true; + + ESP_LOGD(TAG, "Received WiFi credentials - SSID: %s", _Provisioning_State.WiFi_STA_Config.ssid); + } else { + ESP_LOGE(TAG, "WiFi config in CRED_RECV is NULL!"); + } + break; } case WIFI_PROV_CRED_FAIL: { wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)p_EventData; + ESP_LOGE(TAG, "Provisioning failed! Reason: %s", (*reason == WIFI_PROV_STA_AUTH_ERROR) ? "Auth Error" : "AP Not Found"); + break; } case WIFI_PROV_CRED_SUCCESS: { + Network_WiFi_Credentials_t Credentials; + ESP_LOGD(TAG, "Provisioning successful"); - /* Stop timeout timer */ + if (_Provisioning_State.timeout_timer != NULL) { xTimerStop(_Provisioning_State.timeout_timer, 0); } + + memset(&Credentials, 0, sizeof(Credentials)); + + /* Copy SSID and password from saved configuration */ + if (_Provisioning_State.hasCredentials) { + strncpy(Credentials.SSID, (const char *)_Provisioning_State.WiFi_STA_Config.ssid, sizeof(Credentials.SSID) - 1); + strncpy(Credentials.Password, (const char *)_Provisioning_State.WiFi_STA_Config.password, + sizeof(Credentials.Password) - 1); + + ESP_LOGD(TAG, "Credentials - SSID: %s, Password: %s", Credentials.SSID, Credentials.Password); + } else { + ESP_LOGE(TAG, "No WiFi credentials available!"); + } + + NetworkManager_SetCredentials(&Credentials); + break; } case WIFI_PROV_END: { ESP_LOGD(TAG, "Provisioning ended"); + wifi_prov_mgr_deinit(); - /* Release BLE/BT memory after provisioning */ - if ((_Provisioning_State.Method == NETWORK_PROV_BLE) || (_Provisioning_State.Method == NETWORK_PROV_BOTH)) { - wifi_prov_scheme_ble_event_cb_free_btdm(NULL, WIFI_PROV_END, NULL); - } + wifi_prov_scheme_ble_event_cb_free_btdm(NULL, WIFI_PROV_END, NULL); + _Provisioning_State.active = false; + break; } default: { @@ -127,7 +155,6 @@ static esp_err_t on_Custom_Data_Prov_Handler(uint32_t session_id, const uint8_t ESP_LOGD(TAG, "Received custom data: %.*s", (int)inlen, (char *)p_InBuf); } - /* Send device info as response */ const char *response = "{\"device\":\"PyroVision\",\"version\":\"1.0\"}"; *p_OutLen = strlen(response); *p_OutBuf = (uint8_t *)malloc(*p_OutLen); @@ -142,20 +169,14 @@ static esp_err_t on_Custom_Data_Prov_Handler(uint32_t session_id, const uint8_t return ESP_OK; } -esp_err_t Provisioning_Init(Network_ProvMethod_t Method, const Network_Config_t *p_Config) +esp_err_t Provisioning_Init(Network_WiFi_STA_Config_t *p_Config) { if (_Provisioning_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); return ESP_OK; } - if (Method == NETWORK_PROV_NONE) { - ESP_LOGD(TAG, "Provisioning disabled"); - return ESP_OK; - } - ESP_LOGD(TAG, "Initializing Provisioning Manager"); - _Provisioning_State.Method = Method; #ifdef CONFIG_NETWORK_PROV_BLE_DEVICE_NAME strncpy(_Provisioning_State.device_name, CONFIG_NETWORK_PROV_BLE_DEVICE_NAME, sizeof(_Provisioning_State.device_name) - 1); @@ -173,10 +194,8 @@ esp_err_t Provisioning_Init(Network_ProvMethod_t Method, const Network_Config_t #else _Provisioning_State.timeout_sec = 300; #endif - /* Register event handler */ ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &on_Prov_Event, NULL)); - /* Create timeout timer */ _Provisioning_State.timeout_timer = xTimerCreate("prov_timeout", (_Provisioning_State.timeout_sec * 1000) / portTICK_PERIOD_MS, pdFALSE, @@ -198,10 +217,8 @@ void Provisioning_Deinit(void) Provisioning_Stop(); - /* Give time for stop to complete before deinit */ vTaskDelay(200 / portTICK_PERIOD_MS); - /* Now safely deinit the provisioning manager */ wifi_prov_mgr_deinit(); if (_Provisioning_State.timeout_timer != NULL) { @@ -235,26 +252,16 @@ esp_err_t Provisioning_Start(void) ESP_LOGD(TAG, "Starting Provisioning"); - if ((_Provisioning_State.Method == NETWORK_PROV_BLE) || (_Provisioning_State.Method == NETWORK_PROV_BOTH)) { - prov_config.scheme = wifi_prov_scheme_ble; - prov_config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; - } - - if (_Provisioning_State.Method == NETWORK_PROV_SOFTAP) { - prov_config.scheme = wifi_prov_scheme_softap; - prov_config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; - } - + prov_config.scheme = wifi_prov_scheme_ble; + prov_config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; prov_config.app_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; - /* Initialize provisioning */ Error = wifi_prov_mgr_init(prov_config); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to init Provisioning: %d!", Error); return Error; } - /* Security configuration */ #ifdef CONFIG_NETWORK_PROV_SECURITY_VERSION int security = CONFIG_NETWORK_PROV_SECURITY_VERSION; #else @@ -265,22 +272,18 @@ esp_err_t Provisioning_Start(void) pop = _Provisioning_State.pop; } - /* Set service name (BLE device name or SoftAP SSID) */ esp_wifi_get_mac(WIFI_IF_STA, mac); snprintf(service_name, sizeof(service_name), "%.26s_%02X%02X", _Provisioning_State.device_name, mac[4], mac[5]); - if ((_Provisioning_State.Method == NETWORK_PROV_BLE) || (_Provisioning_State.Method == NETWORK_PROV_BOTH)) { - /* Configure BLE service UUID */ - uint8_t custom_service_uuid[] = { - 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, - 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, - }; - wifi_prov_scheme_ble_set_service_uuid(custom_service_uuid); - } + + uint8_t custom_service_uuid[] = { + 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, + 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, + }; + wifi_prov_scheme_ble_set_service_uuid(custom_service_uuid); /* Register custom endpoint */ wifi_prov_mgr_endpoint_create("custom-data"); - /* Start provisioning */ Error = wifi_prov_mgr_start_provisioning((wifi_prov_security_t)security, pop, service_name, NULL); if (Error != ESP_OK) { @@ -289,14 +292,11 @@ esp_err_t Provisioning_Start(void) return Error; } - /* Register custom endpoint handler */ wifi_prov_mgr_endpoint_register("custom-data", on_Custom_Data_Prov_Handler, NULL); _Provisioning_State.active = true; - /* Post provisioning started event */ esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STARTED, NULL, 0, portMAX_DELAY); - /* Start timeout timer */ if (_Provisioning_State.timeout_timer != NULL) { xTimerStart(_Provisioning_State.timeout_timer, 0); } @@ -314,18 +314,14 @@ esp_err_t Provisioning_Stop(void) ESP_LOGD(TAG, "Stopping Provisioning"); - /* Stop timeout timer */ if (_Provisioning_State.timeout_timer != NULL) { xTimerStop(_Provisioning_State.timeout_timer, 0); } - /* Stop provisioning service - do NOT deinit to avoid race conditions */ - /* The provisioning manager can be restarted without deinit */ wifi_prov_mgr_stop_provisioning(); _Provisioning_State.active = false; - /* Post provisioning stopped event */ esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STOPPED, NULL, 0, portMAX_DELAY); return ESP_OK; @@ -338,13 +334,8 @@ bool Provisioning_isProvisioned(void) memset(&config, 0, sizeof(wifi_prov_mgr_config_t)); - if ((_Provisioning_State.Method == NETWORK_PROV_BLE) || (_Provisioning_State.Method == NETWORK_PROV_BOTH)) { - config.scheme = wifi_prov_scheme_ble; - config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; - } else if (_Provisioning_State.Method == NETWORK_PROV_SOFTAP) { - config.scheme = wifi_prov_scheme_softap; - config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; - } + config.scheme = wifi_prov_scheme_ble; + config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; if (wifi_prov_mgr_init(config) == ESP_OK) { wifi_prov_mgr_is_provisioned(&isProvisioned); @@ -360,10 +351,6 @@ esp_err_t Provisioning_Reset(void) { ESP_LOGD(TAG, "Resetting Provisioning"); - /* Clear WiFi credentials from NVS */ - NetworkManager_ClearCredentials(); - - /* Reset provisioning state */ wifi_prov_mgr_reset_provisioning(); return ESP_OK; diff --git a/main/Application/Manager/Network/Provisioning/provisioning.h b/main/Application/Manager/Network/Provisioning/provisioning.h index 4c2c73a..2366fc4 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.h +++ b/main/Application/Manager/Network/Provisioning/provisioning.h @@ -24,14 +24,16 @@ #ifndef PROVISIONING_H_ #define PROVISIONING_H_ +#include +#include + #include "../network_types.h" /** @brief Initialize provisioning manager. - * @param Method Provisioning method (BLE, SoftAP, or both) * @param p_Config Network configuration * @return ESP_OK on success */ -esp_err_t Provisioning_Init(Network_ProvMethod_t Method, const Network_Config_t *p_Config); +esp_err_t Provisioning_Init(Network_WiFi_STA_Config_t *p_Config); /** @brief Deinitialize provisioning manager. */ diff --git a/main/Application/Manager/Network/SNTP/sntp.cpp b/main/Application/Manager/Network/SNTP/sntp.cpp index 4557a6b..5b8f918 100644 --- a/main/Application/Manager/Network/SNTP/sntp.cpp +++ b/main/Application/Manager/Network/SNTP/sntp.cpp @@ -28,39 +28,8 @@ #include "sntp.h" #include "../networkManager.h" -#define SNTP_TZ_MAX_LEN 64 - -static char _SNTP_Timezone[SNTP_TZ_MAX_LEN] = "CET-1CEST,M3.5.0,M10.5.0/3"; - static const char *TAG = "sntp"; -/** @brief SNTP event handler for task coordination. - * @param p_HandlerArgs Handler argument - * @param Base Event base - * @param ID Event ID - * @param p_Data Event-specific data - */ -static void on_SNTP_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) -{ - switch (ID) { - case NETWORK_EVENT_SET_TZ: { - size_t Len = strlen((const char *)p_Data); - if (Len < SNTP_TZ_MAX_LEN) { - memcpy(_SNTP_Timezone, (const char *)p_Data, Len + 1); - setenv("TZ", _SNTP_Timezone, 1); - tzset(); - } else { - ESP_LOGE(TAG, "Timezone string too long!"); - } - - break; - } - default: { - break; - } - } -} - /** @brief SNTP time synchronization callback. * @param p_tv Pointer to timeval structure with synchronized time */ @@ -73,17 +42,6 @@ static void on_SNTP_Time_Sync(struct timeval *p_tv) esp_err_t SNTP_Init(void) { - esp_err_t Error; - - Error = esp_event_handler_register(NETWORK_EVENTS, NETWORK_EVENT_SET_TZ, on_SNTP_Event_Handler, NULL); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to register event handler: %d!", Error); - return Error; - } - - setenv("TZ", _SNTP_Timezone, 1); - tzset(); - esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); esp_sntp_setservername(0, "pool.ntp.org"); esp_sntp_set_time_sync_notification_cb(on_SNTP_Time_Sync); @@ -95,7 +53,7 @@ esp_err_t SNTP_Init(void) esp_err_t SNTP_Deinit(void) { esp_sntp_stop(); - return esp_event_handler_unregister(NETWORK_EVENTS, NETWORK_EVENT_SET_TZ, on_SNTP_Event_Handler); + return ESP_OK; } esp_err_t SNTP_GetTime(uint8_t Retries) @@ -121,6 +79,7 @@ esp_err_t SNTP_GetTime(uint8_t Retries) } ESP_LOGD(TAG, "Time synchronized successfully"); + time(&Now); localtime_r(&Now, &TimeInfo); diff --git a/main/Application/Manager/Network/Server/http_server.cpp b/main/Application/Manager/Network/Server/http_server.cpp index 681438a..7501dde 100644 --- a/main/Application/Manager/Network/Server/http_server.cpp +++ b/main/Application/Manager/Network/Server/http_server.cpp @@ -34,6 +34,7 @@ #include "http_server.h" #include "image_encoder.h" +#include "../network_types.h" #define HTTP_SERVER_API_BASE_PATH "/api/v1" #define HTTP_SERVER_API_KEY_HEADER "X-API-Key" @@ -58,25 +59,26 @@ static const char *TAG = "http_server"; */ static bool HTTP_Server_CheckAuth(httpd_req_t *p_Request) { - if (_HTTPServer_State.Config.api_key == NULL) { + char ApiKey[64] = {0}; + + if (_HTTPServer_State.Config.API_Key == NULL) { return true; } - char ApiKey[64] = {0}; if (httpd_req_get_hdr_value_str(p_Request, HTTP_SERVER_API_KEY_HEADER, ApiKey, sizeof(ApiKey)) != ESP_OK) { return false; } - return (strcmp(ApiKey, _HTTPServer_State.Config.api_key) == 0); + return (strcmp(ApiKey, _HTTPServer_State.Config.API_Key) == 0); } /** @brief Send JSON response. * @param p_Request HTTP request handle * @param p_JSON JSON object to send - * @param status_code HTTP status code + * @param StatusCode HTTP status code * @return ESP_OK on success */ -static esp_err_t HTTP_Server_SendJSON(httpd_req_t *p_Request, cJSON *p_JSON, int status_code) +static esp_err_t HTTP_Server_SendJSON(httpd_req_t *p_Request, cJSON *p_JSON, int StatusCode) { esp_err_t Error; @@ -86,15 +88,15 @@ static esp_err_t HTTP_Server_SendJSON(httpd_req_t *p_Request, cJSON *p_JSON, int return ESP_FAIL; } - if (status_code != 200) { + if (StatusCode != 200) { char status_str[16]; - snprintf(status_str, sizeof(status_str), "%d", status_code); + snprintf(status_str, sizeof(status_str), "%d", StatusCode); httpd_resp_set_status(p_Request, status_str); } httpd_resp_set_type(p_Request, "application/json"); - if (_HTTPServer_State.Config.enable_cors) { + if (_HTTPServer_State.Config.EnableCORS) { httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Origin", "*"); } @@ -106,19 +108,24 @@ static esp_err_t HTTP_Server_SendJSON(httpd_req_t *p_Request, cJSON *p_JSON, int /** @brief Send error response. * @param p_Request HTTP request handle - * @param status_code HTTP status code + * @param StatusCode HTTP status code * @param p_Message Error message * @return ESP_OK on success */ -static esp_err_t HTTP_Server_SendError(httpd_req_t *p_Request, int status_code, const char *p_Message) +static esp_err_t HTTP_Server_SendError(httpd_req_t *p_Request, int StatusCode, const char *p_Message) { esp_err_t Error; cJSON *Json = cJSON_CreateObject(); + if(Json == NULL) { + httpd_resp_send_err(p_Request, HTTPD_500_INTERNAL_SERVER_ERROR, "JSON allocation failed"); + return ESP_FAIL; + } + cJSON_AddStringToObject(Json, "error", p_Message); - cJSON_AddNumberToObject(Json, "code", status_code); + cJSON_AddNumberToObject(Json, "code", StatusCode); - Error = HTTP_Server_SendJSON(p_Request, Json, status_code); + Error = HTTP_Server_SendJSON(p_Request, Json, StatusCode); cJSON_Delete(Json); return Error; @@ -188,9 +195,9 @@ static esp_err_t HTTP_Handler_Time(httpd_req_t *p_Request) settimeofday(&tv, NULL); /* Set timezone if provided */ - if (cJSON_IsString(timezone) && timezone->valuestring != NULL) { - setenv("TZ", timezone->valuestring, 1); - tzset(); + if (cJSON_IsString(timezone) && (timezone->valuestring != NULL)) { + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SET_TZ, (void *)timezone->valuestring, strlen(timezone->valuestring) + 1, + portMAX_DELAY); } ESP_LOGI(TAG, "Time set to epoch: %f", epoch->valuedouble); @@ -214,22 +221,18 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) { esp_err_t Error; Network_Encoded_Image_t encoded; + char query[128] = {0}; + Network_ImageFormat_t format = NETWORK_IMAGE_FORMAT_JPEG; + Server_Palette_t palette = PALETTE_IRON; _HTTPServer_State.RequestCount++; if (HTTP_Server_CheckAuth(p_Request) == false) { return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); - } - - if (_HTTPServer_State.ThermalFrame == NULL) { + } else if (_HTTPServer_State.ThermalFrame == NULL) { return HTTP_Server_SendError(p_Request, 503, "No thermal data available"); } - /* Parse query parameters */ - char query[128] = {0}; - Network_ImageFormat_t format = NETWORK_IMAGE_FORMAT_JPEG; - Server_Palette_t palette = PALETTE_IRON; - if (httpd_req_get_url_query_str(p_Request, query, sizeof(query)) == ESP_OK) { char param[32]; if (httpd_query_key_value(query, "format", param, sizeof(param)) == ESP_OK) { @@ -248,7 +251,6 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) } } - /* Lock frame data */ if (xSemaphoreTake(_HTTPServer_State.ThermalFrame->mutex, 100 / portTICK_PERIOD_MS) != pdTRUE) { return HTTP_Server_SendError(p_Request, 503, "Frame busy"); } @@ -275,7 +277,7 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) break; } - if (_HTTPServer_State.Config.enable_cors) { + if (_HTTPServer_State.Config.EnableCORS) { httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Origin", "*"); } @@ -312,10 +314,6 @@ static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) cJSON_AddNumberToObject(json, "sensor_temp_c", _HTTPServer_State.ThermalFrame->temp_avg); } - /* Core temperature (ESP32 internal) */ - /* Note: ESP32 doesn't have a direct internal temp sensor API, use 0 as placeholder */ - cJSON_AddNumberToObject(json, "core_temp_c", 0); - /* Supply voltage (placeholder) */ cJSON_AddNumberToObject(json, "supply_voltage_v", 0); @@ -500,15 +498,17 @@ static const httpd_uri_t _URI_Options = { esp_err_t HTTP_Server_Init(const Server_Config_t *p_Config) { + esp_err_t Error; + if (p_Config == NULL) { return ESP_ERR_INVALID_ARG; - } - - if (_HTTPServer_State.isInitialized) { + } else if (_HTTPServer_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); return ESP_OK; } + Error = ESP_OK; + ESP_LOGI(TAG, "Initializing HTTP server"); memcpy(&_HTTPServer_State.Config, p_Config, sizeof(Server_Config_t)); @@ -517,7 +517,7 @@ esp_err_t HTTP_Server_Init(const Server_Config_t *p_Config) _HTTPServer_State.RequestCount = 0; _HTTPServer_State.isInitialized = true; - return ESP_OK; + return Error; } void HTTP_Server_Deinit(void) @@ -536,20 +536,18 @@ esp_err_t HTTP_Server_Start(void) { if (_HTTPServer_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } - - if (_HTTPServer_State.isRunning) { + } else if (_HTTPServer_State.isRunning) { ESP_LOGW(TAG, "Server already running"); return ESP_OK; } httpd_config_t config = HTTPD_DEFAULT_CONFIG(); - config.server_port = _HTTPServer_State.Config.http_port; + config.server_port = _HTTPServer_State.Config.HTTP_Port; config.max_uri_handlers = 16; - config.max_open_sockets = _HTTPServer_State.Config.max_clients; + config.max_open_sockets = _HTTPServer_State.Config.MaxClients; config.lru_purge_enable = true; config.uri_match_fn = httpd_uri_match_wildcard; - + /* WebSocket stability configuration */ config.recv_wait_timeout = 120; /* Increase receive timeout to 120 seconds */ config.send_wait_timeout = 120; /* Increase send timeout to 120 seconds */ @@ -557,7 +555,7 @@ esp_err_t HTTP_Server_Start(void) config.keep_alive_idle = 60; /* Start keep-alive after 60s of idle */ config.keep_alive_interval = 10; /* Send keep-alive probes every 10s */ config.keep_alive_count = 3; /* Close connection after 3 failed probes */ - + /* Increase stack size for handling large WebSocket frames */ config.stack_size = 8192; /* Increase from default 4096 to handle JPEG encoding */ config.max_resp_headers = 16; /* Increase header limit */ @@ -576,7 +574,7 @@ esp_err_t HTTP_Server_Start(void) httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Telemetry); httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Update); - if (_HTTPServer_State.Config.enable_cors) { + if (_HTTPServer_State.Config.EnableCORS) { httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Options); } @@ -613,7 +611,6 @@ bool HTTP_Server_isRunning(void) void HTTP_Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) { - /* Consider adding synchronization if called from different contexts */ _HTTPServer_State.ThermalFrame = p_Frame; } diff --git a/main/Application/Manager/Network/Server/image_encoder.cpp b/main/Application/Manager/Network/Server/image_encoder.cpp index 34f9bd8..30e01f4 100644 --- a/main/Application/Manager/Network/Server/image_encoder.cpp +++ b/main/Application/Manager/Network/Server/image_encoder.cpp @@ -67,13 +67,11 @@ static esp_err_t Image_Encoder_ApplyPalette(const Network_Thermal_Frame_t *p_Fra Server_Palette_t palette, uint8_t *p_Output) { - if (p_Frame == NULL || p_Output == NULL || p_Frame->buffer == NULL) { + if ((p_Frame == NULL) || (p_Output == NULL) || (p_Frame->buffer == NULL)) { return ESP_ERR_INVALID_ARG; } - /* Frame already contains RGB888 data with palette applied by Lepton task */ - size_t buffer_size = p_Frame->width * p_Frame->height * 3; - memcpy(p_Output, p_Frame->buffer, buffer_size); + memcpy(p_Output, p_Frame->buffer, p_Frame->width * p_Frame->height * 3); return ESP_OK; } @@ -89,7 +87,6 @@ static esp_err_t Image_Encoder_ApplyPalette(const Network_Thermal_Frame_t *p_Fra static esp_err_t Image_Encoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, uint16_t height, uint8_t quality, Network_Encoded_Image_t *p_Encoded) { - /* Configure JPEG encoder */ jpeg_enc_config_t enc_config = { .width = width, .height = height, @@ -105,34 +102,26 @@ static esp_err_t Image_Encoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, jpeg_enc_handle_t encoder = NULL; jpeg_error_t err = jpeg_enc_open(&enc_config, &encoder); if (err != JPEG_ERR_OK) { - ESP_LOGE(TAG, "Failed to open JPEG encoder: %d", err); + ESP_LOGE(TAG, "Failed to open JPEG encoder: %d!", err); return ESP_FAIL; } - - /* Allocate output buffer (estimate max size) */ - size_t max_size = width * height * 3; - p_Encoded->data = (uint8_t *)heap_caps_malloc(max_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (p_Encoded->data == NULL) { - p_Encoded->data = (uint8_t *)malloc(max_size); - } - + ; + p_Encoded->data = (uint8_t *)heap_caps_malloc(width * height * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (p_Encoded->data == NULL) { jpeg_enc_close(encoder); - ESP_LOGE(TAG, "Failed to allocate JPEG output buffer"); + ESP_LOGE(TAG, "Failed to allocate JPEG output buffer!"); return ESP_ERR_NO_MEM; } - /* Encode image */ int out_size = 0; - size_t input_size = width * height * 3; - err = jpeg_enc_process(encoder, p_RGB, input_size, p_Encoded->data, max_size, &out_size); + err = jpeg_enc_process(encoder, p_RGB, width * height * 3, p_Encoded->data, width * height * 3, &out_size); jpeg_enc_close(encoder); if (err != JPEG_ERR_OK) { - free(p_Encoded->data); + heap_caps_free(p_Encoded->data); p_Encoded->data = NULL; - ESP_LOGE(TAG, "JPEG encoding failed: %d", err); + ESP_LOGE(TAG, "JPEG encoding failed: %d!", err); return ESP_FAIL; } @@ -144,19 +133,20 @@ static esp_err_t Image_Encoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, return ESP_OK; } -esp_err_t Image_Encoder_Init(uint8_t quality) +esp_err_t Image_Encoder_Init(uint8_t Quality) { if (_Encoder_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); return ESP_OK; } - ESP_LOGI(TAG, "Initializing image encoder, quality=%d", quality); + ESP_LOGI(TAG, "Initializing image encoder, quality=%d", Quality); - _Encoder_State.JpegQuality = quality; + _Encoder_State.JpegQuality = Quality; if (_Encoder_State.JpegQuality < 1) { _Encoder_State.JpegQuality = 1; } + if (_Encoder_State.JpegQuality > 100) { _Encoder_State.JpegQuality = 100; } @@ -178,10 +168,12 @@ void Image_Encoder_Deinit(void) } esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, - Network_ImageFormat_t format, - Server_Palette_t palette, + Network_ImageFormat_t Format, + Server_Palette_t Palette, Network_Encoded_Image_t *p_Encoded) { + esp_err_t Error; + if ((p_Frame == NULL) || (p_Encoded == NULL)) { return ESP_ERR_INVALID_ARG; } @@ -189,52 +181,46 @@ esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, memset(p_Encoded, 0, sizeof(Network_Encoded_Image_t)); size_t pixel_count = p_Frame->width * p_Frame->height; - size_t rgb_size = pixel_count * 3; - - /* Allocate RGB buffer */ - uint8_t *rgb_buffer = (uint8_t *)heap_caps_malloc(rgb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (rgb_buffer == NULL) { - rgb_buffer = (uint8_t *)malloc(rgb_size); - } + uint8_t *rgb_buffer = (uint8_t *)heap_caps_malloc(pixel_count * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (rgb_buffer == NULL) { - ESP_LOGE(TAG, "Failed to allocate RGB buffer"); + ESP_LOGE(TAG, "Failed to allocate RGB buffer!"); return ESP_ERR_NO_MEM; } - /* Apply color palette */ - esp_err_t err = Image_Encoder_ApplyPalette(p_Frame, palette, rgb_buffer); - if (err != ESP_OK) { - free(rgb_buffer); - return err; + Error = Image_Encoder_ApplyPalette(p_Frame, Palette, rgb_buffer); + if (Error != ESP_OK) { + heap_caps_free(rgb_buffer); + return Error; } - /* Encode based on format */ - switch (format) { - case NETWORK_IMAGE_FORMAT_JPEG: - err = Image_Encoder_EncodeJPEG(rgb_buffer, p_Frame->width, p_Frame->height, - _Encoder_State.JpegQuality, p_Encoded); + switch (Format) { + case NETWORK_IMAGE_FORMAT_JPEG: { + Error = Image_Encoder_EncodeJPEG(rgb_buffer, p_Frame->width, p_Frame->height, + _Encoder_State.JpegQuality, p_Encoded); break; - - case NETWORK_IMAGE_FORMAT_PNG: + } + case NETWORK_IMAGE_FORMAT_PNG: { /* PNG not implemented - fall through to RAW */ ESP_LOGW(TAG, "PNG format not implemented, using RAW"); - /* Fall through */ - + /* Fall through */ + } case NETWORK_IMAGE_FORMAT_RAW: - default: + default: { /* Return raw RGB data */ p_Encoded->data = rgb_buffer; - p_Encoded->size = rgb_size; + p_Encoded->size = pixel_count * 3; p_Encoded->format = NETWORK_IMAGE_FORMAT_RAW; p_Encoded->width = p_Frame->width; p_Encoded->height = p_Frame->height; + return ESP_OK; + } } - free(rgb_buffer); + heap_caps_free(rgb_buffer); - return err; + return Error; } void Image_Encoder_Free(Network_Encoded_Image_t *p_Encoded) @@ -244,19 +230,20 @@ void Image_Encoder_Free(Network_Encoded_Image_t *p_Encoded) } if (p_Encoded->data != NULL) { - free(p_Encoded->data); + heap_caps_free(p_Encoded->data); p_Encoded->data = NULL; } p_Encoded->size = 0; } -void Image_Encoder_SetQuality(uint8_t quality) +void Image_Encoder_SetQuality(uint8_t Quality) { - _Encoder_State.JpegQuality = quality; + _Encoder_State.JpegQuality = Quality; if (_Encoder_State.JpegQuality < 1) { _Encoder_State.JpegQuality = 1; } + if (_Encoder_State.JpegQuality > 100) { _Encoder_State.JpegQuality = 100; } diff --git a/main/Application/Manager/Network/Server/image_encoder.h b/main/Application/Manager/Network/Server/image_encoder.h index dac5ddb..8f837da 100644 --- a/main/Application/Manager/Network/Server/image_encoder.h +++ b/main/Application/Manager/Network/Server/image_encoder.h @@ -29,25 +29,25 @@ #include "../network_types.h" /** @brief Initialize the image encoder. - * @param quality JPEG quality (1-100) + * @param Quality JPEG quality (1-100) * @return ESP_OK on success */ -esp_err_t Image_Encoder_Init(uint8_t quality); +esp_err_t Image_Encoder_Init(uint8_t Quality); /** @brief Deinitialize the image encoder. */ void Image_Encoder_Deinit(void); -/** @brief Encode a thermal frame to the specified format. - * @param p_Frame Pointer to thermal frame data - * @param format Output image format - * @param palette Color palette to use - * @param p_Encoded Pointer to store encoded image data - * @return ESP_OK on success +/** @brief Encode a thermal frame to the specified format. + * @param p_Frame Pointer to thermal frame data + * @param Format Output image format + * @param Palette Color palette to use + * @param p_Encoded Pointer to store encoded image data + * @return ESP_OK on success */ esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, - Network_ImageFormat_t format, - Server_Palette_t palette, + Network_ImageFormat_t Format, + Server_Palette_t Palette, Network_Encoded_Image_t *p_Encoded); /** @brief Free encoded image data. @@ -55,9 +55,9 @@ esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, */ void Image_Encoder_Free(Network_Encoded_Image_t *p_Encoded); -/** @brief Set JPEG encoding quality. - * @param quality Quality value (1-100) +/** @brief Set JPEG encoding quality. + * @param Quality Quality value (1-100) */ -void Image_Encoder_SetQuality(uint8_t quality); +void Image_Encoder_SetQuality(uint8_t Quality); #endif /* IMAGE_ENCODER_H_ */ diff --git a/main/Application/Manager/Network/Server/websocket_handler.cpp b/main/Application/Manager/Network/Server/websocket_handler.cpp index da464f3..2194b2f 100644 --- a/main/Application/Manager/Network/Server/websocket_handler.cpp +++ b/main/Application/Manager/Network/Server/websocket_handler.cpp @@ -67,12 +67,16 @@ static const char *TAG = "websocket_handler"; */ static WS_Client_t *WS_FindClient(int FD) { + xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { if (_WSHandler_State.Clients[i].active && _WSHandler_State.Clients[i].fd == FD) { return &_WSHandler_State.Clients[i]; } } + xSemaphoreGive(_WSHandler_State.ClientsMutex); + return NULL; } @@ -188,24 +192,24 @@ static esp_err_t WS_SendBinary(int FD, const uint8_t *p_Data, size_t Length) esp_err_t err = ESP_FAIL; for (uint8_t retry = 0; retry < 3; retry++) { err = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &Frame); - + if (err == ESP_OK) { /* Send queued successfully - add small delay to prevent queue overflow */ vTaskDelay(5 / portTICK_PERIOD_MS); break; } - + /* Queue might be full, wait and retry */ - ESP_LOGW(TAG, "Failed to queue frame to fd=%d (retry %d): %s", + ESP_LOGW(TAG, "Failed to queue frame to fd=%d (retry %d): %s", FD, retry + 1, esp_err_to_name(err)); vTaskDelay(50 / portTICK_PERIOD_MS); } - + if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to send binary frame to fd=%d after retries: %s (len=%zu)", + ESP_LOGE(TAG, "Failed to send binary frame to fd=%d after retries: %s (len=%zu)", FD, esp_err_to_name(err), Length); } - + return err; } @@ -220,8 +224,12 @@ static void WS_HandleStart(WS_Client_t *p_Client, cJSON *p_Data) /* Set FPS (default 8) */ if (cJSON_IsNumber(fps)) { p_Client->stream_fps = (uint8_t)fps->valueint; - if (p_Client->stream_fps < 1) p_Client->stream_fps = 1; - if (p_Client->stream_fps > 30) p_Client->stream_fps = 30; + if (p_Client->stream_fps < 1) { + p_Client->stream_fps = 1; + } + if (p_Client->stream_fps > 30) { + p_Client->stream_fps = 30; + } } /* Always use JPEG format for simplicity and efficiency */ @@ -419,7 +427,7 @@ static esp_err_t WS_Handler(httpd_req_t *p_Request) /* Pong fails sometimes. So we simply try again */ vTaskDelay(10 / portTICK_PERIOD_MS); Error = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &pong_frame); - if(Error != ESP_OK) { + if (Error != ESP_OK) { ESP_LOGW(TAG, "Failed to send Pong to fd=%d again: %d, removing client!", FD, Error); WS_RemoveClient(FD); } @@ -597,7 +605,6 @@ static void WS_BroadcastTask(void *p_Param) /* Send to all active streaming clients */ xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); - for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { WS_Client_t *client = &_WSHandler_State.Clients[i]; @@ -606,27 +613,28 @@ static void WS_BroadcastTask(void *p_Param) } /* Check frame rate limit */ - uint32_t frame_interval = 1000 / client->stream_fps; - if ((Now - client->last_frame_time) < frame_interval) { + if ((Now - client->last_frame_time) < (1000 / client->stream_fps)) { continue; } - /* Release mutex during send to avoid blocking other operations */ - xSemaphoreGive(_WSHandler_State.ClientsMutex); + /* Copy FD before releasing mutex */ + int client_fd = client->fd; + uint8_t client_idx = i; - /* Send frame to this client */ - esp_err_t send_err = WS_SendBinary(client->fd, Encoded.data, Encoded.size); - - /* Re-acquire mutex to update state */ + xSemaphoreGive(_WSHandler_State.ClientsMutex); + esp_err_t send_err = WS_SendBinary(client_fd, Encoded.data, Encoded.size); xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); - if (send_err == ESP_OK) { - client->last_frame_time = Now; - } else { - /* Send failed - remove client */ - ESP_LOGW(TAG, "Removing client fd=%d due to send failure", client->fd); - client->active = false; - _WSHandler_State.ClientCount--; + /* Re-validate client is still active and same FD */ + if (_WSHandler_State.Clients[client_idx].active && + _WSHandler_State.Clients[client_idx].fd == client_fd) { + if (send_err == ESP_OK) { + _WSHandler_State.Clients[client_idx].last_frame_time = Now; + } else { + ESP_LOGW(TAG, "Removing client fd=%d due to send failure", client_fd); + _WSHandler_State.Clients[client_idx].active = false; + _WSHandler_State.ClientCount--; + } } } @@ -641,6 +649,7 @@ static void WS_BroadcastTask(void *p_Param) } ESP_LOGI(TAG, "WebSocket broadcast task stopped"); + _WSHandler_State.BroadcastTask = NULL; vTaskDelete(NULL); } diff --git a/main/Application/Manager/Network/networkManager.cpp b/main/Application/Manager/Network/networkManager.cpp index 67f6474..daf9cbd 100644 --- a/main/Application/Manager/Network/networkManager.cpp +++ b/main/Application/Manager/Network/networkManager.cpp @@ -54,14 +54,11 @@ ESP_EVENT_DEFINE_BASE(NETWORK_EVENTS); typedef struct { bool isInitialized; Network_State_t State; - Network_WiFiMode_t mode; esp_netif_t *STA_NetIF; esp_netif_t *AP_NetIF; EventGroupHandle_t EventGroup; - Network_WiFi_STA_Config_t STA_Config; - Network_WiFi_AP_Config_t AP_Config; + Network_WiFi_STA_Config_t *STA_Config; uint8_t RetryCount; - uint8_t Retries; esp_netif_ip_info_t IP_Info; } Network_Manager_State_t; @@ -194,17 +191,17 @@ static void on_WiFi_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID /* Special handling for "No AP found" */ if (Event->reason == WIFI_REASON_NO_AP_FOUND) { ESP_LOGW(TAG, "AP '%s' not found - check SSID spelling, signal strength, or if AP is on 2.4GHz band", - _Network_Manager_State.STA_Config.ssid); + _Network_Manager_State.STA_Config->Credentials.SSID); } _Network_Manager_State.State = NETWORK_STATE_DISCONNECTED; esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_WIFI_DISCONNECTED, p_Data, sizeof(wifi_event_sta_disconnected_t), portMAX_DELAY); - if (_Network_Manager_State.RetryCount < _Network_Manager_State.Retries) { - ESP_LOGD(TAG, "Retry %d/%d", _Network_Manager_State.RetryCount++, _Network_Manager_State.Retries); + if (_Network_Manager_State.RetryCount < _Network_Manager_State.STA_Config->MaxRetries) { + ESP_LOGD(TAG, "Retry %d/%d", _Network_Manager_State.RetryCount++, _Network_Manager_State.STA_Config->MaxRetries); - vTaskDelay(_Network_Manager_State.STA_Config.retry_interval_ms / portTICK_PERIOD_MS); + vTaskDelay(_Network_Manager_State.STA_Config->RetryInterval / portTICK_PERIOD_MS); esp_wifi_connect(); _Network_Manager_State.State = NETWORK_STATE_CONNECTING; } else { @@ -292,7 +289,7 @@ static void on_IP_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, } } -esp_err_t NetworkManager_Init(const Network_Config_t *p_Config) +esp_err_t NetworkManager_Init(Network_WiFi_STA_Config_t *p_Config) { esp_err_t Error; @@ -307,6 +304,9 @@ esp_err_t NetworkManager_Init(const Network_Config_t *p_Config) ESP_LOGD(TAG, "Initializing WiFi Manager"); + /* Initialize TCP/IP stack */ + ESP_ERROR_CHECK(esp_netif_init()); + /* Create event group */ _Network_Manager_State.EventGroup = xEventGroupCreate(); if (_Network_Manager_State.EventGroup == NULL) { @@ -314,14 +314,8 @@ esp_err_t NetworkManager_Init(const Network_Config_t *p_Config) return ESP_ERR_NO_MEM; } - /* Initialize TCP/IP stack */ - ESP_ERROR_CHECK(esp_netif_init()); - /* Copy configuration */ - memcpy(&_Network_Manager_State.STA_Config, &p_Config->STA_Config, sizeof(Network_WiFi_STA_Config_t)); - memcpy(&_Network_Manager_State.AP_Config, &p_Config->AP_Config, sizeof(Network_WiFi_AP_Config_t)); - _Network_Manager_State.mode = p_Config->WiFi_Mode; - _Network_Manager_State.Retries = _Network_Manager_State.STA_Config.max_retries; + _Network_Manager_State.STA_Config = p_Config; /* Create network interfaces */ _Network_Manager_State.STA_NetIF = esp_netif_create_default_wifi_sta(); @@ -427,107 +421,21 @@ esp_err_t NetworkManager_StartSTA(void) xEventGroupClearBits(_Network_Manager_State.EventGroup, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT); ESP_LOGI(TAG, "Starting WiFi in STA mode"); - ESP_LOGI(TAG, "Connecting to SSID: %s", _Network_Manager_State.STA_Config.ssid); + ESP_LOGI(TAG, "Connecting to SSID: %s", _Network_Manager_State.STA_Config->Credentials.SSID); memset(&WifiConfig, 0, sizeof(wifi_config_t)); WifiConfig.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; WifiConfig.sta.pmf_cfg.capable = true; WifiConfig.sta.pmf_cfg.required = false; - strncpy((char *)WifiConfig.sta.ssid, _Network_Manager_State.STA_Config.ssid, sizeof(WifiConfig.sta.ssid) - 1); - strncpy((char *)WifiConfig.sta.password, _Network_Manager_State.STA_Config.password, + strncpy((char *)WifiConfig.sta.ssid, _Network_Manager_State.STA_Config->Credentials.SSID, + sizeof(WifiConfig.sta.ssid) - 1); + strncpy((char *)WifiConfig.sta.password, _Network_Manager_State.STA_Config->Credentials.Password, sizeof(WifiConfig.sta.password) - 1); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &WifiConfig)); ESP_ERROR_CHECK(esp_wifi_start()); - _Network_Manager_State.mode = NETWORK_WIFI_MODE_STA; - _Network_Manager_State.State = NETWORK_STATE_CONNECTING; - - return ESP_OK; -} - -esp_err_t NetworkManager_StartAP(void) -{ - wifi_config_t WifiConfig; - - if (_Network_Manager_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } - - ESP_LOGD(TAG, "Starting WiFi in AP mode"); - memset(&WifiConfig, 0, sizeof(wifi_config_t)); - WifiConfig.ap.channel = _Network_Manager_State.AP_Config.channel; - WifiConfig.ap.max_connection = _Network_Manager_State.AP_Config.max_connections; - WifiConfig.ap.authmode = WIFI_AUTH_WPA2_PSK; - WifiConfig.ap.ssid_hidden = _Network_Manager_State.AP_Config.hidden ? 1 : 0; - strncpy((char *)WifiConfig.ap.ssid, _Network_Manager_State.AP_Config.ssid, sizeof(WifiConfig.ap.ssid) - 1); - WifiConfig.ap.ssid_len = strlen(_Network_Manager_State.AP_Config.ssid); - - if (strlen(_Network_Manager_State.AP_Config.password) < 8) { - WifiConfig.ap.authmode = WIFI_AUTH_OPEN; - } else { - strncpy((char *)WifiConfig.ap.password, _Network_Manager_State.AP_Config.password, - sizeof(WifiConfig.ap.password) - 1); - } - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &WifiConfig)); - ESP_ERROR_CHECK(esp_wifi_start()); - - _Network_Manager_State.mode = NETWORK_WIFI_MODE_AP; - _Network_Manager_State.State = NETWORK_STATE_AP_STARTED; - - /* Get AP IP info */ - esp_netif_get_ip_info(_Network_Manager_State.AP_NetIF, &_Network_Manager_State.IP_Info); - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STARTED, NULL, 0, portMAX_DELAY); - ESP_LOGD(TAG, "AP started. SSID: %s, IP: " IPSTR, - _Network_Manager_State.AP_Config.ssid, IP2STR(&_Network_Manager_State.IP_Info.ip)); - - return ESP_OK; -} - -esp_err_t NetworkManager_StartAPSTA(void) -{ - wifi_config_t STA_Config; - wifi_config_t AP_Config; - - if (_Network_Manager_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } - - ESP_LOGD(TAG, "Starting WiFi in AP+STA mode"); - - /* Configure STA */ - memset(&STA_Config, 0, sizeof(wifi_config_t)); - STA_Config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; - STA_Config.sta.pmf_cfg.capable = true; - STA_Config.sta.pmf_cfg.required = false; - strncpy((char *)STA_Config.sta.ssid, _Network_Manager_State.STA_Config.ssid, sizeof(STA_Config.sta.ssid) - 1); - strncpy((char *)STA_Config.sta.password, _Network_Manager_State.STA_Config.password, - sizeof(STA_Config.sta.password) - 1); - - /* Configure AP */ - memset(&AP_Config, 0, sizeof(wifi_config_t)); - AP_Config.ap.channel = _Network_Manager_State.AP_Config.channel; - AP_Config.ap.max_connection = _Network_Manager_State.AP_Config.max_connections; - AP_Config.ap.authmode = WIFI_AUTH_WPA2_PSK; - AP_Config.ap.ssid_hidden = _Network_Manager_State.AP_Config.hidden ? 1 : 0; - strncpy((char *)AP_Config.ap.ssid, _Network_Manager_State.AP_Config.ssid, sizeof(AP_Config.ap.ssid) - 1); - AP_Config.ap.ssid_len = strlen(_Network_Manager_State.AP_Config.ssid); - - if (strlen(_Network_Manager_State.AP_Config.password) < 8) { - AP_Config.ap.authmode = WIFI_AUTH_OPEN; - } else { - strncpy((char *)AP_Config.ap.password, _Network_Manager_State.AP_Config.password, sizeof(AP_Config.ap.password) - 1); - } - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &STA_Config)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &AP_Config)); - ESP_ERROR_CHECK(esp_wifi_start()); - - _Network_Manager_State.mode = NETWORK_WIFI_MODE_APSTA; _Network_Manager_State.State = NETWORK_STATE_CONNECTING; return ESP_OK; @@ -535,10 +443,8 @@ esp_err_t NetworkManager_StartAPSTA(void) esp_err_t NetworkManager_StartServer(Server_Config_t *p_Config) { - Server_Init(p_Config); - Server_Start(); - - /* Broadcast task will handle frame broadcasting automatically */ + ESP_ERROR_CHECK(Server_Init(p_Config)); + ESP_ERROR_CHECK(Server_Start()); return ESP_OK; } @@ -565,11 +471,13 @@ esp_err_t NetworkManager_ConnectWiFi(const char *p_SSID, const char *p_Password) } if (p_SSID != NULL) { - strncpy(_Network_Manager_State.STA_Config.ssid, p_SSID, sizeof(_Network_Manager_State.STA_Config.ssid) - 1); + strncpy(_Network_Manager_State.STA_Config->Credentials.SSID, p_SSID, + sizeof(_Network_Manager_State.STA_Config->Credentials.SSID) - 1); } if (p_Password != NULL) { - strncpy(_Network_Manager_State.STA_Config.password, p_Password, sizeof(_Network_Manager_State.STA_Config.password) - 1); + strncpy(_Network_Manager_State.STA_Config->Credentials.Password, p_Password, + sizeof(_Network_Manager_State.STA_Config->Credentials.Password) - 1); } /* Restart the WiFi connection with the new credentials */ @@ -584,10 +492,10 @@ esp_err_t NetworkManager_ConnectWiFi(const char *p_SSID, const char *p_Password) 30000 / portTICK_PERIOD_MS); if (Bits & WIFI_CONNECTED_BIT) { - ESP_LOGD(TAG, "Connected to SSID: %s!", _Network_Manager_State.STA_Config.ssid); + ESP_LOGD(TAG, "Connected to SSID: %s!", _Network_Manager_State.STA_Config->Credentials.SSID); return ESP_OK; } else if (Bits & WIFI_FAIL_BIT) { - ESP_LOGE(TAG, "Failed to connect to SSID: %s!", _Network_Manager_State.STA_Config.ssid); + ESP_LOGE(TAG, "Failed to connect to SSID: %s!", _Network_Manager_State.STA_Config->Credentials.SSID); return ESP_FAIL; } else { ESP_LOGE(TAG, "Connection timeout!"); @@ -651,109 +559,23 @@ esp_err_t NetworkManager_GetMAC(uint8_t *p_MAC) return esp_wifi_get_mac(WIFI_IF_STA, p_MAC); } -esp_err_t NetworkManager_SetCredentials(const char *p_SSID, const char *p_Password) +esp_err_t NetworkManager_SetCredentials(Network_WiFi_Credentials_t *p_Credentials) { - if (p_SSID == NULL) { + if (p_Credentials == NULL) { return ESP_ERR_INVALID_ARG; } - strncpy(_Network_Manager_State.STA_Config.ssid, p_SSID, sizeof(_Network_Manager_State.STA_Config.ssid) - 1); - if (p_Password != NULL) { - strncpy(_Network_Manager_State.STA_Config.password, p_Password, sizeof(_Network_Manager_State.STA_Config.password) - 1); + strncpy(_Network_Manager_State.STA_Config->Credentials.SSID, p_Credentials->SSID, + sizeof(_Network_Manager_State.STA_Config->Credentials.SSID) - 1); + if (strlen(p_Credentials->Password) != 0) { + strncpy(_Network_Manager_State.STA_Config->Credentials.Password, p_Credentials->Password, + sizeof(_Network_Manager_State.STA_Config->Credentials.Password) - 1); } else { - _Network_Manager_State.STA_Config.password[0] = '\0'; + _Network_Manager_State.STA_Config->Credentials.Password[0] = '\0'; } - return ESP_OK; -} - -esp_err_t NetworkManager_SaveCredentials(void) -{ - nvs_handle_t Handle; - esp_err_t Error; - - Error = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &Handle); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to open NVS: %d!", Error); - return Error; - } - - Error = nvs_set_str(Handle, NVS_KEY_SSID, _Network_Manager_State.STA_Config.ssid); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to save SSID: %d!", Error); - nvs_close(Handle); - return Error; - } - - Error = nvs_set_str(Handle, NVS_KEY_PASSWORD, _Network_Manager_State.STA_Config.password); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to save password: %d!", Error); - nvs_close(Handle); - return Error; - } - - Error = nvs_commit(Handle); - nvs_close(Handle); - - ESP_LOGD(TAG, "Credentials saved to NVS"); - - return ESP_OK; -} - -esp_err_t NetworkManager_LoadCredentials(void) -{ - nvs_handle_t Handle; - esp_err_t Error; - size_t Length; - - Error = nvs_open(NVS_NAMESPACE, NVS_READONLY, &Handle); - if (Error != ESP_OK) { - ESP_LOGW(TAG, "No stored credentials found"); - return Error; - } - Length = sizeof(_Network_Manager_State.STA_Config.ssid); - - Error = nvs_get_str(Handle, NVS_KEY_SSID, _Network_Manager_State.STA_Config.ssid, &Length); - if (Error != ESP_OK) { - ESP_LOGW(TAG, "Failed to load SSID: %d!", Error); - nvs_close(Handle); - return Error; - } - Length = sizeof(_Network_Manager_State.STA_Config.password); - - Error = nvs_get_str(Handle, NVS_KEY_PASSWORD, _Network_Manager_State.STA_Config.password, &Length); - if (Error != ESP_OK) { - ESP_LOGW(TAG, "Failed to load password: %d!", Error); - nvs_close(Handle); - return Error; - } - - nvs_close(Handle); - - ESP_LOGD(TAG, "Credentials loaded from NVS. SSID: %s", _Network_Manager_State.STA_Config.ssid); - - return ESP_OK; -} - -esp_err_t NetworkManager_ClearCredentials(void) -{ - nvs_handle_t Handle; - esp_err_t Error; - - Error = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &Handle); - if (Error != ESP_OK) { - return Error; - } - - nvs_erase_key(Handle, NVS_KEY_SSID); - nvs_erase_key(Handle, NVS_KEY_PASSWORD); - nvs_commit(Handle); - nvs_close(Handle); - - _Network_Manager_State.STA_Config.ssid[0] = '\0'; - _Network_Manager_State.STA_Config.password[0] = '\0'; - - ESP_LOGD(TAG, "Credentials cleared"); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_CREDENTIALS_UPDATED, &_Network_Manager_State.STA_Config->Credentials, + sizeof(Network_WiFi_Credentials_t), portMAX_DELAY); return ESP_OK; } @@ -762,10 +584,6 @@ uint8_t NetworkManager_GetConnectedStations(void) { wifi_sta_list_t StaList; - if ((_Network_Manager_State.mode != NETWORK_WIFI_MODE_AP) && (_Network_Manager_State.mode != NETWORK_WIFI_MODE_APSTA)) { - return 0; - } - if (esp_wifi_ap_get_sta_list(&StaList) == ESP_OK) { return StaList.num; } diff --git a/main/Application/Manager/Network/networkManager.h b/main/Application/Manager/Network/networkManager.h index de147ab..67c30cf 100644 --- a/main/Application/Manager/Network/networkManager.h +++ b/main/Application/Manager/Network/networkManager.h @@ -34,10 +34,10 @@ #include "Provisioning/provisioning.h" /** @brief Initialize the Network Manager. - * @param config Pointer to WiFi configuration + * @param p_Config Pointer to WiFi configuration * @return ESP_OK on success */ -esp_err_t NetworkManager_Init(const Network_Config_t *p_Config); +esp_err_t NetworkManager_Init(Network_WiFi_STA_Config_t *p_Config); /** @brief Deinitialize the Network Manager. */ @@ -48,16 +48,6 @@ void NetworkManager_Deinit(void); */ esp_err_t NetworkManager_StartSTA(void); -/** @brief Start WiFi in access point mode. - * @return ESP_OK on success - */ -esp_err_t NetworkManager_StartAP(void); - -/** @brief Start WiFi in AP+STA mode. - * @return ESP_OK on success - */ -esp_err_t NetworkManager_StartAPSTA(void); - /** @brief Stop Network Manager. * @return ESP_OK on success */ @@ -102,27 +92,11 @@ int8_t NetworkManager_GetRSSI(void); */ esp_err_t NetworkManager_GetMAC(uint8_t *p_MAC); -/** @brief Set WiFi credentials for station mode. - * @param p_SSID SSID - * @param p_Password Password - * @return ESP_OK on success - */ -esp_err_t NetworkManager_SetCredentials(const char *p_SSID, const char *p_Password); - -/** @brief Save WiFi credentials to NVS. - * @return ESP_OK on success - */ -esp_err_t NetworkManager_SaveCredentials(void); - -/** @brief Load WiFi credentials from NVS. - * @return ESP_OK on success - */ -esp_err_t NetworkManager_LoadCredentials(void); - -/** @brief Clear stored WiFi credentials. - * @return ESP_OK on success +/** @brief Set WiFi credentials for station mode. + * @param p_Credentials Pointer to credentials + * @return ESP_OK on success */ -esp_err_t NetworkManager_ClearCredentials(void); +esp_err_t NetworkManager_SetCredentials(Network_WiFi_Credentials_t *p_Credentials); /** @brief Get number of connected stations (AP mode). * @return Number of connected stations diff --git a/main/Application/Manager/Network/network_types.h b/main/Application/Manager/Network/network_types.h index 562a0a5..5886d1b 100644 --- a/main/Application/Manager/Network/network_types.h +++ b/main/Application/Manager/Network/network_types.h @@ -50,14 +50,6 @@ typedef enum { NETWORK_STATE_ERROR, } Network_State_t; -/** @brief WiFi operation mode. - */ -typedef enum { - NETWORK_WIFI_MODE_STA = 0, - NETWORK_WIFI_MODE_AP, - NETWORK_WIFI_MODE_APSTA, -} Network_WiFiMode_t; - /** @brief Provisioning method. */ typedef enum { @@ -82,6 +74,8 @@ typedef enum { NETWORK_EVENT_WIFI_DISCONNECTED, NETWORK_EVENT_WIFI_GOT_IP, /**< The device got an IP address Data is of type Network_IP_Info_t */ + NETWORK_EVENT_CREDENTIALS_UPDATED, /**< New WiFi credentials have been set + Data is of ... */ NETWORK_EVENT_AP_STARTED, NETWORK_EVENT_AP_STOPPED, NETWORK_EVENT_AP_STA_CONNECTED, @@ -92,8 +86,6 @@ typedef enum { NETWORK_EVENT_PROV_SUCCESS, NETWORK_EVENT_PROV_FAILED, NETWORK_EVENT_PROV_TIMEOUT, - NETWORK_EVENT_WS_CLIENT_CONNECTED, - NETWORK_EVENT_WS_CLIENT_DISCONNECTED, NETWORK_EVENT_OTA_STARTED, NETWORK_EVENT_OTA_PROGRESS, NETWORK_EVENT_OTA_COMPLETED, @@ -189,50 +181,29 @@ typedef struct { int client_fd; } Network_Event_WS_Client_t; -/** @brief WiFi station configuration. +/** @brief WiFi credentials. */ typedef struct { - char ssid[33]; - char password[65]; - uint8_t max_retries; - uint16_t retry_interval_ms; -} Network_WiFi_STA_Config_t; + char SSID[33]; + char Password[65]; +} Network_WiFi_Credentials_t; -/** @brief WiFi access point configuration. - */ -typedef struct { - char ssid[33]; - char password[65]; - uint8_t channel; - uint8_t max_connections; - bool hidden; -} Network_WiFi_AP_Config_t; - -/** @brief Network interface configuration. - */ -typedef struct { - Network_WiFiMode_t WiFi_Mode; - Network_WiFi_STA_Config_t STA_Config; - Network_WiFi_AP_Config_t AP_Config; - Network_ProvMethod_t Prov_Method; -} Network_Config_t; - -/** @brief LED control request. +/** @brief WiFi station configuration. */ typedef struct { - Server_LED_State_t state; - uint8_t brightness; - uint16_t blink_ms; -} Server_LED_Request_t; + Network_WiFi_Credentials_t Credentials; + uint8_t MaxRetries; + uint16_t RetryInterval; +} Network_WiFi_STA_Config_t; /** @brief Server configuration. */ typedef struct { - uint16_t http_port; - uint8_t max_clients; - uint16_t ws_ping_interval_sec; - bool enable_cors; - const char *api_key; + uint16_t HTTP_Port; + uint8_t MaxClients; + uint16_t WSPingIntervalSec; + bool EnableCORS; + const char *API_Key; } Server_Config_t; /** @brief Server status. diff --git a/main/Application/Manager/SD/sdManager.cpp b/main/Application/Manager/SD/sdManager.cpp index 949bb10..ef368b9 100644 --- a/main/Application/Manager/SD/sdManager.cpp +++ b/main/Application/Manager/SD/sdManager.cpp @@ -53,7 +53,7 @@ #if CONFIG_SD_CARD_PIN_CD > 0 #define SD_DEBOUNCE_TIME_MS 500 -#endif /* CONFIG_SD_CARD_PIN_CD */ +#endif #define SD_MOUNT_TASK_STACK 4096 #define SD_MOUNT_TASK_PRIORITY 3 @@ -105,11 +105,12 @@ static void IRAM_ATTR SDManager_CardDetectISR(void *p_Arg) /* Restart debounce timer on every edge - only triggers callback after stable period */ if (_SD_Manager_State.DebounceTimer != NULL) { + // TODO: Not IRAM save esp_timer_stop(_SD_Manager_State.DebounceTimer); esp_timer_start_once(_SD_Manager_State.DebounceTimer, SD_DEBOUNCE_TIME_MS * 1000); } } -#endif /* CONFIG_SD_CARD_PIN_CD */ +#endif esp_err_t SDManager_Init(void) { @@ -152,6 +153,8 @@ esp_err_t SDManager_Init(void) ESP_LOGI(TAG, "SD card filesystem mounted successfully"); #if CONFIG_SD_CARD_PIN_CD > 0 + esp_err_t Error; + /* Configure card detect pin with interrupt */ _SD_Manager_State.CD_Conf.intr_type = GPIO_INTR_ANYEDGE; _SD_Manager_State.CD_Conf.mode = GPIO_MODE_INPUT; @@ -207,7 +210,7 @@ esp_err_t SDManager_Init(void) _SD_Manager_State.CardPresent = false; } -#endif /* CONFIG_SD_CARD_PIN_CD */ +#endif _SD_Manager_State.isInitialized = true; diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index 57a66fa..a2fb7bb 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -65,18 +65,41 @@ static void _SettingsManager_InitDefaults(App_Settings_t *p_Settings) p_Settings->Version = SETTINGS_VERSION; - /* Lepton defaults */ - p_Settings->Lepton.SpotmeterROI.x = 40; - p_Settings->Lepton.SpotmeterROI.y = 40; - p_Settings->Lepton.SpotmeterROI.w = 80; - p_Settings->Lepton.SpotmeterROI.h = 40; + /* Spotmeter defaults */ + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].Type = ROI_TYPE_SPOTMETER; + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].x = 60; + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].y = 40; + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].w = 40; + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].h = 40; + + /* Scene statistics defaults */ + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].Type = ROI_TYPE_SCENE; + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].x = 0; + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].y = 0; + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].w = 160; + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].h = 120; + + /* AGC defaults */ + p_Settings->Lepton.ROI[ROI_TYPE_AGC].Type = ROI_TYPE_AGC; + p_Settings->Lepton.ROI[ROI_TYPE_AGC].x = 0; + p_Settings->Lepton.ROI[ROI_TYPE_AGC].y = 0; + p_Settings->Lepton.ROI[ROI_TYPE_AGC].w = 160; + p_Settings->Lepton.ROI[ROI_TYPE_AGC].h = 120; + + /* Video focus defaults */ + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].Type = ROI_TYPE_VIDEO_FOCUS; + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].x = 1; + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].y = 1; + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].w = 157; + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].h = 157; + + p_Settings->Lepton.EnableSceneStatistics = true; + p_Settings->Lepton.Emissivity = 95; /* WiFi defaults */ strncpy(p_Settings->WiFi.SSID, "", sizeof(p_Settings->WiFi.SSID)); strncpy(p_Settings->WiFi.Password, "", sizeof(p_Settings->WiFi.Password)); - p_Settings->WiFi.AP_Mode = false; - strncpy(p_Settings->WiFi.AP_SSID, "PyroVision", sizeof(p_Settings->WiFi.AP_SSID)); - strncpy(p_Settings->WiFi.AP_Password, "pyrovision123", sizeof(p_Settings->WiFi.AP_Password)); + p_Settings->WiFi.AutoConnect = true; /* Display defaults */ p_Settings->Display.Brightness = 80; @@ -84,7 +107,6 @@ static void _SettingsManager_InitDefaults(App_Settings_t *p_Settings) /* System defaults */ if (esp_efuse_mac_get_default(Mac) == ESP_OK) { - /* Append the MAC address to the device name */ snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision-%02X%02X%02X%02X%02X%02X", Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]); } else { @@ -110,14 +132,12 @@ esp_err_t SettingsManager_Init(void) ESP_ERROR_CHECK(nvs_flash_init()); - /* Create mutex for thread-safe access */ _State.Mutex = xSemaphoreCreateMutex(); if (_State.Mutex == NULL) { ESP_LOGE(TAG, "Failed to create mutex!"); return ESP_ERR_NO_MEM; } - /* Open NVS handle */ Error = nvs_open(SETTINGS_NVS_NAMESPACE, NVS_READWRITE, &_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to open NVS handle: %d!", Error); @@ -128,12 +148,10 @@ esp_err_t SettingsManager_Init(void) _State.isInitialized = true; _State.PendingChanges = false; - /* Load settings from NVS or use defaults */ Error = SettingsManager_Load(&_State.Settings); if (Error == ESP_ERR_NVS_NOT_FOUND) { ESP_LOGI(TAG, "No settings found, using factory defaults"); _SettingsManager_InitDefaults(&_State.Settings); - /* Save defaults to NVS */ SettingsManager_Save(&_State.Settings); } else if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to load settings: %d!", Error); @@ -142,7 +160,6 @@ esp_err_t SettingsManager_Init(void) ESP_LOGI(TAG, "Settings Manager initialized (version %lu)", _State.Settings.Version); - /* Post event to notify settings loaded */ esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_LOADED, &_State.Settings, sizeof(App_Settings_t), portMAX_DELAY); return ESP_OK; @@ -154,7 +171,6 @@ esp_err_t SettingsManager_Deinit(void) return ESP_OK; } - /* Commit any pending changes */ if (_State.PendingChanges) { SettingsManager_Commit(); } @@ -182,7 +198,6 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) xSemaphoreTake(_State.Mutex, portMAX_DELAY); - /* Check if settings blob exists */ Error = nvs_get_blob(_State.NVS_Handle, "settings", NULL, &RequiredSize); if (Error == ESP_ERR_NVS_NOT_FOUND) { xSemaphoreGive(_State.Mutex); @@ -193,7 +208,6 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) return Error; } - /* Verify size matches */ if (RequiredSize != sizeof(App_Settings_t)) { ESP_LOGW(TAG, "Settings size mismatch (expected %u, got %u), using defaults", sizeof(App_Settings_t), RequiredSize); @@ -201,7 +215,6 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) return ESP_ERR_INVALID_SIZE; } - /* Load settings blob */ Error = nvs_get_blob(_State.NVS_Handle, "settings", p_Settings, &RequiredSize); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to read settings: %d!", Error); @@ -235,7 +248,6 @@ esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings) xSemaphoreTake(_State.Mutex, portMAX_DELAY); - /* Save settings blob */ Error = nvs_set_blob(_State.NVS_Handle, "settings", p_Settings, sizeof(App_Settings_t)); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to write settings: %d!", Error); @@ -243,7 +255,6 @@ esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings) return Error; } - /* Commit to flash */ Error = nvs_commit(_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to commit settings: %d!", Error); @@ -257,7 +268,6 @@ esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings) ESP_LOGI(TAG, "Settings saved to NVS"); - /* Post event to notify settings saved */ esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_SAVED, NULL, 0, portMAX_DELAY); return ESP_OK; @@ -295,7 +305,6 @@ esp_err_t SettingsManager_SetLepton(const App_Settings_Lepton_t *p_Lepton) ESP_LOGI(TAG, "Lepton settings updated"); - /* Broadcast event */ esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_LEPTON_CHANGED, p_Lepton, sizeof(App_Settings_Lepton_t), portMAX_DELAY); @@ -317,10 +326,6 @@ esp_err_t SettingsManager_SetWiFi(const App_Settings_WiFi_t *p_WiFi) xSemaphoreGive(_State.Mutex); - ESP_LOGI(TAG, "WiFi settings updated (SSID: %s, AP Mode: %d)", - p_WiFi->SSID, p_WiFi->AP_Mode); - - /* Broadcast event */ esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_WIFI_CHANGED, p_WiFi, sizeof(App_Settings_WiFi_t), portMAX_DELAY); @@ -345,7 +350,6 @@ esp_err_t SettingsManager_SetDisplay(const App_Settings_Display_t *p_Display) ESP_LOGI(TAG, "Display settings updated (Brightness: %d%%, Timeout: %ds)", p_Display->Brightness, p_Display->ScreenTimeout); - /* Broadcast event */ esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_DISPLAY_CHANGED, p_Display, sizeof(App_Settings_Display_t), portMAX_DELAY); @@ -370,7 +374,6 @@ esp_err_t SettingsManager_SetSystem(const App_Settings_System_t *p_System) ESP_LOGI(TAG, "System settings updated (Device: %s, SD Auto: %d)", p_System->DeviceName, p_System->SDCard_AutoMount); - /* Broadcast event */ esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_SYSTEM_CHANGED, p_System, sizeof(App_Settings_System_t), portMAX_DELAY); @@ -389,7 +392,6 @@ esp_err_t SettingsManager_ResetToDefaults(void) xSemaphoreTake(_State.Mutex, portMAX_DELAY); - /* Erase settings from NVS */ Error = nvs_erase_key(_State.NVS_Handle, "settings"); if (Error != ESP_OK && Error != ESP_ERR_NVS_NOT_FOUND) { ESP_LOGE(TAG, "Failed to erase settings: %d!", Error); @@ -404,18 +406,15 @@ esp_err_t SettingsManager_ResetToDefaults(void) return Error; } - /* Load factory defaults */ _SettingsManager_InitDefaults(&_State.Settings); _State.PendingChanges = false; xSemaphoreGive(_State.Mutex); - /* Save defaults */ SettingsManager_Save(&_State.Settings); ESP_LOGI(TAG, "Settings reset to factory defaults"); - /* Broadcast event */ esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_CHANGED, &_State.Settings, sizeof(App_Settings_t), portMAX_DELAY); diff --git a/main/Application/Manager/Settings/settings_types.h b/main/Application/Manager/Settings/settings_types.h index b695998..5b4d932 100644 --- a/main/Application/Manager/Settings/settings_types.h +++ b/main/Application/Manager/Settings/settings_types.h @@ -49,32 +49,42 @@ enum { SETTINGS_EVENT_REQUEST_RESET, /**< Request to reset settings to factory defaults. */ }; -/** @brief Region of Interest (ROI) rectangle definition. +/** @brief GUI ROI types. + */ +typedef enum { + ROI_TYPE_SPOTMETER, /**< Spotmeter ROI. */ + ROI_TYPE_SCENE, /**< Scene statistics ROI. */ + ROI_TYPE_AGC, /**< AGC ROI. */ + ROI_TYPE_VIDEO_FOCUS, /**< Video focus ROI. */ +} App_Settings_ROI_Type_t; + +/** @brief Region of Interest (ROI) rectangle definition (based on Display coordinates). */ typedef struct { - uint16_t x; - uint16_t y; - uint16_t w; - uint16_t h; + App_Settings_ROI_Type_t Type; /**< ROI type (e.g., spotmeter). */ + uint16_t x; /**< X coordinate of the top-left corner. */ + uint16_t y; /**< Y coordinate of the top-left corner. */ + uint16_t w; /**< Width of the ROI. */ + uint16_t h; /**< Height of the ROI. */ } App_Settings_ROI_t; /** @brief Lepton camera settings. */ typedef struct { - App_Settings_ROI_t SpotmeterROI; /**< Spotmeter Region of Interest. */ + App_Settings_ROI_t ROI[4]; /**< Camera ROIs. */ + uint8_t Emissivity; /**< Emissivity (0-100). */ + bool EnableSceneStatistics; /**< Enable scene statistics calculation. */ uint8_t Reserved[100]; /**< Reserved for future use. */ -} App_Settings_Lepton_t; +} __attribute__((packed)) App_Settings_Lepton_t; /** @brief WiFi settings. */ typedef struct { - char SSID[32]; /**< WiFi SSID. */ - char Password[64]; /**< WiFi password. */ - bool AP_Mode; /**< Access Point mode (true) or Station mode (false). */ - char AP_SSID[32]; /**< AP mode SSID. */ - char AP_Password[64]; /**< AP mode password. */ + char SSID[33]; /**< WiFi SSID. */ + char Password[65]; /**< WiFi password. */ + bool AutoConnect; /**< Automatically connect to known WiFi networks. */ uint8_t Reserved[100]; /**< Reserved for future use. */ -} App_Settings_WiFi_t; +} __attribute__((packed)) App_Settings_WiFi_t; /** @brief Display settings. */ @@ -82,7 +92,7 @@ typedef struct { uint8_t Brightness; /**< Display brightness (0-100%). */ uint16_t ScreenTimeout; /**< Screen timeout in seconds (0=never). */ uint8_t Reserved[100]; /**< Reserved for future use. */ -} App_Settings_Display_t; +} __attribute__((packed)) App_Settings_Display_t; /** @brief System settings. */ @@ -92,7 +102,7 @@ typedef struct { bool Bluetooth_Enabled; /**< Bluetooth enabled. */ char Timezone[32]; /**< Timezone string (e.g., "CET-1CEST,M3.5.0,M10.5.0/3"). */ uint8_t Reserved[100]; /**< Reserved for future use. */ -} App_Settings_System_t; +} __attribute__((packed)) App_Settings_System_t; /** @brief Complete application settings structure. */ @@ -102,6 +112,6 @@ typedef struct { App_Settings_WiFi_t WiFi; /**< WiFi settings. */ App_Settings_Display_t Display; /**< Display settings. */ App_Settings_System_t System; /**< System settings. */ -} App_Settings_t; +} __attribute__((packed)) App_Settings_t; #endif /* SETTINGS_TYPES_H_ */ diff --git a/main/Application/Tasks/Devices/devicesTask.cpp b/main/Application/Tasks/Devices/devicesTask.cpp index c149082..8015a37 100644 --- a/main/Application/Tasks/Devices/devicesTask.cpp +++ b/main/Application/Tasks/Devices/devicesTask.cpp @@ -74,12 +74,9 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int static void Task_Devices(void *p_Parameters) { uint32_t Now; - App_Context_t *App_Context; esp_task_wdt_add(NULL); - App_Context = reinterpret_cast(p_Parameters); - ESP_LOGD(TAG, "Devices task started on core %d", xPortGetCoreID()); _DevicesTask_State.RunTask = true; diff --git a/main/Application/Tasks/GUI/Export/project.info b/main/Application/Tasks/GUI/Export/project.info index ff358ab..8be9eb8 100644 --- a/main/Application/Tasks/GUI/Export/project.info +++ b/main/Application/Tasks/GUI/Export/project.info @@ -1,9 +1,9 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2025-12-31T13:28:21.9912286+01:00", + "datetime": "2026-01-05T13:41:48.0249747+01:00", "editor_version": "1.5.4", - "project_version": 83, + "project_version": 92, "user": "Kampert Daniel", - "export_datetime": "2025-12-31T13:28:22.6736847+01:00", + "export_datetime": "2026-01-05T19:30:10.2287361+01:00", "export_user": "Kampert Daniel" } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.c b/main/Application/Tasks/GUI/Export/screens/ui_Info.c index 4cb6708..3d1bf7c 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.c @@ -47,6 +47,9 @@ lv_obj_t * ui_Label_Info_Lepton_Revision = NULL; lv_obj_t * ui_Label_Info_Lepton_Uptime = NULL; lv_obj_t * ui_Label_Info_Lepton_FPA = NULL; lv_obj_t * ui_Label_Info_Lepton_AUX = NULL; +lv_obj_t * ui_Container_Info_Buttons = NULL; +lv_obj_t * ui_Button_Info_Back = NULL; +lv_obj_t * ui_Label_Info_Back = NULL; // event funtions void ui_event_Info(lv_event_t * e) { @@ -61,18 +64,29 @@ void ui_event_Info(lv_event_t * e) } } +void ui_event_Button_Info_Back(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_CLICKED) { + _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); + } +} + // build funtions void ui_Info_screen_init(void) { ui_Info = lv_obj_create(NULL); lv_obj_remove_flag(ui_Info, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_flex_flow(ui_Info, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Info, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); lv_obj_set_style_bg_color(ui_Info, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_opa(ui_Info, 255, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Panel_Info_Header = lv_obj_create(ui_Info); lv_obj_set_width(ui_Panel_Info_Header, 320); - lv_obj_set_height(ui_Panel_Info_Header, 30); + lv_obj_set_height(ui_Panel_Info_Header, lv_pct(8)); lv_obj_set_x(ui_Panel_Info_Header, 1); lv_obj_set_y(ui_Panel_Info_Header, 1); lv_obj_set_align(ui_Panel_Info_Header, LV_ALIGN_TOP_MID); @@ -99,10 +113,10 @@ void ui_Info_screen_init(void) ui_Panel_Info_Content = lv_obj_create(ui_Info); lv_obj_set_width(ui_Panel_Info_Content, 320); - lv_obj_set_height(ui_Panel_Info_Content, 210); - lv_obj_set_x(ui_Panel_Info_Content, 0); - lv_obj_set_y(ui_Panel_Info_Content, 30); - lv_obj_set_align(ui_Panel_Info_Content, LV_ALIGN_TOP_MID); + lv_obj_set_height(ui_Panel_Info_Content, lv_pct(75)); + lv_obj_set_x(ui_Panel_Info_Content, -276); + lv_obj_set_y(ui_Panel_Info_Content, 104); + lv_obj_set_align(ui_Panel_Info_Content, LV_ALIGN_CENTER); lv_obj_set_flex_flow(ui_Panel_Info_Content, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(ui_Panel_Info_Content, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); lv_obj_set_scrollbar_mode(ui_Panel_Info_Content, LV_SCROLLBAR_MODE_ON); @@ -702,6 +716,38 @@ void ui_Info_screen_init(void) lv_obj_set_style_pad_top(ui_Label_Info_Lepton_AUX, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_AUX, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + ui_Container_Info_Buttons = lv_obj_create(ui_Info); + lv_obj_remove_style_all(ui_Container_Info_Buttons); + lv_obj_set_width(ui_Container_Info_Buttons, lv_pct(100)); + lv_obj_set_height(ui_Container_Info_Buttons, lv_pct(10)); + lv_obj_set_x(ui_Container_Info_Buttons, 0); + lv_obj_set_y(ui_Container_Info_Buttons, 100); + lv_obj_set_align(ui_Container_Info_Buttons, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Container_Info_Buttons, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Button_Info_Back = lv_button_create(ui_Container_Info_Buttons); + lv_obj_set_width(ui_Button_Info_Back, 50); + lv_obj_set_height(ui_Button_Info_Back, lv_pct(95)); + lv_obj_set_x(ui_Button_Info_Back, -80); + lv_obj_set_y(ui_Button_Info_Back, 0); + lv_obj_set_align(ui_Button_Info_Back, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Button_Info_Back, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_bg_color(ui_Button_Info_Back, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Button_Info_Back, 200, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Button_Info_Back, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Button_Info_Back, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Button_Info_Back, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Back = lv_label_create(ui_Button_Info_Back); + lv_obj_set_width(ui_Label_Info_Back, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Back, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Back, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Back, "B"); + lv_obj_set_style_text_font(ui_Label_Info_Back, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + + lv_obj_add_event_cb(ui_Button_Info_Back, ui_event_Button_Info_Back, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(ui_Info, ui_event_Info, LV_EVENT_ALL, NULL); } @@ -753,5 +799,8 @@ void ui_Info_screen_destroy(void) ui_Label_Info_Lepton_Uptime = NULL; ui_Label_Info_Lepton_FPA = NULL; ui_Label_Info_Lepton_AUX = NULL; + ui_Container_Info_Buttons = NULL; + ui_Button_Info_Back = NULL; + ui_Label_Info_Back = NULL; } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.h b/main/Application/Tasks/GUI/Export/screens/ui_Info.h index 81829b0..e752ce7 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.h @@ -56,6 +56,10 @@ extern lv_obj_t * ui_Label_Info_Lepton_Revision; extern lv_obj_t * ui_Label_Info_Lepton_Uptime; extern lv_obj_t * ui_Label_Info_Lepton_FPA; extern lv_obj_t * ui_Label_Info_Lepton_AUX; +extern lv_obj_t * ui_Container_Info_Buttons; +extern void ui_event_Button_Info_Back(lv_event_t * e); +extern lv_obj_t * ui_Button_Info_Back; +extern lv_obj_t * ui_Label_Info_Back; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.c b/main/Application/Tasks/GUI/Export/screens/ui_Main.c index 9c10754..17ad764 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.c @@ -13,13 +13,18 @@ lv_obj_t * ui_Image_Main_SDCard = NULL; lv_obj_t * ui_Label_Main_Time = NULL; lv_obj_t * ui_Image_Main_Battery = NULL; lv_obj_t * ui_Label_Main_Battery_Remaining = NULL; -lv_obj_t * ui_Label_Main_MinTemp = NULL; -lv_obj_t * ui_Label_Main_MaxTemp = NULL; lv_obj_t * ui_Container_Main_Thermal = NULL; lv_obj_t * ui_Image_Thermal = NULL; -lv_obj_t * ui_Image_Main_Thermal_ROI = NULL; +lv_obj_t * ui_Image_Main_Thermal_Scene_ROI = NULL; +lv_obj_t * ui_Image_Main_Thermal_Spotmeter_ROI = NULL; +lv_obj_t * ui_Image_Main_Thermal_Video_Focus_ROI = NULL; +lv_obj_t * ui_Image_Main_Thermal_AGC_ROI = NULL; lv_obj_t * ui_Label_Main_Thermal_Crosshair = NULL; lv_obj_t * ui_Label_Main_Thermal_PixelTemperature = NULL; +lv_obj_t * ui_Container_Main_Thermal_Scene_Statistics = NULL; +lv_obj_t * ui_Label_Main_Thermal_Scene_Max = NULL; +lv_obj_t * ui_Label_Main_Thermal_Scene_Min = NULL; +lv_obj_t * ui_Label_Main_Thermal_Scene_Mean = NULL; lv_obj_t * ui_Container_Gradient = NULL; lv_obj_t * ui_Label_TempScaleMax = NULL; lv_obj_t * ui_Image_Gradient = NULL; @@ -168,30 +173,6 @@ void ui_Main_screen_init(void) lv_obj_set_style_text_opa(ui_Label_Main_Battery_Remaining, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_Label_Main_Battery_Remaining, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Label_Main_MinTemp = lv_label_create(ui_Container_Main_StatusBar); - lv_obj_set_width(ui_Label_Main_MinTemp, LV_SIZE_CONTENT); /// 1 - lv_obj_set_height(ui_Label_Main_MinTemp, LV_SIZE_CONTENT); /// 1 - lv_obj_set_x(ui_Label_Main_MinTemp, 65); - lv_obj_set_y(ui_Label_Main_MinTemp, 0); - lv_obj_set_align(ui_Label_Main_MinTemp, LV_ALIGN_LEFT_MID); - lv_label_set_text(ui_Label_Main_MinTemp, "-99.99 °C"); - lv_obj_add_flag(ui_Label_Main_MinTemp, LV_OBJ_FLAG_HIDDEN); /// Flags - lv_obj_set_style_text_color(ui_Label_Main_MinTemp, lv_color_hex(0x004DFF), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_opa(ui_Label_Main_MinTemp, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Main_MinTemp, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); - - ui_Label_Main_MaxTemp = lv_label_create(ui_Container_Main_StatusBar); - lv_obj_set_width(ui_Label_Main_MaxTemp, LV_SIZE_CONTENT); /// 1 - lv_obj_set_height(ui_Label_Main_MaxTemp, LV_SIZE_CONTENT); /// 1 - lv_obj_set_x(ui_Label_Main_MaxTemp, 130); - lv_obj_set_y(ui_Label_Main_MaxTemp, 0); - lv_obj_set_align(ui_Label_Main_MaxTemp, LV_ALIGN_LEFT_MID); - lv_label_set_text(ui_Label_Main_MaxTemp, "+99.99 °C"); - lv_obj_add_flag(ui_Label_Main_MaxTemp, LV_OBJ_FLAG_HIDDEN); /// Flags - lv_obj_set_style_text_color(ui_Label_Main_MaxTemp, lv_color_hex(0xFF0000), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_opa(ui_Label_Main_MaxTemp, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Main_MaxTemp, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Container_Main_Thermal = lv_obj_create(ui_Main); lv_obj_remove_style_all(ui_Container_Main_Thermal); lv_obj_set_width(ui_Container_Main_Thermal, lv_pct(100)); @@ -216,18 +197,66 @@ void ui_Main_screen_init(void) lv_obj_set_style_bg_grad_color(ui_Image_Thermal, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_grad_dir(ui_Image_Thermal, LV_GRAD_DIR_HOR, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Image_Main_Thermal_ROI = lv_obj_create(ui_Image_Thermal); - lv_obj_set_width(ui_Image_Main_Thermal_ROI, 60); - lv_obj_set_height(ui_Image_Main_Thermal_ROI, 60); - lv_obj_remove_flag(ui_Image_Main_Thermal_ROI, + ui_Image_Main_Thermal_Scene_ROI = lv_obj_create(ui_Image_Thermal); + lv_obj_set_width(ui_Image_Main_Thermal_Scene_ROI, 240); + lv_obj_set_height(ui_Image_Main_Thermal_Scene_ROI, 180); + lv_obj_set_align(ui_Image_Main_Thermal_Scene_ROI, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Image_Main_Thermal_Scene_ROI, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_scrollbar_mode(ui_Image_Main_Thermal_Scene_ROI, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_bg_color(ui_Image_Main_Thermal_Scene_ROI, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Image_Main_Thermal_Scene_ROI, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Image_Main_Thermal_Scene_ROI, lv_color_hex(0xF03FEE), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Image_Main_Thermal_Scene_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Image_Main_Thermal_Scene_ROI, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Main_Thermal_Spotmeter_ROI = lv_obj_create(ui_Image_Thermal); + lv_obj_set_width(ui_Image_Main_Thermal_Spotmeter_ROI, 1); + lv_obj_set_height(ui_Image_Main_Thermal_Spotmeter_ROI, 1); + lv_obj_set_x(ui_Image_Main_Thermal_Spotmeter_ROI, 119); + lv_obj_set_y(ui_Image_Main_Thermal_Spotmeter_ROI, 89); + lv_obj_set_align(ui_Image_Main_Thermal_Spotmeter_ROI, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Image_Main_Thermal_Spotmeter_ROI, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_scrollbar_mode(ui_Image_Main_Thermal_Spotmeter_ROI, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_bg_color(ui_Image_Main_Thermal_Spotmeter_ROI, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Image_Main_Thermal_Spotmeter_ROI, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Image_Main_Thermal_Spotmeter_ROI, lv_color_hex(0x7B3FF0), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Image_Main_Thermal_Spotmeter_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Image_Main_Thermal_Spotmeter_ROI, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Main_Thermal_Video_Focus_ROI = lv_obj_create(ui_Image_Thermal); + lv_obj_set_width(ui_Image_Main_Thermal_Video_Focus_ROI, 238); + lv_obj_set_height(ui_Image_Main_Thermal_Video_Focus_ROI, 178); + lv_obj_set_align(ui_Image_Main_Thermal_Video_Focus_ROI, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Image_Main_Thermal_Video_Focus_ROI, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags - lv_obj_set_scrollbar_mode(ui_Image_Main_Thermal_ROI, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_style_bg_color(ui_Image_Main_Thermal_ROI, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_bg_opa(ui_Image_Main_Thermal_ROI, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_border_color(ui_Image_Main_Thermal_ROI, lv_color_hex(0x7B3FF0), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_border_opa(ui_Image_Main_Thermal_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_border_width(ui_Image_Main_Thermal_ROI, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_scrollbar_mode(ui_Image_Main_Thermal_Video_Focus_ROI, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_bg_color(ui_Image_Main_Thermal_Video_Focus_ROI, lv_color_hex(0x000000), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Image_Main_Thermal_Video_Focus_ROI, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Image_Main_Thermal_Video_Focus_ROI, lv_color_hex(0xEBF03F), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Image_Main_Thermal_Video_Focus_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Image_Main_Thermal_Video_Focus_ROI, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Image_Main_Thermal_AGC_ROI = lv_obj_create(ui_Image_Thermal); + lv_obj_set_width(ui_Image_Main_Thermal_AGC_ROI, 240); + lv_obj_set_height(ui_Image_Main_Thermal_AGC_ROI, 180); + lv_obj_set_align(ui_Image_Main_Thermal_AGC_ROI, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Image_Main_Thermal_AGC_ROI, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_scrollbar_mode(ui_Image_Main_Thermal_AGC_ROI, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_style_bg_color(ui_Image_Main_Thermal_AGC_ROI, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Image_Main_Thermal_AGC_ROI, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Image_Main_Thermal_AGC_ROI, lv_color_hex(0x3F96F0), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Image_Main_Thermal_AGC_ROI, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Image_Main_Thermal_AGC_ROI, 2, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Label_Main_Thermal_Crosshair = lv_label_create(ui_Image_Thermal); lv_obj_set_width(ui_Label_Main_Thermal_Crosshair, LV_SIZE_CONTENT); /// 1 @@ -243,11 +272,57 @@ void ui_Main_screen_init(void) lv_obj_set_y(ui_Label_Main_Thermal_PixelTemperature, -15); lv_obj_set_align(ui_Label_Main_Thermal_PixelTemperature, LV_ALIGN_CENTER); lv_label_set_text(ui_Label_Main_Thermal_PixelTemperature, "101.1"); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_PixelTemperature, lv_color_hex(0xFFFFFF), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Thermal_PixelTemperature, 192, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_Label_Main_Thermal_PixelTemperature, &lv_font_montserrat_14, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_bg_color(ui_Label_Main_Thermal_PixelTemperature, lv_color_hex(0xFFFFFF), - LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_bg_opa(ui_Label_Main_Thermal_PixelTemperature, 127, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Container_Main_Thermal_Scene_Statistics = lv_obj_create(ui_Image_Thermal); + lv_obj_remove_style_all(ui_Container_Main_Thermal_Scene_Statistics); + lv_obj_set_height(ui_Container_Main_Thermal_Scene_Statistics, 20); + lv_obj_set_width(ui_Container_Main_Thermal_Scene_Statistics, lv_pct(100)); + lv_obj_set_align(ui_Container_Main_Thermal_Scene_Statistics, LV_ALIGN_BOTTOM_MID); + lv_obj_remove_flag(ui_Container_Main_Thermal_Scene_Statistics, + LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Label_Main_Thermal_Scene_Max = lv_label_create(ui_Container_Main_Thermal_Scene_Statistics); + lv_obj_set_width(ui_Label_Main_Thermal_Scene_Max, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Thermal_Scene_Max, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Thermal_Scene_Max, LV_ALIGN_LEFT_MID); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Max, "100.0"); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Max, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Thermal_Scene_Max, 192, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_Thermal_Scene_Max, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_image_opa(ui_Label_Main_Thermal_Scene_Max, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Main_Thermal_Scene_Max, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Main_Thermal_Scene_Max, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Main_Thermal_Scene_Max, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Main_Thermal_Scene_Max, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Thermal_Scene_Min = lv_label_create(ui_Container_Main_Thermal_Scene_Statistics); + lv_obj_set_width(ui_Label_Main_Thermal_Scene_Min, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Thermal_Scene_Min, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Thermal_Scene_Min, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Min, "-40.0"); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Min, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Thermal_Scene_Min, 192, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_Thermal_Scene_Min, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_image_opa(ui_Label_Main_Thermal_Scene_Min, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Thermal_Scene_Mean = lv_label_create(ui_Container_Main_Thermal_Scene_Statistics); + lv_obj_set_width(ui_Label_Main_Thermal_Scene_Mean, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Thermal_Scene_Mean, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Thermal_Scene_Mean, LV_ALIGN_RIGHT_MID); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Mean, "80.0"); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Mean, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Thermal_Scene_Mean, 192, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_Thermal_Scene_Mean, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_image_opa(ui_Label_Main_Thermal_Scene_Mean, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Main_Thermal_Scene_Mean, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Main_Thermal_Scene_Mean, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Main_Thermal_Scene_Mean, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Main_Thermal_Scene_Mean, 5, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Container_Gradient = lv_obj_create(ui_Container_Main_Thermal); lv_obj_remove_style_all(ui_Container_Gradient); @@ -299,8 +374,8 @@ void ui_Main_screen_init(void) lv_obj_remove_style_all(ui_Container_Main_Buttons); lv_obj_set_width(ui_Container_Main_Buttons, lv_pct(100)); lv_obj_set_height(ui_Container_Main_Buttons, lv_pct(10)); - lv_obj_set_x(ui_Container_Main_Buttons, 11); - lv_obj_set_y(ui_Container_Main_Buttons, 97); + lv_obj_set_x(ui_Container_Main_Buttons, 106); + lv_obj_set_y(ui_Container_Main_Buttons, -14); lv_obj_set_align(ui_Container_Main_Buttons, LV_ALIGN_CENTER); lv_obj_remove_flag(ui_Container_Main_Buttons, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags @@ -416,13 +491,18 @@ void ui_Main_screen_destroy(void) ui_Label_Main_Time = NULL; ui_Image_Main_Battery = NULL; ui_Label_Main_Battery_Remaining = NULL; - ui_Label_Main_MinTemp = NULL; - ui_Label_Main_MaxTemp = NULL; ui_Container_Main_Thermal = NULL; ui_Image_Thermal = NULL; - ui_Image_Main_Thermal_ROI = NULL; + ui_Image_Main_Thermal_Scene_ROI = NULL; + ui_Image_Main_Thermal_Spotmeter_ROI = NULL; + ui_Image_Main_Thermal_Video_Focus_ROI = NULL; + ui_Image_Main_Thermal_AGC_ROI = NULL; ui_Label_Main_Thermal_Crosshair = NULL; ui_Label_Main_Thermal_PixelTemperature = NULL; + ui_Container_Main_Thermal_Scene_Statistics = NULL; + ui_Label_Main_Thermal_Scene_Max = NULL; + ui_Label_Main_Thermal_Scene_Min = NULL; + ui_Label_Main_Thermal_Scene_Mean = NULL; ui_Container_Gradient = NULL; ui_Label_TempScaleMax = NULL; ui_Image_Gradient = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.h b/main/Application/Tasks/GUI/Export/screens/ui_Main.h index 0d261af..6306c52 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.h @@ -22,13 +22,18 @@ extern lv_obj_t * ui_Image_Main_SDCard; extern lv_obj_t * ui_Label_Main_Time; extern lv_obj_t * ui_Image_Main_Battery; extern lv_obj_t * ui_Label_Main_Battery_Remaining; -extern lv_obj_t * ui_Label_Main_MinTemp; -extern lv_obj_t * ui_Label_Main_MaxTemp; extern lv_obj_t * ui_Container_Main_Thermal; extern lv_obj_t * ui_Image_Thermal; -extern lv_obj_t * ui_Image_Main_Thermal_ROI; +extern lv_obj_t * ui_Image_Main_Thermal_Scene_ROI; +extern lv_obj_t * ui_Image_Main_Thermal_Spotmeter_ROI; +extern lv_obj_t * ui_Image_Main_Thermal_Video_Focus_ROI; +extern lv_obj_t * ui_Image_Main_Thermal_AGC_ROI; extern lv_obj_t * ui_Label_Main_Thermal_Crosshair; extern lv_obj_t * ui_Label_Main_Thermal_PixelTemperature; +extern lv_obj_t * ui_Container_Main_Thermal_Scene_Statistics; +extern lv_obj_t * ui_Label_Main_Thermal_Scene_Max; +extern lv_obj_t * ui_Label_Main_Thermal_Scene_Min; +extern lv_obj_t * ui_Label_Main_Thermal_Scene_Mean; extern lv_obj_t * ui_Container_Gradient; extern lv_obj_t * ui_Label_TempScaleMax; extern lv_obj_t * ui_Image_Gradient; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c index 81df529..f540c27 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c @@ -9,6 +9,9 @@ lv_obj_t * ui_Menu = NULL; lv_obj_t * ui_Panel_Menu_Header = NULL; lv_obj_t * ui_Label_Menu_Header = NULL; lv_obj_t * ui_Container_Menu = NULL; +lv_obj_t * ui_Container_Menu_Buttons = NULL; +lv_obj_t * ui_Button_Menu_Back = NULL; +lv_obj_t * ui_Label_Menu_Back = NULL; // event funtions void ui_event_Menu(lv_event_t * e) { @@ -23,18 +26,29 @@ void ui_event_Menu(lv_event_t * e) } } +void ui_event_Button_Menu_Back(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_CLICKED) { + _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); + } +} + // build funtions void ui_Menu_screen_init(void) { ui_Menu = lv_obj_create(NULL); lv_obj_remove_flag(ui_Menu, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_flex_flow(ui_Menu, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(ui_Menu, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); lv_obj_set_style_bg_color(ui_Menu, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_opa(ui_Menu, 255, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Panel_Menu_Header = lv_obj_create(ui_Menu); lv_obj_set_width(ui_Panel_Menu_Header, 320); - lv_obj_set_height(ui_Panel_Menu_Header, lv_pct(12)); + lv_obj_set_height(ui_Panel_Menu_Header, lv_pct(8)); lv_obj_set_x(ui_Panel_Menu_Header, 1); lv_obj_set_y(ui_Panel_Menu_Header, 1); lv_obj_set_align(ui_Panel_Menu_Header, LV_ALIGN_TOP_MID); @@ -61,13 +75,45 @@ void ui_Menu_screen_init(void) ui_Container_Menu = lv_obj_create(ui_Menu); lv_obj_remove_style_all(ui_Container_Menu); - lv_obj_set_height(ui_Container_Menu, 210); lv_obj_set_width(ui_Container_Menu, lv_pct(100)); + lv_obj_set_height(ui_Container_Menu, lv_pct(75)); lv_obj_set_x(ui_Container_Menu, 0); lv_obj_set_y(ui_Container_Menu, 15); lv_obj_set_align(ui_Container_Menu, LV_ALIGN_CENTER); lv_obj_remove_flag(ui_Container_Menu, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + ui_Container_Menu_Buttons = lv_obj_create(ui_Menu); + lv_obj_remove_style_all(ui_Container_Menu_Buttons); + lv_obj_set_width(ui_Container_Menu_Buttons, lv_pct(100)); + lv_obj_set_height(ui_Container_Menu_Buttons, lv_pct(10)); + lv_obj_set_x(ui_Container_Menu_Buttons, 0); + lv_obj_set_y(ui_Container_Menu_Buttons, 100); + lv_obj_set_align(ui_Container_Menu_Buttons, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Container_Menu_Buttons, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_Button_Menu_Back = lv_button_create(ui_Container_Menu_Buttons); + lv_obj_set_width(ui_Button_Menu_Back, 50); + lv_obj_set_height(ui_Button_Menu_Back, lv_pct(95)); + lv_obj_set_x(ui_Button_Menu_Back, -80); + lv_obj_set_y(ui_Button_Menu_Back, 0); + lv_obj_set_align(ui_Button_Menu_Back, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Button_Menu_Back, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_bg_color(ui_Button_Menu_Back, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Button_Menu_Back, 200, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Button_Menu_Back, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Button_Menu_Back, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Button_Menu_Back, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Menu_Back = lv_label_create(ui_Button_Menu_Back); + lv_obj_set_width(ui_Label_Menu_Back, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Menu_Back, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Menu_Back, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Menu_Back, "B"); + lv_obj_set_style_text_font(ui_Label_Menu_Back, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + + lv_obj_add_event_cb(ui_Button_Menu_Back, ui_event_Button_Menu_Back, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(ui_Menu, ui_event_Menu, LV_EVENT_ALL, NULL); } @@ -81,5 +127,8 @@ void ui_Menu_screen_destroy(void) ui_Panel_Menu_Header = NULL; ui_Label_Menu_Header = NULL; ui_Container_Menu = NULL; + ui_Container_Menu_Buttons = NULL; + ui_Button_Menu_Back = NULL; + ui_Label_Menu_Back = NULL; } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h index 44ee69d..1e46a28 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h @@ -18,6 +18,10 @@ extern lv_obj_t * ui_Menu; extern lv_obj_t * ui_Panel_Menu_Header; extern lv_obj_t * ui_Label_Menu_Header; extern lv_obj_t * ui_Container_Menu; +extern lv_obj_t * ui_Container_Menu_Buttons; +extern void ui_event_Button_Menu_Back(lv_event_t * e); +extern lv_obj_t * ui_Button_Menu_Back; +extern lv_obj_t * ui_Label_Menu_Back; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/ui_events.cpp b/main/Application/Tasks/GUI/Export/ui_events.cpp index 3ca73ee..06c3784 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.cpp +++ b/main/Application/Tasks/GUI/Export/ui_events.cpp @@ -24,9 +24,12 @@ void ScreenMainLoaded(lv_event_t *e) lv_label_set_text(ui_Label_Main_Button_Menu, "\uF0C9"); lv_label_set_text(ui_Label_Main_Button_Info, "\uF129"); - lv_label_set_text(ui_Label_Main_Button_ROI, "\uF05B"); + lv_label_set_text(ui_Label_Main_Button_ROI, "\uE595"); lv_label_set_text(ui_Label_Main_Button_WiFi, "\uF1EB"); lv_label_set_text(ui_Label_Main_Thermal_Crosshair, "\uF05B"); + + lv_label_set_text(ui_Label_Menu_Back, "\uF060"); + lv_label_set_text(ui_Label_Info_Back, "\uF060"); } void ScreenInfoLoaded(lv_event_t *e) diff --git a/main/Application/Tasks/GUI/Private/guiHelper.cpp b/main/Application/Tasks/GUI/Private/guiHelper.cpp index c4e9321..4c739ce 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.cpp +++ b/main/Application/Tasks/GUI/Private/guiHelper.cpp @@ -213,6 +213,9 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t p_GUITask_State->UpdateTimer[1] = lv_timer_create(GUI_Helper_Timer_SpotUpdate, 2000, NULL); p_GUITask_State->UpdateTimer[2] = lv_timer_create(GUI_Helper_Timer_SpotmeterUpdate, 5000, NULL); + p_GUITask_State->UpdateTimer[3] = lv_timer_create(GUI_Helper_Timer_SceneStatisticsUpdate, 5000, NULL); + + _lock_init(&p_GUITask_State->LVGL_API_Lock); return ESP_OK; } @@ -230,10 +233,6 @@ void GUI_Helper_Deinit(GUI_Task_State_t *p_GUITask_State) } } - esp_timer_stop(p_GUITask_State->LVGL_TickTimer); - esp_timer_delete(p_GUITask_State->LVGL_TickTimer); - p_GUITask_State->LVGL_TickTimer = NULL; - if (p_GUITask_State->LVGL_TickTimer != NULL) { esp_timer_stop(p_GUITask_State->LVGL_TickTimer); esp_timer_delete(p_GUITask_State->LVGL_TickTimer); @@ -276,14 +275,8 @@ void GUI_Helper_Deinit(GUI_Task_State_t *p_GUITask_State) esp_lcd_panel_del(p_GUITask_State->PanelHandle); p_GUITask_State->PanelHandle = NULL; } -} - -void GUI_Helper_GetSpotTemperature(float Temperature) -{ - char buf[16]; - snprintf(buf, sizeof(buf), "%.2f °C", Temperature); - lv_label_set_text(ui_Label_Main_Thermal_PixelTemperature, buf); + _lock_close(&p_GUITask_State->LVGL_API_Lock); } void GUI_Helper_Timer_ClockUpdate(lv_timer_t *p_Timer) @@ -309,8 +302,6 @@ void GUI_Helper_Timer_SpotUpdate(lv_timer_t *p_Timer) /* Check if thermal image is initialized */ if ((lv_obj_get_width(ui_Image_Thermal) == 0) || (lv_obj_get_height(ui_Image_Thermal) == 0)) { - ESP_LOGW(TAG, "Thermal image not yet initialized, skipping spot update", - lv_obj_get_width(ui_Image_Thermal), lv_obj_get_height(ui_Image_Thermal)); return; } @@ -322,7 +313,8 @@ void GUI_Helper_Timer_SpotUpdate(lv_timer_t *p_Timer) ScreenPosition.Width = lv_obj_get_width(ui_Image_Thermal); ScreenPosition.Height = lv_obj_get_height(ui_Image_Thermal); - ESP_LOGD(TAG, "Crosshair center in thermal canvas: (%d,%d), size (%d,%d)", ScreenPosition.x, ScreenPosition.y, ScreenPosition.Width, ScreenPosition.Height); + ESP_LOGD(TAG, "Crosshair center in thermal canvas: (%d,%d), size (%d,%d)", ScreenPosition.x, ScreenPosition.y, + ScreenPosition.Width, ScreenPosition.Height); esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_PIXEL_TEMPERATURE, &ScreenPosition, sizeof(ScreenPosition), portMAX_DELAY); } @@ -330,4 +322,9 @@ void GUI_Helper_Timer_SpotUpdate(lv_timer_t *p_Timer) void GUI_Helper_Timer_SpotmeterUpdate(lv_timer_t *p_Timer) { esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_SPOTMETER, NULL, 0, portMAX_DELAY); +} + +void GUI_Helper_Timer_SceneStatisticsUpdate(lv_timer_t *p_Timer) +{ + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_SCENE_STATISTICS, NULL, 0, portMAX_DELAY); } \ No newline at end of file diff --git a/main/Application/Tasks/GUI/Private/guiHelper.h b/main/Application/Tasks/GUI/Private/guiHelper.h index f8021db..d251f56 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.h +++ b/main/Application/Tasks/GUI/Private/guiHelper.h @@ -52,6 +52,7 @@ #define LEPTON_PIXEL_TEMPERATURE_READY BIT13 #define LEPTON_CAMERA_READY BIT4 #define LEPTON_SPOTMETER_READY BIT5 +#define LEPTON_SCENE_STATISTICS_READY BIT6 typedef struct { bool isInitialized; @@ -73,10 +74,10 @@ typedef struct { lv_indev_t *Touch; lv_img_dsc_t ThermalImageDescriptor; lv_img_dsc_t GradientImageDescriptor; - lv_timer_t *UpdateTimer[3]; + lv_timer_t *UpdateTimer[4]; _lock_t LVGL_API_Lock; App_Devices_Battery_t BatteryInfo; - App_Lepton_Spotmeter_t SpotmeterInfo; + App_Lepton_ROI_Result_t ROIResult; App_Lepton_Device_t LeptonDeviceInfo; App_Lepton_Temperatures_t LeptonTemperatures; Network_IP_Info_t IP_Info; @@ -90,17 +91,6 @@ typedef struct { /* Network frame for server streaming */ Network_Thermal_Frame_t NetworkFrame; - /* ROI control state */ - bool ROI_EditMode; - bool ROI_LongPressActive; /* Flag to prevent CLICKED after LONG_PRESSED */ - uint8_t ROI_ResizeMode; /* 0=move, 1=resize_left, 2=resize_right, 4=resize_top, 8=resize_bottom, combinations for corners */ - int32_t ROI_DragStartX; - int32_t ROI_DragStartY; - int32_t ROI_InitialX; - int32_t ROI_InitialY; - int32_t ROI_InitialW; - int32_t ROI_InitialH; - #ifdef CONFIG_GUI_TOUCH_DEBUG /* Touch debug visualization */ lv_obj_t *TouchDebugOverlay; @@ -120,8 +110,6 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t */ void GUI_Helper_Deinit(GUI_Task_State_t *p_GUITask_State); -void GUI_Helper_GetSpotTemperature(float Temperature); - /** @brief LVGL timer callback to update the clock display. * @param p_Timer Pointer to the LVGL timer structure. */ @@ -137,4 +125,9 @@ void GUI_Helper_Timer_SpotUpdate(lv_timer_t *p_Timer); */ void GUI_Helper_Timer_SpotmeterUpdate(lv_timer_t *p_Timer); +/** @brief LVGL timer callback to request scene statistics data update. + * @param p_Timer Pointer to the LVGL timer structure. + */ +void GUI_Helper_Timer_SceneStatisticsUpdate(lv_timer_t *p_Timer); + #endif /* GUI_HELPER_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp index 41f20aa..4f1f19c 100644 --- a/main/Application/Tasks/GUI/guiTask.cpp +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -256,12 +256,19 @@ static void on_Lepton_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, break; } case LEPTON_EVENT_RESPONSE_SPOTMETER: { - memcpy(&_GUITask_State.SpotmeterInfo, p_Data, sizeof(App_Lepton_Spotmeter_t)); + memcpy(&_GUITask_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_SPOTMETER_READY); break; } + case LEPTON_EVENT_RESPONSE_SCENE_STATISTICS: { + memcpy(&_GUITask_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); + + xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_SCENE_STATISTICS_READY); + + break; + } case LEPTON_EVENT_RESPONSE_UPTIME: { memcpy(&_GUITask_State.LeptonUptime, p_Data, sizeof(uint32_t)); @@ -299,282 +306,113 @@ static void GUI_Update_Info(void) } /** @brief Update the ROI rectangle on the GUI and on the Lepton. + * @param Type ROI type * @param x X position of the ROI (in Lepton coordinates 0-159) * @param y Y position (in Lepton coordinates 0-119) * @param w Width of the ROI * @param h Height of the ROI */ -static void GUI_Update_ROI(int32_t x, int32_t y, int32_t w, int32_t h) +static void GUI_Update_ROI(App_Settings_ROI_t ROI) { - App_Settings_ROI_t ROI; - - /* Clamp values to Lepton sensor dimensions */ - if (x < 0) { - x = 0; - } + int32_t DisplayWidth; + int32_t DisplayHeight; + App_Settings_ROI_t Lepton_ROI; + App_Settings_t App_Settings; - if (y < 0) { - y = 0; + if ((ROI.x + ROI.w) > 160) { + ROI.w = 160 - ROI.x; } - if (x + w > 160) { - w = 160 - x; - } - - if (y + h > 120) { - h = 120 - y; + if ((ROI.y + ROI.h) > 120) { + ROI.h = 120 - ROI.y; } /* Minimum size constraints */ - if (w < 10) { - w = 10; - } else if (h < 10) { - h = 10; + if (ROI.w < 1) { + ROI.w = 1; + } else if (ROI.h < 1) { + ROI.h = 1; } - ROI = { - .x = (uint16_t)x, - .y = (uint16_t)y, - .w = (uint16_t)w, - .h = (uint16_t)h - }; - /* Update visual rectangle on display (convert Lepton coords to display coords) */ - if (ui_Image_Main_Thermal_ROI != NULL) { - int32_t display_width; - int32_t display_height; - - ESP_LOGD(TAG, "Updating ROI rectangle - Start: (%ld,%ld), End: (%ld,%ld), Size: %ldx%ld", - ROI.x, ROI.y, ROI.x + ROI.w, ROI.y + ROI.h, ROI.w, ROI.h); - - display_width = lv_obj_get_width(ui_Image_Thermal); - display_height = lv_obj_get_height(ui_Image_Thermal); - - int32_t disp_x = (x * display_width) / 160; - int32_t disp_y = (y * display_height) / 120; - int32_t disp_w = (w * display_width) / 160; - int32_t disp_h = (h * display_height) / 120; - - /* Remove alignment to allow manual positioning */ - lv_obj_set_align(ui_Image_Main_Thermal_ROI, LV_ALIGN_TOP_LEFT); - lv_obj_set_pos(ui_Image_Main_Thermal_ROI, disp_x, disp_y); - lv_obj_set_size(ui_Image_Main_Thermal_ROI, disp_w, disp_h); - } - - /* Send ROI update to Lepton task */ - esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_ROI, &ROI, sizeof(App_Settings_ROI_t), portMAX_DELAY); -} - -/** @brief Event handler for ROI reset button. - * Handles both LONG_PRESSED (reset) and CLICKED (toggle visibility). - */ -static void ROI_Clicked_Event_Handler(lv_event_t *e) -{ - lv_event_code_t code = lv_event_get_code(e); - - if (code == LV_EVENT_LONG_PRESSED) { - ESP_LOGD(TAG, "ROI reset - long press detected"); - - /* Set flag to prevent subsequent CLICKED event */ - _GUITask_State.ROI_LongPressActive = true; + ESP_LOGD(TAG, "Updating ROI rectangle - Start: (%ld,%ld), End: (%ld,%ld), Size: %ldx%ld", + ROI.x, ROI.y, ROI.x + ROI.w, ROI.y + ROI.h, ROI.w, ROI.h); + + DisplayWidth = lv_obj_get_width(ui_Image_Thermal); + DisplayHeight = lv_obj_get_height(ui_Image_Thermal); + + int32_t disp_x = (ROI.x * DisplayWidth) / 160; + int32_t disp_y = (ROI.y * DisplayHeight) / 120; + int32_t disp_w = (ROI.w * DisplayWidth) / 160; + int32_t disp_h = (ROI.h * DisplayHeight) / 120; + + switch (ROI.Type) { + case ROI_TYPE_SPOTMETER: { + if (ui_Image_Main_Thermal_Spotmeter_ROI != NULL) { + lv_obj_set_align(ui_Image_Main_Thermal_Spotmeter_ROI, LV_ALIGN_TOP_LEFT); + lv_obj_set_pos(ui_Image_Main_Thermal_Spotmeter_ROI, disp_x, disp_y); + lv_obj_set_size(ui_Image_Main_Thermal_Spotmeter_ROI, disp_w, disp_h); + } - /* Reset ROI to center with default size */ - GUI_Update_ROI(60, 40, 40, 40); - } else if (code == LV_EVENT_CLICKED) { - /* Check if this click came after a long press */ - if (_GUITask_State.ROI_LongPressActive) { - ESP_LOGD(TAG, "ROI click suppressed after long press"); - _GUITask_State.ROI_LongPressActive = false; - return; + break; } + case ROI_TYPE_SCENE: { + if (ui_Image_Main_Thermal_Scene_ROI != NULL) { + lv_obj_set_align(ui_Image_Main_Thermal_Scene_ROI, LV_ALIGN_TOP_LEFT); + lv_obj_set_pos(ui_Image_Main_Thermal_Scene_ROI, disp_x, disp_y); + lv_obj_set_size(ui_Image_Main_Thermal_Scene_ROI, disp_w, disp_h); + } - ESP_LOGD(TAG, "ROI toggle visibility"); - /* Toggle ROI visibility on normal click */ - if (lv_obj_has_flag(ui_Image_Main_Thermal_ROI, LV_OBJ_FLAG_HIDDEN)) { - lv_obj_clear_flag(ui_Image_Main_Thermal_ROI, LV_OBJ_FLAG_HIDDEN); - } else { - lv_obj_add_flag(ui_Image_Main_Thermal_ROI, LV_OBJ_FLAG_HIDDEN); + break; } - } -} + case ROI_TYPE_AGC: { + if (ui_Image_Main_Thermal_AGC_ROI != NULL) { + lv_obj_set_align(ui_Image_Main_Thermal_AGC_ROI, LV_ALIGN_TOP_LEFT); + lv_obj_set_pos(ui_Image_Main_Thermal_AGC_ROI, disp_x, disp_y); + lv_obj_set_size(ui_Image_Main_Thermal_AGC_ROI, disp_w, disp_h); + } -/** @brief Event handler for ROI rectangle touch interactions. - * - Normal drag at edges: Immediate resize - * - Long press inside center: Activate move mode - */ -static void ROI_Rectangle_Event_Handler(lv_event_t *e) -{ - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t *obj = (lv_obj_t *)lv_event_get_target(e); - - if (code == LV_EVENT_PRESSED) { - lv_indev_t *indev = lv_indev_get_act(); - lv_point_t point; - lv_area_t roi_area; - - lv_indev_get_point(indev, &point); - - /* Store initial touch position and ROI state */ - _GUITask_State.ROI_DragStartX = point.x; - _GUITask_State.ROI_DragStartY = point.y; - _GUITask_State.ROI_InitialX = lv_obj_get_x(obj); - _GUITask_State.ROI_InitialY = lv_obj_get_y(obj); - _GUITask_State.ROI_InitialW = lv_obj_get_width(obj); - _GUITask_State.ROI_InitialH = lv_obj_get_height(obj); - - /* Get absolute position of ROI on screen */ - lv_obj_get_coords(obj, &roi_area); - - /* Calculate touch position relative to ROI (not screen) */ - int32_t rel_x = point.x - roi_area.x1; - int32_t rel_y = point.y - roi_area.y1; - int32_t edge_threshold = 20; /* pixels from edge to trigger resize */ - - bool near_left = rel_x < edge_threshold; - bool near_right = rel_x > _GUITask_State.ROI_InitialW - edge_threshold; - bool near_top = rel_y < edge_threshold; - bool near_bottom = rel_y > _GUITask_State.ROI_InitialH - edge_threshold; - - /* Determine resize mode - allow combining edges (e.g., corner resize) */ - _GUITask_State.ROI_ResizeMode = 0; - if (near_left) { - _GUITask_State.ROI_ResizeMode |= 1; /* Left edge */ - } else if (near_right) { - _GUITask_State.ROI_ResizeMode |= 2; /* Right edge */ - } else if (near_top) { - _GUITask_State.ROI_ResizeMode |= 4; /* Top edge */ - } else if (near_bottom) { - _GUITask_State.ROI_ResizeMode |= 8; /* Bottom edge */ + break; } + case ROI_TYPE_VIDEO_FOCUS: { + if (ui_Image_Main_Thermal_Video_Focus_ROI != NULL) { + lv_obj_set_align(ui_Image_Main_Thermal_Video_Focus_ROI, LV_ALIGN_TOP_LEFT); + lv_obj_set_pos(ui_Image_Main_Thermal_Video_Focus_ROI, disp_x, disp_y); + lv_obj_set_size(ui_Image_Main_Thermal_Video_Focus_ROI, disp_w, disp_h); + } - /* If touch is at edge/corner, activate resize immediately */ - if (_GUITask_State.ROI_ResizeMode != 0) { - _GUITask_State.ROI_EditMode = true; - ESP_LOGD(TAG, "ROI RESIZE activated - mode=%d (1=left, 2=right, 4=top, 8=bottom) rel_pos=(%ld,%ld)", - _GUITask_State.ROI_ResizeMode, rel_x, rel_y); - } else { - /* Touch is in center - wait for long press to activate move mode */ - _GUITask_State.ROI_EditMode = false; - ESP_LOGD(TAG, "ROI center pressed - waiting for long press to activate MOVE mode"); + break; } - } else if (code == LV_EVENT_LONG_PRESSED) { - /* Long press detected - only activate move mode if touch was in center (ResizeMode == 0) */ - if (_GUITask_State.ROI_ResizeMode == 0) { - _GUITask_State.ROI_EditMode = true; - ESP_LOGD(TAG, "ROI MOVE mode ACTIVATED after long press"); + default: { + ESP_LOGW(TAG, "Invalid GUI ROI type: %d", ROI.Type); + return; } - } else if (code == LV_EVENT_PRESSING && _GUITask_State.ROI_EditMode) { - lv_indev_t *indev = lv_indev_get_act(); - lv_point_t point; - lv_indev_get_point(indev, &point); - - /* Calculate drag delta */ - int32_t delta_x = point.x - _GUITask_State.ROI_DragStartX; - int32_t delta_y = point.y - _GUITask_State.ROI_DragStartY; - - int32_t img_width = lv_obj_get_width(ui_Image_Thermal); - int32_t img_height = lv_obj_get_height(ui_Image_Thermal); - int32_t min_size = 15; /* Minimum ROI size in display pixels */ - - if (_GUITask_State.ROI_ResizeMode == 0) { - /* Move mode */ - int32_t new_x = _GUITask_State.ROI_InitialX + delta_x; - int32_t new_y = _GUITask_State.ROI_InitialY + delta_y; - - if (new_x < 0) { - new_x = 0; - } else if (new_y < 0) { - new_y = 0; - } else if (new_x + _GUITask_State.ROI_InitialW > img_width) { - new_x = img_width - _GUITask_State.ROI_InitialW; - } else if (new_y + _GUITask_State.ROI_InitialH > img_height) { - new_y = img_height - _GUITask_State.ROI_InitialH; - } - - lv_obj_set_pos(obj, new_x, new_y); - } else { - /* Resize mode */ - int32_t new_x = _GUITask_State.ROI_InitialX; - int32_t new_y = _GUITask_State.ROI_InitialY; - int32_t new_w = _GUITask_State.ROI_InitialW; - int32_t new_h = _GUITask_State.ROI_InitialH; - - /* Resize left edge */ - if (_GUITask_State.ROI_ResizeMode & 1) { - new_x = _GUITask_State.ROI_InitialX + delta_x; - new_w = _GUITask_State.ROI_InitialW - delta_x; - if (new_x < 0) { - new_w += new_x; - new_x = 0; - } else if (new_w < min_size) { - new_x = _GUITask_State.ROI_InitialX + _GUITask_State.ROI_InitialW - min_size; - new_w = min_size; - } - } + } - /* Resize right edge */ - if (_GUITask_State.ROI_ResizeMode & 2) { - new_w = _GUITask_State.ROI_InitialW + delta_x; - if (new_x + new_w > img_width) { - new_w = img_width - new_x; - } else if (new_w < min_size) { - new_w = min_size; - } - } + /* Save the new ROI to NVS */ + if (SettingsManager_Get(&App_Settings) == ESP_OK) { + if (App_Settings.Lepton.ROI[ROI.Type].x == ROI.x && + App_Settings.Lepton.ROI[ROI.Type].y == ROI.y && + App_Settings.Lepton.ROI[ROI.Type].w == ROI.w && + App_Settings.Lepton.ROI[ROI.Type].h == ROI.h) { + ESP_LOGW(TAG, "ROI unchanged, not updating NVS"); + return; + } - /* Resize top edge */ - if (_GUITask_State.ROI_ResizeMode & 4) { - new_y = _GUITask_State.ROI_InitialY + delta_y; - new_h = _GUITask_State.ROI_InitialH - delta_y; - if (new_y < 0) { - new_h += new_y; - new_y = 0; - } else if (new_h < min_size) { - new_y = _GUITask_State.ROI_InitialY + _GUITask_State.ROI_InitialH - min_size; - new_h = min_size; - } - } + memcpy(&App_Settings.Lepton.ROI[ROI.Type], &ROI, sizeof(App_Settings_ROI_t)); + SettingsManager_SetLepton(&App_Settings.Lepton); + } - /* Resize bottom edge */ - if (_GUITask_State.ROI_ResizeMode & 8) { - new_h = _GUITask_State.ROI_InitialH + delta_y; - if (new_y + new_h > img_height) { - new_h = img_height - new_y; - } else if (new_h < min_size) { - new_h = min_size; - } - } + /* The Lepton task needs the ROI with the Lepton coordinates */ + Lepton_ROI = { + .Type = ROI.Type, + .x = (uint16_t)ROI.x, + .y = (uint16_t)ROI.y, + .w = (uint16_t)ROI.w, + .h = (uint16_t)ROI.h + }; - lv_obj_set_pos(obj, new_x, new_y); - lv_obj_set_size(obj, new_w, new_h); - } - } else if (code == LV_EVENT_RELEASED) { - /* Only process if edit mode was active (after long press) */ - if (_GUITask_State.ROI_EditMode) { - _GUITask_State.ROI_EditMode = false; - - /* Convert display coordinates back to Lepton coordinates */ - int32_t disp_x = lv_obj_get_x(obj); - int32_t disp_y = lv_obj_get_y(obj); - int32_t disp_w = lv_obj_get_width(obj); - int32_t disp_h = lv_obj_get_height(obj); - - int32_t img_width = lv_obj_get_width(ui_Image_Thermal); - int32_t img_height = lv_obj_get_height(ui_Image_Thermal); - - int32_t lepton_x = (disp_x * 160) / img_width; - int32_t lepton_y = (disp_y * 120) / img_height; - int32_t lepton_w = (disp_w * 160) / img_width; - int32_t lepton_h = (disp_h * 120) / img_height; - - /* Update ROI on Lepton camera */ - GUI_Update_ROI(lepton_x, lepton_y, lepton_w, lepton_h); - - ESP_LOGD(TAG, "ROI edit mode DEACTIVATED - changes saved"); - } else { - ESP_LOGD(TAG, "ROI released without edit mode (short press ignored)"); - } - } + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_ROI, &Lepton_ROI, sizeof(App_Settings_ROI_t), portMAX_DELAY); } /** @brief Create temperature gradient canvas for palette visualization. @@ -708,26 +546,27 @@ void Task_GUI(void *p_Parameters) lv_timer_handler(); /* Set the initial ROI FIRST to give it a size */ - GUI_Update_ROI(App_Context->Settings.Lepton.SpotmeterROI.x, App_Context->Settings.Lepton.SpotmeterROI.y, - App_Context->Settings.Lepton.SpotmeterROI.w, App_Context->Settings.Lepton.SpotmeterROI.h); - lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_PRESSED, NULL); - lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_PRESSING, NULL); - lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_RELEASED, NULL); + GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_SPOTMETER]); + GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_SPOTMETER]); + GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_SCENE]); + GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_AGC]); + GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_VIDEO_FOCUS]); GUI_Update_Info(); _GUITask_State.RunTask = true; while (_GUITask_State.RunTask) { EventBits_t EventBits; - App_Lepton_FrameReady_t LeptonEvent; + App_Lepton_FrameReady_t LeptonFrame; esp_task_wdt_reset(); /* Check for new thermal frame */ - if (xQueueReceive(App_Context->Lepton_FrameEventQueue, &LeptonEvent, 0) == pdTRUE) { + if (xQueueReceive(App_Context->Lepton_FrameEventQueue, &LeptonFrame, 0) == pdTRUE) { uint8_t *dst; uint32_t Image_Width; uint32_t Image_Height; + char temp_buf[16]; /* Scale from source (160x120) to destination (240x180) using bilinear interpolation */ dst = _GUITask_State.ThermalCanvasBuffer; @@ -741,28 +580,28 @@ void Task_GUI(void *p_Parameters) } /* Pre-calculate scaling factors (fixed-point 16.16) */ - uint32_t x_ratio = ((LeptonEvent.Width - 1) << 16) / Image_Width; - uint32_t y_ratio = ((LeptonEvent.Height - 1) << 16) / Image_Height; + uint32_t x_ratio = ((LeptonFrame.Width - 1) << 16) / Image_Width; + uint32_t y_ratio = ((LeptonFrame.Height - 1) << 16) / Image_Height; for (uint32_t dst_y = 0; dst_y < Image_Height; dst_y++) { uint32_t src_y_fixed = dst_y * y_ratio; uint32_t y0 = src_y_fixed >> 16; - uint32_t y1 = (y0 + 1 < LeptonEvent.Height) ? y0 + 1 : y0; + uint32_t y1 = (y0 + 1 < LeptonFrame.Height) ? y0 + 1 : y0; uint32_t y_frac = (src_y_fixed >> 8) & 0xFF; /* 8-bit fractional part */ uint32_t y_inv = 256 - y_frac; for (uint32_t dst_x = 0; dst_x < Image_Width; dst_x++) { uint32_t src_x_fixed = dst_x * x_ratio; uint32_t x0 = src_x_fixed >> 16; - uint32_t x1 = (x0 + 1 < LeptonEvent.Width) ? x0 + 1 : x0; + uint32_t x1 = (x0 + 1 < LeptonFrame.Width) ? x0 + 1 : x0; uint32_t x_frac = (src_x_fixed >> 8) & 0xFF; /* 8-bit fractional part */ uint32_t x_inv = 256 - x_frac; /* Get the four surrounding pixels */ - uint32_t idx00 = (y0 * LeptonEvent.Width + x0) * 3; - uint32_t idx10 = (y0 * LeptonEvent.Width + x1) * 3; - uint32_t idx01 = (y1 * LeptonEvent.Width + x0) * 3; - uint32_t idx11 = (y1 * LeptonEvent.Width + x1) * 3; + uint32_t idx00 = (y0 * LeptonFrame.Width + x0) * 3; + uint32_t idx10 = (y0 * LeptonFrame.Width + x1) * 3; + uint32_t idx01 = (y1 * LeptonFrame.Width + x0) * 3; + uint32_t idx11 = (y1 * LeptonFrame.Width + x1) * 3; /* Bilinear interpolation using fixed-point arithmetic (8.8 format) */ /* Weight: (256-x_frac)*(256-y_frac), x_frac*(256-y_frac), etc. */ @@ -771,20 +610,20 @@ void Task_GUI(void *p_Parameters) uint32_t w01 = (x_inv * y_frac) >> 8; uint32_t w11 = (x_frac * y_frac) >> 8; - uint32_t r = (LeptonEvent.Buffer[idx00 + 0] * w00 + - LeptonEvent.Buffer[idx10 + 0] * w10 + - LeptonEvent.Buffer[idx01 + 0] * w01 + - LeptonEvent.Buffer[idx11 + 0] * w11) >> 8; + uint32_t r = (LeptonFrame.Buffer[idx00 + 0] * w00 + + LeptonFrame.Buffer[idx10 + 0] * w10 + + LeptonFrame.Buffer[idx01 + 0] * w01 + + LeptonFrame.Buffer[idx11 + 0] * w11) >> 8; - uint32_t g = (LeptonEvent.Buffer[idx00 + 1] * w00 + - LeptonEvent.Buffer[idx10 + 1] * w10 + - LeptonEvent.Buffer[idx01 + 1] * w01 + - LeptonEvent.Buffer[idx11 + 1] * w11) >> 8; + uint32_t g = (LeptonFrame.Buffer[idx00 + 1] * w00 + + LeptonFrame.Buffer[idx10 + 1] * w10 + + LeptonFrame.Buffer[idx01 + 1] * w01 + + LeptonFrame.Buffer[idx11 + 1] * w11) >> 8; - uint32_t b_val = (LeptonEvent.Buffer[idx00 + 2] * w00 + - LeptonEvent.Buffer[idx10 + 2] * w10 + - LeptonEvent.Buffer[idx01 + 2] * w01 + - LeptonEvent.Buffer[idx11 + 2] * w11) >> 8; + uint32_t b_val = (LeptonFrame.Buffer[idx00 + 2] * w00 + + LeptonFrame.Buffer[idx10 + 2] * w10 + + LeptonFrame.Buffer[idx01 + 2] * w01 + + LeptonFrame.Buffer[idx11 + 2] * w11) >> 8; /* Destination pixel index (rotated 180 degrees) */ uint32_t rot_y = Image_Height - 1 - dst_y; @@ -802,12 +641,22 @@ void Task_GUI(void *p_Parameters) } } + /* Max temperature (top of gradient) */ + float temp_max_celsius = (LeptonFrame.Max / 100.0f) - 273.15f; + snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_max_celsius); + lv_label_set_text(ui_Label_TempScaleMax, temp_buf); + + /* Min temperature (bottom of gradient) */ + float temp_min_celsius = (LeptonFrame.Min / 100.0f) - 273.15f; + snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_min_celsius); + lv_label_set_text(ui_Label_TempScaleMin, temp_buf); + /* Trigger LVGL to redraw the image */ lv_obj_invalidate(ui_Image_Thermal); - ESP_LOGD(TAG, "Updated thermal image display (src: %ux%u -> dst: %ux%u)", LeptonEvent.Width, LeptonEvent.Height, + ESP_LOGD(TAG, "Updated thermal image display (src: %ux%u -> dst: %ux%u)", LeptonFrame.Width, LeptonFrame.Height, Image_Width, Image_Height); - /* Update network frame for server streaming (if server is running) */ + /* Update network frame for server streaming if server is running */ if (Server_isRunning()) { if (xSemaphoreTake(_GUITask_State.NetworkFrame.mutex, 0) == pdTRUE) { /* Convert scaled RGB565 buffer to RGB888 for network transmission */ @@ -832,11 +681,6 @@ void Task_GUI(void *p_Parameters) _GUITask_State.NetworkFrame.height = Image_Height; _GUITask_State.NetworkFrame.timestamp = esp_timer_get_time() / 1000; - /* Update temperatures from spotmeter data */ - _GUITask_State.NetworkFrame.temp_min = _GUITask_State.SpotmeterInfo.Min; - _GUITask_State.NetworkFrame.temp_max = _GUITask_State.SpotmeterInfo.Max; - _GUITask_State.NetworkFrame.temp_avg = _GUITask_State.SpotmeterInfo.AverageTemperature; - xSemaphoreGive(_GUITask_State.NetworkFrame.mutex); } @@ -873,7 +717,6 @@ void Task_GUI(void *p_Parameters) lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_EMPTY); } - /* Update percentage text */ snprintf(buf, sizeof(buf), "%d%%", _GUITask_State.BatteryInfo.Percentage); lv_label_set_text(ui_Label_Main_Battery_Remaining, buf); @@ -915,22 +758,16 @@ void Task_GUI(void *p_Parameters) xEventGroupClearBits(_GUITask_State.EventGroup, SD_CARD_MOUNT_ERROR); } else if (EventBits & LEPTON_SPOTMETER_READY) { - char temp_buf[16]; - - /* Max temperature (top of gradient) */ - float temp_max_celsius = _GUITask_State.SpotmeterInfo.Max; - snprintf(temp_buf, sizeof(temp_buf), "%.1f°C", temp_max_celsius); - lv_label_set_text(ui_Label_TempScaleMax, temp_buf); - - /* Min temperature (bottom of gradient) */ - float temp_min_celsius = _GUITask_State.SpotmeterInfo.Min;; - snprintf(temp_buf, sizeof(temp_buf), "%.1f°C", temp_min_celsius); - lv_label_set_text(ui_Label_TempScaleMin, temp_buf); + // TODO: Can we move this to the network task? + if (Server_isRunning()) { + if (xSemaphoreTake(_GUITask_State.NetworkFrame.mutex, 0) == pdTRUE) { + _GUITask_State.NetworkFrame.temp_min = _GUITask_State.ROIResult.Min; + _GUITask_State.NetworkFrame.temp_max = _GUITask_State.ROIResult.Max; + _GUITask_State.NetworkFrame.temp_avg = _GUITask_State.ROIResult.Average; - ESP_LOGD(TAG, "Updated spotmeter temperatures on GUI: Min=%.2f K, Max=%.2f K, Avg=%.2f K", - _GUITask_State.SpotmeterInfo.Min, - _GUITask_State.SpotmeterInfo.Max, - _GUITask_State.SpotmeterInfo.AverageTemperature); + xSemaphoreGive(_GUITask_State.NetworkFrame.mutex); + } + } xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_SPOTMETER_READY); } else if (EventBits & LEPTON_UPTIME_READY) { @@ -953,9 +790,28 @@ void Task_GUI(void *p_Parameters) xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_TEMP_READY); } else if (EventBits & LEPTON_PIXEL_TEMPERATURE_READY) { - GUI_Helper_GetSpotTemperature(_GUITask_State.SpotTemperature); + char buf[16]; + + snprintf(buf, sizeof(buf), "%.2f °C", _GUITask_State.SpotTemperature); + lv_label_set_text(ui_Label_Main_Thermal_PixelTemperature, buf); xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); + } else if (EventBits & LEPTON_SCENE_STATISTICS_READY) { + char temp_buf[16]; + + float temp_max_celsius = _GUITask_State.ROIResult.Max; + snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_max_celsius); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Max, temp_buf); + + float temp_min_celsius = _GUITask_State.ROIResult.Min; + snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_min_celsius); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Min, temp_buf); + + float temp_mean_celsius = _GUITask_State.ROIResult.Mean ; + snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_mean_celsius); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Mean, temp_buf); + + xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_SCENE_STATISTICS_READY); } _lock_acquire(&_GUITask_State.LVGL_API_Lock); @@ -1072,28 +928,16 @@ esp_err_t GUI_Task_Init(void) lv_obj_add_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); lv_obj_remove_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_CLICKABLE); - ESP_LOGI(TAG, "Touch debug visualization enabled on ui_Main screen"); + ESP_LOGD(TAG, "Touch debug visualization enabled on ui_Main screen"); #endif - /* Register event handler for ROI touch interactions (drag & resize) */ - lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_PRESSED, NULL); - lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_LONG_PRESSED, NULL); - lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_PRESSING, NULL); - lv_obj_add_event_cb(ui_Image_Main_Thermal_ROI, ROI_Rectangle_Event_Handler, LV_EVENT_RELEASED, NULL); - - /* Register ROI button events: long-press for reset, click for toggle */ - lv_obj_add_event_cb(ui_Button_Main_ROI, ROI_Clicked_Event_Handler, LV_EVENT_LONG_PRESSED, NULL); - lv_obj_add_event_cb(ui_Button_Main_ROI, ROI_Clicked_Event_Handler, LV_EVENT_CLICKED, NULL); - - ESP_LOGI(TAG, "ROI event handlers registered and configured for touch interaction"); - - _GUITask_State.ROI_EditMode = false; - _GUITask_State.ROI_LongPressActive = false; - /* Initialize network frame for server streaming */ _GUITask_State.NetworkFrame.mutex = xSemaphoreCreateMutex(); if (_GUITask_State.NetworkFrame.mutex == NULL) { ESP_LOGE(TAG, "Failed to create NetworkFrame mutex!"); + heap_caps_free(_GUITask_State.ThermalCanvasBuffer); + heap_caps_free(_GUITask_State.GradientCanvasBuffer); + heap_caps_free(_GUITask_State.NetworkRGBBuffer); return ESP_ERR_NO_MEM; } @@ -1168,6 +1012,7 @@ esp_err_t GUI_Task_Stop(void) return ESP_OK; } + esp_task_wdt_delete(_GUITask_State.GUI_Handle); vTaskDelete(_GUITask_State.GUI_Handle); _GUITask_State.GUI_Handle = NULL; diff --git a/main/Application/Tasks/GUI/guiTask.h b/main/Application/Tasks/GUI/guiTask.h index e9b04f3..f57dad6 100644 --- a/main/Application/Tasks/GUI/guiTask.h +++ b/main/Application/Tasks/GUI/guiTask.h @@ -33,14 +33,29 @@ ESP_EVENT_DECLARE_BASE(GUI_EVENTS); +/** @brief Initialize the GUI task. + * @return ESP_OK on success, error code otherwise + */ esp_err_t GUI_Task_Init(void); +/** @brief Deinitialize the GUI task. + */ void GUI_Task_Deinit(void); +/** @brief Start the GUI task. + * @param p_AppContext Pointer to the application context + * @return ESP_OK on success, error code otherwise + */ esp_err_t GUI_Task_Start(App_Context_t *p_AppContext); +/** @brief Stop the GUI task. + * @return ESP_OK on success, error code otherwise + */ esp_err_t GUI_Task_Stop(void); +/** @brief Check if the GUI task is running. + * @return true if running, false otherwise + */ bool GUI_Task_isRunning(void); /** @brief Toggle ROI (Region of Interest) edit mode. diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp index 2c4c5d2..f509b88 100644 --- a/main/Application/Tasks/Lepton/leptonTask.cpp +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -42,6 +42,7 @@ #define LEPTON_TASK_UPDATE_UPTIME_REQUEST BIT3 #define LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE BIT4 #define LEPTON_TASK_UPDATE_SPOTMETER BIT5 +#define LEPTON_TASK_UPDATE_SCENE_STATISTICS BIT6 ESP_EVENT_DEFINE_BASE(LEPTON_EVENTS); @@ -59,7 +60,7 @@ typedef struct { Lepton_FrameBuffer_t RawFrame; Lepton_Conf_t LeptonConf; Lepton_t Lepton; - Lepton_ROI_t ROI; + App_Settings_ROI_t ROI; App_GUI_Screenposition_t ScreenPosition; } Lepton_Task_State_t; @@ -73,10 +74,7 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int switch (ID) { case GUI_EVENT_REQUEST_ROI: { - _LeptonTask_State.ROI.Start_Col = ((App_Settings_ROI_t *)p_Data)->x; - _LeptonTask_State.ROI.Start_Row = ((App_Settings_ROI_t *)p_Data)->y; - _LeptonTask_State.ROI.End_Col = ((App_Settings_ROI_t *)p_Data)->x + ((App_Settings_ROI_t *)p_Data)->w - 1; - _LeptonTask_State.ROI.End_Row = ((App_Settings_ROI_t *)p_Data)->y + ((App_Settings_ROI_t *)p_Data)->h - 1; + memcpy(&_LeptonTask_State.ROI, p_Data, sizeof(App_Settings_ROI_t)); xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_ROI_REQUEST); @@ -103,6 +101,11 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int break; } + case GUI_EVENT_REQUEST_SCENE_STATISTICS: { + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SCENE_STATISTICS); + + break; + } default: { ESP_LOGW(TAG, "Unhandled GUI event ID: %d", ID); break; @@ -151,8 +154,24 @@ static void Task_Lepton(void *p_Parameters) esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_READY, &DeviceInfo, sizeof(App_Lepton_Device_t), portMAX_DELAY); + Lepton_FluxLinearParams_t FluxParams; + Lepton_GetFluxLinearParameters(&_LeptonTask_State.Lepton, &FluxParams); + ESP_LOGI(TAG, "Flux Linear Parameters - Scene Emissivity: %u, TBkgK: %u, TauWindow: %u, TWindowK: %u, TauAtm: %u, TAtmK: %u, ReflWindow: %u, TReflK: %u", + FluxParams.SceneEmissivity, + FluxParams.TBkgK, + FluxParams.TauWindow, + FluxParams.TWindowK, + FluxParams.TauAtm, + FluxParams.TAtmK, + FluxParams.ReflWindow, + FluxParams.TReflK); + ESP_LOGD(TAG, "Start image capturing..."); + if (Lepton_SetEmissivity(&_LeptonTask_State.Lepton, (Lepton_Emissivity_t)App_Context->Settings.Lepton.Emissivity) != LEPTON_ERR_OK) { + ESP_LOGE(TAG, "Failed to set emissivity!"); + } + if (Lepton_StartCapture(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrameQueue) != LEPTON_ERR_OK) { ESP_LOGE(TAG, "Can not start image capturing!"); esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); @@ -169,6 +188,9 @@ static void Task_Lepton(void *p_Parameters) uint8_t WriteBufferIdx; uint8_t *WriteBuffer; Lepton_Telemetry_t Telemetry; + Lepton_VideoFormat_t VideoFormat; + int16_t Min = 0; + int16_t Max = 0; if (_LeptonTask_State.RawFrame.Telemetry_Buffer != NULL) { memcpy(&Telemetry, _LeptonTask_State.RawFrame.Telemetry_Buffer, sizeof(Lepton_Telemetry_t)); @@ -191,8 +213,21 @@ static void Task_Lepton(void *p_Parameters) continue; } - Lepton_Raw14ToRGB(_LeptonTask_State.RawFrame.Image_Buffer, WriteBuffer, _LeptonTask_State.RawFrame.Width, - _LeptonTask_State.RawFrame.Height); + /* Process frame based on video format */ + Lepton_GetVideoFormat(&_LeptonTask_State.Lepton, &VideoFormat); + + if (VideoFormat == LEPTON_FORMAT_RGB888) { + /* RGB888: Data is already in RGB format, just copy it */ + size_t ImageSize = _LeptonTask_State.RawFrame.Width * _LeptonTask_State.RawFrame.Height * + _LeptonTask_State.RawFrame.BytesPerPixel; + memcpy(WriteBuffer, _LeptonTask_State.RawFrame.Image_Buffer, ImageSize); + ESP_LOGD(TAG, "Copied RGB888 frame: %ux%u (%u bytes)", _LeptonTask_State.RawFrame.Width, + _LeptonTask_State.RawFrame.Height, static_cast(ImageSize)); + } else { + /* RAW14: Convert to RGB */ + Lepton_Raw14ToRGB(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrame.Image_Buffer, WriteBuffer, &Min, &Max, _LeptonTask_State.RawFrame.Width, + _LeptonTask_State.RawFrame.Height); + } /* Mark buffer as ready and update read buffer index */ if (xSemaphoreTake(_LeptonTask_State.BufferMutex, 100 / portTICK_PERIOD_MS) == pdTRUE) { @@ -208,7 +243,9 @@ static void Task_Lepton(void *p_Parameters) .Buffer = WriteBuffer, .Width = _LeptonTask_State.RawFrame.Width, .Height = _LeptonTask_State.RawFrame.Height, - .Channels = 3 + .Channels = 3, + .Min = Min, + .Max = Max }; /* Use xQueueOverwrite to always have the latest frame */ @@ -221,20 +258,46 @@ static void Task_Lepton(void *p_Parameters) EventBits = xEventGroupGetBits(_LeptonTask_State.EventGroup); if (EventBits & LEPTON_TASK_UPDATE_ROI_REQUEST) { - ESP_LOGD(TAG, "Before SetSpotmeterROI - I2C Dev: %p", - _LeptonTask_State.Lepton.Internal.CCI.I2C_Dev_Handle); - - if (Lepton_SetSpotmeterROI(&_LeptonTask_State.Lepton, &_LeptonTask_State.ROI) == LEPTON_ERR_OK) { - Lepton_ROI_t CurrentROI; - - Lepton_GetSpotmeterROI(&_LeptonTask_State.Lepton, &CurrentROI); - ESP_LOGD(TAG, "Current Lepton ROI - Start_Col: %u, Start_Row: %u, End_Col: %u, End_Row: %u", - CurrentROI.Start_Col, - CurrentROI.Start_Row, - CurrentROI.End_Col, - CurrentROI.End_Row); + Lepton_ROI_t ROI; + Lepton_Error_t Error; + + ROI.Start_Col = _LeptonTask_State.ROI.x; + ROI.Start_Row = _LeptonTask_State.ROI.y; + ROI.End_Col = _LeptonTask_State.ROI.x + _LeptonTask_State.ROI.w - 1; + ROI.End_Row = _LeptonTask_State.ROI.y + _LeptonTask_State.ROI.h - 1; + + switch(_LeptonTask_State.ROI.Type) { + case ROI_TYPE_SPOTMETER: { + Error = Lepton_SetSpotmeterROI(&_LeptonTask_State.Lepton, &ROI); + break; + } + case ROI_TYPE_SCENE: { + Error = Lepton_SetSceneROI(&_LeptonTask_State.Lepton, &ROI); + break; + } + case ROI_TYPE_AGC: { + Error = Lepton_SetAGCROI(&_LeptonTask_State.Lepton, &ROI); + break; + } + case ROI_TYPE_VIDEO_FOCUS: { + Error = Lepton_SetVideoFocusROI(&_LeptonTask_State.Lepton, &ROI); + break; + } + default: { + ESP_LOGW(TAG, "Invalid ROI type in GUI event: %d", _LeptonTask_State.ROI.Type); + return; + } + } + + if (Error == LEPTON_ERR_OK) { + ESP_LOGD(TAG, "New Lepton ROI (Type %d) - Start_Col: %u, Start_Row: %u, End_Col: %u, End_Row: %u", + _LeptonTask_State.ROI.Type, + ROI.Start_Col, + ROI.Start_Row, + ROI.End_Col, + ROI.End_Row); } else { - ESP_LOGW(TAG, "Failed to update Lepton ROI!"); + ESP_LOGE(TAG, "Failed to update Lepton ROI with type %d!", _LeptonTask_State.ROI.Type); } xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_ROI_REQUEST); @@ -243,7 +306,7 @@ static void Task_Lepton(void *p_Parameters) uint16_t AUX_Temp; App_Lepton_Temperatures_t Temperatures; - Lepton_GetTemp(&_LeptonTask_State.Lepton, &FPA_Temp, &AUX_Temp); + Lepton_GetTemperature(&_LeptonTask_State.Lepton, &FPA_Temp, &AUX_Temp); Temperatures.FPA = (static_cast(FPA_Temp) * 0.01f) - 273.0f; Temperatures.AUX = (static_cast(AUX_Temp) * 0.01f) - 273.0f; @@ -269,9 +332,12 @@ static void Task_Lepton(void *p_Parameters) int16_t x; int16_t y; float Temperature; + Lepton_VideoFormat_t VideoFormat; - if (_LeptonTask_State.RawFrame.Width == 0 || _LeptonTask_State.RawFrame.Height == 0) { - ESP_LOGW(TAG, "Invalid Lepton frame dimensions, cannot get pixel temperature"); + Lepton_GetVideoFormat(&_LeptonTask_State.Lepton, &VideoFormat); + if (((_LeptonTask_State.RawFrame.Width == 0) || (_LeptonTask_State.RawFrame.Height == 0)) && + (VideoFormat != LEPTON_FORMAT_RAW14)) { + ESP_LOGW(TAG, "Invalid Lepton frame! Cannot get pixel temperature!"); xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); continue; } @@ -280,9 +346,11 @@ static void Task_Lepton(void *p_Parameters) x = (_LeptonTask_State.ScreenPosition.x * _LeptonTask_State.RawFrame.Width) / _LeptonTask_State.ScreenPosition.Width; y = (_LeptonTask_State.ScreenPosition.y * _LeptonTask_State.RawFrame.Height) / _LeptonTask_State.ScreenPosition.Height; - ESP_LOGD(TAG, "Crosshair center in Lepton Frame: (%d,%d), size (%d,%d)", x, y, _LeptonTask_State.RawFrame.Width, _LeptonTask_State.RawFrame.Height); + ESP_LOGD(TAG, "Crosshair center in Lepton Frame: (%d,%d), size (%d,%d)", x, y, _LeptonTask_State.RawFrame.Width, + _LeptonTask_State.RawFrame.Height); - if (Lepton_GetPixelTemperature(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrame.Image_Buffer[(y * _LeptonTask_State.RawFrame.Width) + x], + if (Lepton_GetPixelTemperature(&_LeptonTask_State.Lepton, + _LeptonTask_State.RawFrame.Image_Buffer[(y * _LeptonTask_State.RawFrame.Width) + x], &Temperature) == LEPTON_ERR_OK) { esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE, &Temperature, sizeof(float), 0); } else { @@ -291,14 +359,14 @@ static void Task_Lepton(void *p_Parameters) xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); } else if (EventBits & LEPTON_TASK_UPDATE_SPOTMETER) { - Lepton_Spotmeter_Float_t Spotmeter; + Lepton_Spotmeter_t Spotmeter; ESP_LOGD(TAG, "Getting spotmeter - I2C Bus: %p, I2C Dev: %p", - _LeptonTask_State.Lepton.Internal.CCI.I2C_Bus_Handle, - _LeptonTask_State.Lepton.Internal.CCI.I2C_Dev_Handle); + _LeptonTask_State.Lepton.Internal.CCI.I2C_Bus_Handle, + _LeptonTask_State.Lepton.Internal.CCI.I2C_Dev_Handle); if (Lepton_GetSpotmeter(&_LeptonTask_State.Lepton, &Spotmeter) == LEPTON_ERR_OK) { - App_Lepton_Spotmeter_t App_Lepton_Spotmeter; + App_Lepton_ROI_Result_t App_Lepton_Spotmeter; ESP_LOGD(TAG, "Spotmeter: Spot=%uK, Min=%uK, Max=%uK", Spotmeter.Value, @@ -307,15 +375,35 @@ static void Task_Lepton(void *p_Parameters) App_Lepton_Spotmeter.Min = Spotmeter.Min - 273.0f; App_Lepton_Spotmeter.Max = Spotmeter.Max - 273.0f; - App_Lepton_Spotmeter.AverageTemperature = Spotmeter.Value - 273.0f; + App_Lepton_Spotmeter.Average = Spotmeter.Value - 273.0f; - esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_SPOTMETER, &App_Lepton_Spotmeter, sizeof(App_Lepton_Spotmeter_t), + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_SPOTMETER, &App_Lepton_Spotmeter, sizeof(App_Lepton_ROI_Result_t), 0); } else { ESP_LOGW(TAG, "Failed to read spotmeter!"); } xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SPOTMETER); + } else if (EventBits & LEPTON_TASK_UPDATE_SCENE_STATISTICS) { + Lepton_SceneStatistics_t SceneStats; + + if (Lepton_GetSceneStatistics(&_LeptonTask_State.Lepton, &SceneStats) == LEPTON_ERR_OK) { + App_Lepton_ROI_Result_t App_Lepton_Scene; + + App_Lepton_Scene.Min = SceneStats.MinIntensity; + App_Lepton_Scene.Max = SceneStats.MaxIntensity; + App_Lepton_Scene.Average = SceneStats.MeanIntensity; + + ESP_LOGD(TAG, "Scene Statistics: Min=%.2f°C, Max=%.2f°C, Average=%.2f°C", + App_Lepton_Scene.Min, App_Lepton_Scene.Max, App_Lepton_Scene.Average); + + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_SCENE_STATISTICS, &App_Lepton_Scene, + sizeof(App_Lepton_ROI_Result_t), 0); + } else { + ESP_LOGW(TAG, "Failed to read scene statistics!"); + } + + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SCENE_STATISTICS); } } @@ -338,7 +426,7 @@ esp_err_t Lepton_Task_Init(void) return ESP_OK; } - ESP_LOGI(TAG, "Initializing Lepton Task"); + ESP_LOGD(TAG, "Initializing Lepton Task"); _LeptonTask_State.CurrentReadBuffer = 0; _LeptonTask_State.InitializationRetries = 0; @@ -359,11 +447,31 @@ esp_err_t Lepton_Task_Init(void) return ESP_ERR_NO_MEM; } - /* Allocate 2 RGB buffers for ping-pong buffering */ - _LeptonTask_State.RGB_Buffer[0] = reinterpret_cast(heap_caps_malloc(LEPTON_IMAGE_WIDTH * LEPTON_IMAGE_HEIGHT - * 3, MALLOC_CAP_SPIRAM)); - _LeptonTask_State.RGB_Buffer[1] = reinterpret_cast(heap_caps_malloc(LEPTON_IMAGE_WIDTH * LEPTON_IMAGE_HEIGHT - * 3, MALLOC_CAP_SPIRAM)); + /* Initialize Lepton configuration and I2C BEFORE allocating large buffers */ + _LeptonTask_State.LeptonConf = LEPTON_DEFAULT_CONF; + LEPTON_ASSIGN_FUNC(_LeptonTask_State.LeptonConf, NULL, NULL, I2CM_Write, I2CM_Read); + LEPTON_ASSIGN_I2C_HANDLE(_LeptonTask_State.LeptonConf, DevicesManager_GetI2CBusHandle()); + + /* Initialize Lepton (this creates I2C device handle) before framebuffer allocation */ + Lepton_Error = Lepton_Init(&_LeptonTask_State.Lepton, &_LeptonTask_State.LeptonConf); + if (Lepton_Error != LEPTON_ERR_OK) { + ESP_LOGE(TAG, "Lepton initialization failed with error: %d!", Lepton_Error); + + vSemaphoreDelete(_LeptonTask_State.BufferMutex); + vEventGroupDelete(_LeptonTask_State.EventGroup); + + return ESP_FAIL; + } + + /* Allocate RGB buffers - both RAW14 and RGB888 use 160x120 resolution + * RAW14: 160x120x3 = 57,600 bytes (after conversion to RGB) + * RGB888: 160x120x3 = 57,600 bytes (native RGB data) + */ + size_t RGB_Buffer_Size = 160 * 120 * 3; + + _LeptonTask_State.RGB_Buffer[0] = reinterpret_cast(heap_caps_malloc(RGB_Buffer_Size, MALLOC_CAP_SPIRAM)); + _LeptonTask_State.RGB_Buffer[1] = reinterpret_cast(heap_caps_malloc(RGB_Buffer_Size, MALLOC_CAP_SPIRAM)); + if ((_LeptonTask_State.RGB_Buffer[0] == NULL) || (_LeptonTask_State.RGB_Buffer[1] == NULL)) { ESP_LOGE(TAG, "Can not allocate RGB buffers!"); @@ -372,15 +480,18 @@ esp_err_t Lepton_Task_Init(void) } if (_LeptonTask_State.RGB_Buffer[1]) { - heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); + heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); } + Lepton_Deinit(&_LeptonTask_State.Lepton); vSemaphoreDelete(_LeptonTask_State.BufferMutex); vEventGroupDelete(_LeptonTask_State.EventGroup); return ESP_ERR_NO_MEM; } + ESP_LOGD(TAG, "RGB buffers allocated: 2 x %u bytes", static_cast(RGB_Buffer_Size)); + /* Create internal queue to receive raw frames from VoSPI capture task */ _LeptonTask_State.RawFrameQueue = xQueueCreate(1, sizeof(Lepton_FrameBuffer_t)); if (_LeptonTask_State.RawFrameQueue == NULL) { @@ -388,38 +499,17 @@ esp_err_t Lepton_Task_Init(void) heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); + Lepton_Deinit(&_LeptonTask_State.Lepton); vSemaphoreDelete(_LeptonTask_State.BufferMutex); vEventGroupDelete(_LeptonTask_State.EventGroup); return ESP_ERR_NO_MEM; } - _LeptonTask_State.LeptonConf = LEPTON_DEFAULT_CONF; - LEPTON_ASSIGN_FUNC(_LeptonTask_State.LeptonConf, NULL, NULL, I2CM_Write, I2CM_Read); - LEPTON_ASSIGN_I2C_HANDLE(_LeptonTask_State.LeptonConf, DevicesManager_GetI2CBusHandle()); - - ESP_LOGI(TAG, "I2C Bus Handle before init: %p", _LeptonTask_State.LeptonConf.CCI.I2C_Bus_Handle); - - Lepton_Error = Lepton_Init(&_LeptonTask_State.Lepton, &_LeptonTask_State.LeptonConf); - if (Lepton_Error != LEPTON_ERR_OK) { - ESP_LOGE(TAG, "Lepton initialization failed with error: %d!", Lepton_Error); - - vQueueDelete(_LeptonTask_State.RawFrameQueue); - heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); - heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); - vSemaphoreDelete(_LeptonTask_State.BufferMutex); - vEventGroupDelete(_LeptonTask_State.EventGroup); - - return ESP_FAIL; - } - - ESP_LOGI(TAG, "I2C Bus Handle after init: %p", _LeptonTask_State.Lepton.Internal.CCI.I2C_Bus_Handle); - ESP_LOGI(TAG, "I2C Dev Handle after init: %p", _LeptonTask_State.Lepton.Internal.CCI.I2C_Dev_Handle); - /* Use the event loop to receive control signals from other tasks */ esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL); - ESP_LOGI(TAG, "Lepton Task initialized"); + ESP_LOGD(TAG, "Lepton Task initialized"); _LeptonTask_State.isInitialized = true; diff --git a/main/Application/Tasks/Lepton/leptonTask.h b/main/Application/Tasks/Lepton/leptonTask.h index b301874..791a6f4 100644 --- a/main/Application/Tasks/Lepton/leptonTask.h +++ b/main/Application/Tasks/Lepton/leptonTask.h @@ -32,10 +32,19 @@ #include "Application/application.h" #include "Application/Manager/Devices/devices.h" +/** @brief Initialize the Lepton task. + * @return ESP_OK on success, error code otherwise + */ esp_err_t Lepton_Task_Init(void); +/** @brief Deinitialize the Lepton task. + */ void Lepton_Task_Deinit(void); +/** @brief Start the Lepton task. + * @param p_AppContext Pointer to the application context + * @return ESP_OK on success, error code otherwise + */ esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext); /** @brief Stop the Lepton task diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index 5b313e1..cdbabfe 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -30,8 +30,6 @@ #include #include -#include - #include #include "networkTask.h" @@ -45,17 +43,20 @@ #define NETWORK_TASK_WIFI_DISCONNECTED BIT4 #define NETWORK_TASK_PROV_TIMEOUT BIT5 #define NETWORK_TASK_OPEN_WIFI_REQUEST BIT6 +#define NETWORK_TASK_SNTP_TIMEZONE_SET BIT7 +#define NETWORK_TASK_WIFI_CREDENTIALS_UPDATED BIT8 typedef struct { bool isInitialized; + bool isConnected; bool Running; + bool RunTask; TaskHandle_t TaskHandle; EventGroupHandle_t EventGroup; uint32_t StartTime; - bool RunTask; - bool isConnected; Network_State_t State; - Network_WiFiMode_t WiFi_Mode; + const char *Timezone; + App_Context_t *AppContext; } Network_Task_State_t; static Network_Task_State_t _NetworkTask_State; @@ -71,20 +72,39 @@ static const char *TAG = "network_task"; static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) { switch (ID) { + case NETWORK_EVENT_CREDENTIALS_UPDATED: { + Network_WiFi_Credentials_t *Credentials = (Network_WiFi_Credentials_t *)p_Data; + + ESP_LOGD(TAG, "WiFi credentials updated"); + + memcpy(&_NetworkTask_State.AppContext->Settings.WiFi.SSID, + Credentials->SSID, + sizeof(_NetworkTask_State.AppContext->Settings.WiFi.SSID)); + memcpy(&_NetworkTask_State.AppContext->Settings.WiFi.Password, + Credentials->Password, + sizeof(_NetworkTask_State.AppContext->Settings.WiFi.Password)); + + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); + + break; + } + case NETWORK_EVENT_SET_TZ: { + ESP_LOGD(TAG, "Timezone set"); + + _NetworkTask_State.Timezone = static_cast(p_Data); + + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); + + break; + } case NETWORK_EVENT_WIFI_CONNECTED: { ESP_LOGD(TAG, "WiFi connected"); - /* Notify Time Manager that network is available */ - TimeManager_OnNetworkConnected(); - break; } case NETWORK_EVENT_WIFI_DISCONNECTED: { ESP_LOGD(TAG, "WiFi disconnected"); - /* Notify Time Manager that network is unavailable */ - TimeManager_OnNetworkDisconnected(); - _NetworkTask_State.State = NETWORK_STATE_DISCONNECTED; _NetworkTask_State.isConnected = false; @@ -101,7 +121,7 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, break; } case NETWORK_EVENT_PROV_SUCCESS: { - ESP_LOGI(TAG, "Provisioning success"); + ESP_LOGD(TAG, "Provisioning success"); /* Signal task to handle WiFi restart with new credentials */ xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); @@ -111,13 +131,6 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, case NETWORK_EVENT_PROV_FAILED: { ESP_LOGE(TAG, "Provisioning failed!"); - /* Fall back to AP mode if configured */ - if ((_NetworkTask_State.WiFi_Mode == NETWORK_WIFI_MODE_AP) || - (_NetworkTask_State.WiFi_Mode == NETWORK_WIFI_MODE_APSTA)) { - ESP_LOGI(TAG, "Falling back to AP mode"); - NetworkManager_StartAP(); - } - break; } case NETWORK_EVENT_PROV_TIMEOUT: { @@ -126,16 +139,10 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, /* Stop provisioning in task context (not timer context) */ Provisioning_Stop(); - /* Fall back to AP mode if configured */ - if ((_NetworkTask_State.WiFi_Mode == NETWORK_WIFI_MODE_AP) || - (_NetworkTask_State.WiFi_Mode == NETWORK_WIFI_MODE_APSTA)) { - ESP_LOGI(TAG, "Falling back to AP mode"); - NetworkManager_StartAP(); - } break; } case NETWORK_EVENT_OPEN_WIFI_REQUEST: { - ESP_LOGI(TAG, "Open WiFi request received"); + ESP_LOGD(TAG, "Open WiFi request received"); xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); @@ -147,58 +154,43 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, } } -/** @brief Network task main loop. +/** @brief Network task main loop. * @param p_Parameters Pointer to App_Context_t structure */ static void Task_Network(void *p_Parameters) { - App_Context_t *App_Context; - esp_task_wdt_add(NULL); - App_Context = reinterpret_cast(p_Parameters); ESP_LOGD(TAG, "Network task started on core %d", xPortGetCoreID()); + ESP_LOGI(TAG, "Autoconnect is %s", (_NetworkTask_State.AppContext->Settings.WiFi.AutoConnect) ? "enabled" : "disabled"); /* - do { - EventBits_t EventBits; + if(App_Context->Settings.WiFi.AutoConnect == false) { + do { + EventBits_t EventBits; - esp_task_wdt_reset(); + esp_task_wdt_reset(); - EventBits = xEventGroupGetBits(_NetworkTask_State.EventGroup); - if (EventBits & NETWORK_TASK_OPEN_WIFI_REQUEST) { + EventBits = xEventGroupGetBits(_NetworkTask_State.EventGroup); + if (EventBits & NETWORK_TASK_OPEN_WIFI_REQUEST) { - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); - break; - } - - vTaskDelay(100 / portTICK_PERIOD_MS); - } while (true);*/ + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); + break; + } - /* Try to load stored WiFi credentials */ - NetworkManager_LoadCredentials(); - if ((App_Context->Network_Config.Prov_Method != NETWORK_PROV_NONE) && (Provisioning_isProvisioned() == false) && - ((strlen(App_Context->Network_Config.STA_Config.ssid) == 0))) { + vTaskDelay(100 / portTICK_PERIOD_MS); + } while (true); + }*/ - /* No credentials, start provisioning */ + if ((Provisioning_isProvisioned() == false) && + (strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0)) { ESP_LOGI(TAG, "No credentials found, starting provisioning"); Provisioning_Start(); _NetworkTask_State.State = NETWORK_STATE_PROVISIONING; } else { - /* Start WiFi based on mode */ - switch (App_Context->Network_Config.WiFi_Mode) { - case NETWORK_WIFI_MODE_STA: - NetworkManager_StartSTA(); - break; - case NETWORK_WIFI_MODE_AP: - NetworkManager_StartAP(); - break; - case NETWORK_WIFI_MODE_APSTA: - NetworkManager_StartAPSTA(); - break; - } + NetworkManager_StartSTA(); } _NetworkTask_State.RunTask = true; @@ -213,6 +205,7 @@ static void Task_Network(void *p_Parameters) if (NotificationValue & 0x01) { /* Provisioning timeout notification */ ESP_LOGW(TAG, "Provisioning timeout"); + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); } } @@ -229,7 +222,10 @@ static void Task_Network(void *p_Parameters) } else if (EventBits & NETWORK_TASK_WIFI_CONNECTED) { ESP_LOGD(TAG, "Handling WiFi connection"); - if (NetworkManager_StartServer(&App_Context->Server_Config) == ESP_OK) { + /* Notify Time Manager that network is available */ + TimeManager_OnNetworkConnected(); + + if (NetworkManager_StartServer(&_NetworkTask_State.AppContext->Server_Config) == ESP_OK) { ESP_LOGI(TAG, "HTTP/WebSocket server started"); esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SERVER_STARTED, NULL, 0, portMAX_DELAY); @@ -243,6 +239,9 @@ static void Task_Network(void *p_Parameters) } else if (EventBits & NETWORK_TASK_WIFI_DISCONNECTED) { ESP_LOGD(TAG, "Handling WiFi disconnection"); + /* Notify Time Manager that network is unavailable */ + TimeManager_OnNetworkDisconnected(); + Provisioning_Start(); xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_DISCONNECTED); @@ -265,6 +264,18 @@ static void Task_Network(void *p_Parameters) esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_TIMEOUT, NULL, 0, portMAX_DELAY); xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); + } else if (EventBits & NETWORK_TASK_SNTP_TIMEZONE_SET) { + + memcpy(&_NetworkTask_State.AppContext->Settings.System.Timezone, _NetworkTask_State.Timezone, + sizeof(_NetworkTask_State.AppContext->Settings.System.Timezone)); + SettingsManager_Save(&_NetworkTask_State.AppContext->Settings); + TimeManager_SetTimezone(_NetworkTask_State.AppContext->Settings.System.Timezone); + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); + } else if (EventBits & NETWORK_TASK_WIFI_CREDENTIALS_UPDATED) { + SettingsManager_Save(&_NetworkTask_State.AppContext->Settings); + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); } vTaskDelay(10 / portTICK_PERIOD_MS); @@ -294,6 +305,8 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) ESP_LOGD(TAG, "Initializing network task"); + _NetworkTask_State.AppContext = p_AppContext; + /* Initialize NVS */ Error = nvs_flash_init(); if ((Error == ESP_ERR_NVS_NO_FREE_PAGES) || (Error == ESP_ERR_NVS_NEW_VERSION_FOUND)) { @@ -323,7 +336,13 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) return Error; } - Error = NetworkManager_Init(&p_AppContext->Network_Config); + /* Copy WiFi credentials from settings to network config */ + strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID, p_AppContext->Settings.WiFi.SSID, + sizeof(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) - 1); + strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.Password, p_AppContext->Settings.WiFi.Password, + sizeof(_NetworkTask_State.AppContext->STA_Config.Credentials.Password) - 1); + + Error = NetworkManager_Init(&_NetworkTask_State.AppContext->STA_Config); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to init WiFi manager: %d!", Error); @@ -333,17 +352,17 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) return Error; } - Error = Provisioning_Init(p_AppContext->Network_Config.Prov_Method, &p_AppContext->Network_Config); + Error = Provisioning_Init(&p_AppContext->STA_Config); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to init provisioning: %d!", Error); /* Continue anyway, provisioning is optional */ } + _NetworkTask_State.AppContext = p_AppContext; _NetworkTask_State.State = NETWORK_STATE_IDLE; - _NetworkTask_State.WiFi_Mode = p_AppContext->Network_Config.WiFi_Mode; _NetworkTask_State.isInitialized = true; - ESP_LOGI(TAG, "Network Task initialized"); + ESP_LOGD(TAG, "Network Task initialized"); return ESP_OK; } @@ -370,11 +389,7 @@ void Network_Task_Deinit(void) _NetworkTask_State.isInitialized = false; } -/** @brief Start the network task. - * @param p_AppContext Pointer to application context - * @return ESP_OK on success, error code otherwise - */ -esp_err_t Network_Task_Start(App_Context_t *p_AppContext) +esp_err_t Network_Task_Start(void) { BaseType_t Ret; @@ -385,12 +400,12 @@ esp_err_t Network_Task_Start(App_Context_t *p_AppContext) return ESP_OK; } - ESP_LOGI(TAG, "Starting Network Task"); + ESP_LOGD(TAG, "Starting Network Task"); Ret = xTaskCreatePinnedToCore( Task_Network, "Task_Network", CONFIG_NETWORK_TASK_STACKSIZE, - p_AppContext, + NULL, CONFIG_NETWORK_TASK_PRIO, &_NetworkTask_State.TaskHandle, CONFIG_NETWORK_TASK_CORE @@ -417,11 +432,10 @@ esp_err_t Network_Task_Stop(void) ESP_LOGI(TAG, "Stopping Network Task"); - /* Signal task to stop */ xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_STOP_REQUEST); /* Wait for task to set Running = false before deleting itself */ - for (uint8_t i = 0; i < 20 && _NetworkTask_State.Running; i++) { + for (uint8_t i = 0; (i < 20) && _NetworkTask_State.Running; i++) { vTaskDelay(50 / portTICK_PERIOD_MS); } diff --git a/main/Application/Tasks/Network/networkTask.h b/main/Application/Tasks/Network/networkTask.h index d99d309..9b7184a 100644 --- a/main/Application/Tasks/Network/networkTask.h +++ b/main/Application/Tasks/Network/networkTask.h @@ -32,14 +32,29 @@ #include "Application/application.h" #include "Application/Manager/Network/network_types.h" +/** @brief Initialize the network task. + * @param p_AppContext Pointer to the application context + * @return ESP_OK on success, error code otherwise + */ esp_err_t Network_Task_Init(App_Context_t *p_AppContext); +/** @brief Deinitialize the network task. + */ void Network_Task_Deinit(void); -esp_err_t Network_Task_Start(App_Context_t *p_AppContext); +/** @brief Start the network task. + * @return ESP_OK on success, error code otherwise + */ +esp_err_t Network_Task_Start(void); +/** @brief Stop the network task. + * @return ESP_OK on success, error code otherwise + */ esp_err_t Network_Task_Stop(void); +/** @brief Check if the network task is running. + * @return true if running, false otherwise + */ bool Network_Task_isRunning(void); #endif /* NETWORK_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/application.h b/main/Application/application.h index 276034a..6fb5297 100644 --- a/main/Application/application.h +++ b/main/Application/application.h @@ -49,6 +49,8 @@ enum { Data is transmitted as a uint32_t representing uptime in milliseconds. */ LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE, /**< Pixel temperature data is ready. Data is transmitted as a float. */ + LEPTON_EVENT_RESPONSE_SCENE_STATISTICS, /**< Scene statistics data is ready. + Data is transmitted in a App_Lepton_SceneStatistics_t structure. */ }; /** @brief Device status event identifiers. @@ -73,13 +75,14 @@ enum { GUI_EVENT_REQUEST_PIXEL_TEMPERATURE, /**< Request update of pixel temperature. Data is transmitted in a App_GUI_Screenposition_t structure. */ GUI_EVENT_REQUEST_SPOTMETER, /**< Request update of spotmeter data. */ + GUI_EVENT_REQUEST_SCENE_STATISTICS, /**< Request update of scene statistics data. */ }; /** @brief Structure representing a screen position. */ typedef struct { - int16_t x; /**< X coordinate. */ - int16_t y; /**< Y coordinate. */ + int16_t x; /**< X coordinate (0 to 159). */ + int16_t y; /**< Y coordinate (0 to 119). */ int32_t Width; /**< Width of the screen element where the position is related to. */ int32_t Height; /**< Height of the screen element where the position is related to. */ } App_GUI_Screenposition_t; @@ -94,10 +97,12 @@ typedef struct { /** @brief Structure representing a ready frame from the Lepton camera. */ typedef struct { - uint8_t *Buffer; - uint32_t Width; - uint32_t Height; - uint32_t Channels; + uint8_t *Buffer; /**< Pointer to the image buffer (Width * Height * Channels). */ + uint32_t Width; /**< Width of the frame in pixels. */ + uint32_t Height; /**< Height of the frame in pixels. */ + uint32_t Channels; /**< Number of color channels (e.g., 3 for RGB). */ + int16_t Min; /**< Minimum value in the frame. */ + int16_t Max; /**< Maximum value in the frame. */ } App_Lepton_FrameReady_t; /** @brief Structure representing FPA and AUX temperature from the Lepton camera. @@ -114,21 +119,24 @@ typedef struct { char SerialNumber[24]; /**< Lepton device serial number formatted as "XXXX-XXXX-XXXX-XXXX". */ } App_Lepton_Device_t; -/** @brief Structure representing the spotmeter results from the Lepton camera. +/** @brief Structure representing the ROI results from the Lepton camera. */ typedef struct { - float Max; /**< Maximum temperature value in Degree Celsius within the spotmeter ROI. */ - float Min; /**< Minimum temperature value in Degree Celsius within the spotmeter ROI. */ - float AverageTemperature; /**< Average temperature value in Degree Celsius within the spotmeter ROI. */ -} App_Lepton_Spotmeter_t; + float Max; /**< Maximum value within the specified ROI. */ + float Min; /**< Minimum value within the specified ROI. */ + union { + float Average; /**< Average value within the specified ROI. */ + float Mean; /**< Mean value within the specified ROI. */ + }; +} App_Lepton_ROI_Result_t; /** @brief Application context aggregating shared resources. */ typedef struct { - QueueHandle_t Lepton_FrameEventQueue; - Network_Config_t Network_Config; - Server_Config_t Server_Config; - App_Settings_t Settings; + QueueHandle_t Lepton_FrameEventQueue; /**< Queue for Lepton frame ready events. */ + Network_WiFi_STA_Config_t STA_Config; /**< WiFi STA configuration. */ + Server_Config_t Server_Config; /**< Server configuration. */ + App_Settings_t Settings; /**< Application settings. */ } App_Context_t; #endif /* APPLICATION_H_ */ \ No newline at end of file diff --git a/main/idf_component.yml b/main/idf_component.yml index a7247b7..83cdafc 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -2,14 +2,14 @@ dependencies: espressif/esp_new_jpeg: version: "^1.0.0" espressif/bootloader_support_plus: - version: ">=0.1.0" + version: "^0.1.0" espressif/esp_lcd_ili9341: version: "^2.0.1" - espressif/mdns: - version: "^1.9.1" espressif/esp32-camera: version: "^2.1.0" lvgl/lvgl: version: "^9.4.0" atanisoft/esp_lcd_touch_xpt2046: - version: "^1.0.6" \ No newline at end of file + version: "^1.0.6" + joltwallet/littlefs: + version: "^1.20.3" \ No newline at end of file diff --git a/main/main.cpp b/main/main.cpp index 8903dc6..e388ee5 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -33,16 +33,12 @@ static App_Context_t _App_Context = { .Lepton_FrameEventQueue = NULL, - .Network_Config = { - .WiFi_Mode = NETWORK_WIFI_MODE_STA, - .Prov_Method = NETWORK_PROV_BLE, - }, .Server_Config = { - .http_port = 80, - .max_clients = 4, - .ws_ping_interval_sec = 30, - .enable_cors = true, - .api_key = NULL, + .HTTP_Port = 80, + .MaxClients = 4, + .WSPingIntervalSec = 30, + .EnableCORS = true, + .API_Key = NULL, }, .Settings = {0}, }; @@ -54,6 +50,8 @@ static const char *TAG = "main"; */ extern "C" void app_main(void) { + i2c_master_dev_handle_t RtcHandle = NULL; + ESP_ERROR_CHECK(esp_event_loop_create_default()); _App_Context.Lepton_FrameEventQueue = xQueueCreate(1, sizeof(App_Lepton_FrameReady_t)); @@ -64,16 +62,16 @@ extern "C" void app_main(void) ESP_ERROR_CHECK(SettingsManager_Init()); + ESP_LOGI(TAG, "Loading settings..."); ESP_ERROR_CHECK(SettingsManager_Get(&_App_Context.Settings)); ESP_LOGI(TAG, "Initializing application tasks..."); ESP_ERROR_CHECK(DevicesTask_Init()); /* Initialize Time Manager (requires RTC from DevicesManager) */ - void *RtcHandle = NULL; if (DevicesManager_GetRTCHandle(&RtcHandle) == ESP_OK) { if (TimeManager_Init(RtcHandle) == ESP_OK) { - TimeManager_SetTimezone("CET-1CEST,M3.5.0,M10.5.0/3"); + TimeManager_SetTimezone(_App_Context.Settings.System.Timezone); ESP_LOGI(TAG, "Time Manager initialized with CET timezone"); } else { ESP_LOGW(TAG, "Failed to initialize Time Manager"); @@ -93,7 +91,7 @@ extern "C" void app_main(void) ESP_ERROR_CHECK(DevicesTask_Start(&_App_Context)); ESP_ERROR_CHECK(GUI_Task_Start(&_App_Context)); ESP_ERROR_CHECK(Lepton_Task_Start(&_App_Context)); - ESP_ERROR_CHECK(Network_Task_Start(&_App_Context)); + ESP_ERROR_CHECK(Network_Task_Start()); ESP_LOGI(TAG, " Tasks started"); /* Main task can now be deleted - no need to remove from watchdog as it was never added */ diff --git a/sdkconfig.debug b/sdkconfig.debug index 39bdcb7..e6d7fc4 100644 --- a/sdkconfig.debug +++ b/sdkconfig.debug @@ -2747,6 +2747,23 @@ CONFIG_LEPTON_MISC_ERROR_BASE=0xB000 # end of Misc # end of ESP32-Lepton +# +# ADC Battery Estimation +# +CONFIG_OCV_SOC_MODEL_1=y +# CONFIG_OCV_SOC_MODEL_2 is not set +CONFIG_ADC_FILTER_WINDOW_SIZE=10 +CONFIG_BATTERY_CAPACITY_LPF_COEFFICIENT=2 +CONFIG_BATTERY_STATE_SOFTWARE_ESTIMATION=y + +# +# Software Estimation Configuration +# +CONFIG_SOFTWARE_ESTIMATION_SAMPLE_COUNT=10 +CONFIG_SOFTWARE_ESTIMATION_SAMPLE_INTERVAL=20000 +# end of Software Estimation Configuration +# end of ADC Battery Estimation + # # CMake Utilities # @@ -2811,45 +2828,34 @@ CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS=1 # end of ESP LCD TOUCH # -# mDNS -# -CONFIG_MDNS_MAX_INTERFACES=3 -CONFIG_MDNS_MAX_SERVICES=10 -CONFIG_MDNS_TASK_PRIORITY=1 -CONFIG_MDNS_ACTION_QUEUE_LEN=16 -CONFIG_MDNS_TASK_STACK_SIZE=4096 -# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set -CONFIG_MDNS_TASK_AFFINITY_CPU0=y -# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set -CONFIG_MDNS_TASK_AFFINITY=0x0 - -# -# MDNS Memory Configuration -# -# CONFIG_MDNS_TASK_CREATE_FROM_SPIRAM is not set -CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL=y -# CONFIG_MDNS_MEMORY_ALLOC_SPIRAM is not set -CONFIG_MDNS_MEMORY_ALLOC_INTERNAL=y -# CONFIG_MDNS_MEMORY_CUSTOM_IMPL is not set -# end of MDNS Memory Configuration - -CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 -CONFIG_MDNS_TIMER_PERIOD_MS=100 -# CONFIG_MDNS_NETWORKING_SOCKET is not set -# CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES is not set -# CONFIG_MDNS_ENABLE_DEBUG_PRINTS is not set -CONFIG_MDNS_ENABLE_CONSOLE_CLI=y -# CONFIG_MDNS_RESPOND_REVERSE_QUERIES is not set -CONFIG_MDNS_MULTIPLE_INSTANCE=y - -# -# MDNS Predefined interfaces -# -CONFIG_MDNS_PREDEF_NETIF_STA=y -CONFIG_MDNS_PREDEF_NETIF_AP=y -CONFIG_MDNS_PREDEF_NETIF_ETH=y -# end of MDNS Predefined interfaces -# end of mDNS +# LittleFS +# +# CONFIG_LITTLEFS_SDMMC_SUPPORT is not set +CONFIG_LITTLEFS_MAX_PARTITIONS=3 +CONFIG_LITTLEFS_PAGE_SIZE=256 +CONFIG_LITTLEFS_OBJ_NAME_LEN=64 +CONFIG_LITTLEFS_READ_SIZE=128 +CONFIG_LITTLEFS_WRITE_SIZE=128 +CONFIG_LITTLEFS_LOOKAHEAD_SIZE=128 +CONFIG_LITTLEFS_CACHE_SIZE=512 +CONFIG_LITTLEFS_BLOCK_CYCLES=512 +CONFIG_LITTLEFS_USE_MTIME=y +# CONFIG_LITTLEFS_USE_ONLY_HASH is not set +# CONFIG_LITTLEFS_HUMAN_READABLE is not set +CONFIG_LITTLEFS_MTIME_USE_SECONDS=y +# CONFIG_LITTLEFS_MTIME_USE_NONCE is not set +# CONFIG_LITTLEFS_SPIFFS_COMPAT is not set +# CONFIG_LITTLEFS_FLUSH_FILE_EVERY_WRITE is not set +# CONFIG_LITTLEFS_FCNTL_GET_PATH is not set +# CONFIG_LITTLEFS_MULTIVERSION is not set +# CONFIG_LITTLEFS_MALLOC_STRATEGY_DISABLE is not set +CONFIG_LITTLEFS_MALLOC_STRATEGY_DEFAULT=y +# CONFIG_LITTLEFS_MALLOC_STRATEGY_INTERNAL is not set +# CONFIG_LITTLEFS_MALLOC_STRATEGY_SPIRAM is not set +CONFIG_LITTLEFS_ASSERTS=y +# CONFIG_LITTLEFS_MMAP_PARTITION is not set +# CONFIG_LITTLEFS_WDT_RESET is not set +# end of LittleFS # # LVGL configuration diff --git a/ui/PyroVision.sll b/ui/PyroVision.sll index a35b13f..71c9a09 100644 --- a/ui/PyroVision.sll +++ b/ui/PyroVision.sll @@ -12,7 +12,7 @@ "board": "ESP WROVER KIT", "board_version": "2.0.0", "editor_version": "1.5.4", - "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDgtX0ixtfA/hfUYYNt3ffa/tEm9jv2SBV4JwMD0xWLDDAQrNHux1G4iun1/wD5Jp4J/wC37/0cK5IEg5BxSauEZcsk10L4jsf+fP8A8itS+XYf8+X/AJFaqG9/7zfnRvf+8351n7GPn97/AMzt/tGr/LH/AMAh/wDIl/ZYf8+P/kVqXZp//Ph/5Gas/e/95vzo3v8A3m/Ol7GPn97/AMyfr9XtH/wCH/yJo7dO/wCgf/5Gal26b/0Dv/IzVm73/vN+dG9/7zfnR7CPd/e/8xfXqnaP/gEP/kTTxpn/AEDf/I7Uf8Sz/oGf+R2rM3v/AHm/Oje/95vzpewh3f8A4E/8xfXKnaP/AIBH/I1P+JX/ANAz/wAmGpc6V/0Cv/Jhqyt7/wB5vzo3v/eb86PYQ7v/AMCf+Yvrc+0f/AY/5GrnSv8AoFf+TDUu7SP+gR/5MvWTvf8AvN+dG9/7zfnR9Xh3f/gUv8xfWZ9l/wCAx/yNcNpH/QI/8mXpd+j/APQH/wDJl6x97/3m/Oje/wDeb86X1eHd/wDgUv8AMn6xLsv/AAGP+Rsh9G/6A3/k09HmaN/0Bf8Ayaesbe/95vzo3v8A3m/Oj6tDu/8AwKX+YvbS7L7l/kbXmaL/ANAT/wAm3o83RP8AoB/+Tb1i73/vN+dG9/7zfnR9Wh3f/gUv8xe1fZfcv8jc87Q/+gF/5NvR52hf9AH/AMnHrD3v/eb86N7/AN5vzpfVafd/+BS/zF7R/wBJG752hf8AQA/8nHpfP0H/AKF//wAnJKwd7/3m/Oje/wDeb86PqtPvL/wKX+ZPMb32jQP+he/8nZKX7R4f/wChd/8AJ2SsDe/95vzo3v8A3m/Ol9Up95f+BS/zFc6D7T4e/wChd/8AJ2Sl+0+Hf+hb/wDJ6Sue3v8A3m/Oje/95vzo+qU+8v8AwKX+YrI6L7V4d/6Fv/yeko+1eHP+ha/8n5K53e/95vzo3v8A3m/Oj6pT7y/8Cl/mLlX9NnR/a/Df/Qs/+T8lKLvw1/0LH/k/JXN73/vN+dG9/wC8350vqdPvL/wOX+ZPs4+f3s6T7Z4a/wChX/8AKhJS/bPDP/Qrf+VCSua3v/eb86N7/wB5vzo+p0+8v/A5f5i9lHz+9/5nTfbfDH/Qq/8AlQlpft3hf/oVP/KjLXMb3/vN+dG9/wC8350vqVLvL/wOf/yQvYQ8/vf+ZYu47UyyyQweVGzEpHvLbATwMnritfSNIsbrwP4o1GaDdd2P2T7PJvYbN8hVuAcHI9c1z5JJyTmut0D/AJJp42/7cf8A0ca60rKxsjiaKKKBHba//wAk08E/9v3/AKOFctbQNdXUNuhAeV1RS3QEnHNdTr//ACTTwT/2/f8Ao4Vy9ncfZL63udu/yZFk25xnBzjNAyymjXjeWHjMRfcQsisDtXq2MZx29ajm0+aBHZiNqOidGGdwJBAIBx8pp51ARQrFaRvGoYs3muJM5GMY2gYx7UxdTu13fOhDFSVMSkDbnGBjAxk9PWgBw0yYzPHvjBSfyCSTjdzz06cGln0qeBSzMmBCJujA437OhAOc/pUUt/czEGR1bD7z8i/M3q3HzH65pWvpXWQOfvxiMBFVVADBsYA9RnjHNAEi6VO1zJAHj3pcrbE5ONzFgD06fKf0qNbGV/KwyfvIXnGSfuruyPr8h/SpP7VunuUmlfJWUTHYqoWYHqeOT16g9aiF/ciBYQ67FQxj5FyFJJIzjOOT370AXJNNgFnMwl2XEEaPIhfdjJUdNox94dCay2AVyoYMAcZHQ1ZOo3RiaIupVlCt+7XLAEEAnGT0HWqzMWYscZJycDA/KgQlFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUVZsJrSC9SS9tGurcBg8Ky+WTkEAhsHBBweh6UAXZNDNtqlzY3uo2do0JGJZPMZJQRlWTYjEggggkDginf8I1f/2lc6fmL7TbXCwSpuPy5bbv6fdzgZ/2hxzWxD4ztLVgLax1KAfYBZNLFqQSchZVdW3iLHAGzG37uOeKz7fxQ1nEUtbeQfOxHmzbtyl9x3YUZkIO0uMfL0A60DMe9s3sbkwO6OdiSB0zhlZQykZAPQjqK6bQP+SaeNv+3H/0ca5a5mNxcyzFpDvYnMr72x2y3c+9dToH/JNPG3/bj/6ONAHE0UUUCO21/wD5Jp4J/wC37/0cK5Guu1//AJJp4J/7fv8A0cK5e1mFvcxzNGJNh3BSeCR0z7ZoGWJdKuIbkQSNGv7syM+cqoHXPHUEEEetL/ZM7eX5bxSLLJGkbKThy+4AjI9VIOajTUJkhC5zIHZg554YYYEHqDx+vrU0OsTxFXKo8iTRyplQFXYGwNoGMfN2xQAkekyzRPLFNE6KHOVD4IVcn+Hj8cVM2lxG1l2Pi6iRGaPfuJ3FRjG0AfeHc1RW9mVZAvlrvyCViUHBGCAcZAx6U46jdGFojINrKFYhFDMAQRlsZOMDv2oAfdaZLZ/611HUZ2uBkdslcE/TiqVWZb64mGHZCDnIEajJPUnA6+/Wq1AgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArZsvCmuX9lPeQ6Zd/Z4oPtAkMD7ZFyB8pAwTzn6A1jVqJrUo0V9OkVmwNsMqvtZELbmjPHzISA2OMNyOpBALEfhtZNIm1Jda00wwsEdAJy6kjIyBHwD0BOBkEZqtoehXniC+a0szErrGXLSttXqAoz6szKo92FS6Zq1pptpcbbKZ7yaCW3Mn2jERWRSvzR7ckjOR8wGQpxxVeDVGtdGlsYIzHLNOksk4fkqgO1QO3JLHnkhfSgZnkEEgjBHauu0D/kmnjb/tx/8ARxrndVvl1PVJ74QCFp28x0U5G8j5iOBgFskDtnHOK6LQP+SaeNv+3H/0caAOJooooEdtr/8AyTTwT/2/f+jhXJxoHkVS6oCfvN0FdZr/APyTTwT/ANv3/o4Vy1tN9nuY5tivsYNtboaBln+zH8vzRPCYNhfzfmxgEL0xnqwHTvTzotzsiZWjbzJI41A3fecEjkjB6diaSTVZC0xQO/nRiNzcsJWwGB4JAx0/zxiODU7i3kgZBFiF1kC+UoDFem7Aye/vzQA+HS2nZAl1b4kk8qNjuAcjGcfL7jrimDTnNotyZo1jYgZYOMfjtwfwzUYvbgPEyuqmKQyJtRQFY45xj2FH22YxxoxjYR8KWiUkD0yRnHtQBXooooEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVvW/hLUrm5uYYjCRbWC38shYhQjQCYLnHLlTjHqD2BNYNdVL42mkltAtkkdvb6e1oYkkx5shtfs3mscckLjA7AY7kkArx+Db+aVLaC5s5b3dCstqrsHh81lVCxKhSNzoDtJwWGarxeG57m506K2vLSZNQvTYwTKXC7x5eSdyghf3q9s8HjpmWx8ZazY3VpOssEhtpIpMSW6Zl8vGwSMAGcDAxk8YBGCAQReLr+30yG1tkghljuZbjzlt4uC6xqNg2fuyPL6rg89sUDKh0G6GnfbvMh8r7EL3GTu2GfyMdPvbufTHfPFatj4btLdHk1qZY4SLcxSpcmMEyxCUL/AKpySFZc52qD/F0rNi8RXttDDFbOAqWn2SRZo45VdPNMuNrJjG4g85OR1xwEXxLqqzTyGeOQzMrMJbeN1BUbVKqykKQOBtAwOKAK+s6f/ZGuahpvmeZ9kuZLffjG7YxXOPwroNA/5Jp42/7cf/RxrmLy7n1C+uL26k8y4uJGllfAG5mOScDgcmun0D/kmnjb/tx/9HGgDiaKKKBHba//AMk08E/9v3/o4VhW2h393aJdRpCIZCVRpLmOPcR1wGYGt3X/APkmngn/ALfv/RwpbWx+2eFdMJ0m9vwks/NtJs2ZK9flbr+HStaUFNu/9fmUlc52fSL62+0edblfs6q0nzDhWOFI55BJHIyORUEVpPNbz3EaZigCmRsgYycD6/hXUXeoR6Z4thiyi2cdulqyECTy0KgkNnIZlY59Mj8Kj1xNRYW2g+VHNfFjNMtrCi7jg7FwgGcLlv8AgftVulHW3TT+v66MLI5u4tZrUQmZNvnRiVOQcqc4PH0NOexuY5LeN48NcorxDcPmDHAPtyO9dHrXh7WJk0wRabdP5djGj7YydrAtkH35qTUtH1GG50SeSynWKC3gSVyhwjbzwfTqPzodBpvRhymJdeH9Rs45XnW3URZ3qLuIsMdRtDZz7VB/ZN9/aIsPI/0nAbZuHAK7sk5wBjnOeK3/ABNpTLcajcroeoRfv3c3Ty5jILdduwcH69+9bUw1Ua7ia0iGiyRRpPNLCiDyjGu795gMe/fqBV+wjzNa/wBX8kPlPP4rSeeOd4k3LbpvkO4fKuQuffkjpUNdNYiy0my8q+BP9qjYW5zDb5+WTHqWAbHovvWBe2ktheS2s4Akjbaccg+hHsRyKwnDlSZLRBRRRWYgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArrtA/wCSaeNv+3H/ANHGuRrrtA/5Jp42/wC3H/0caBo4miiigR3eo282pfCrw7c2cbTR6ZNdQ3ZQZMRdw6kjsMd/cetcZVvRfEOreHrhp9JvpbV2wG24KtjplTkH8RW//wALW8a/9Br/AMlYf/iKBnK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrRXVf8LW8a/9Br/yVh/+Io/4Wt41/wCg1/5Kw/8AxFAHK0V1X/C1vGv/AEGv/JWH/wCIo/4Wt41/6DX/AJKw/wDxFAHK0V1X/C1vGv8A0Gv/ACVh/wDiKP8Aha3jX/oNf+SsP/xFAHK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrRXVf8LW8a/9Br/yVh/+Io/4Wt41/wCg1/5Kw/8AxFAHK0V1X/C1vGv/AEGv/JWH/wCIo/4Wt41/6DX/AJKw/wDxFAHK0V1X/C1vGv8A0Gv/ACVh/wDiKP8Aha3jX/oNf+SsP/xFAHK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrRXVf8LW8a/9Br/yVh/+Io/4Wt41/wCg1/5Kw/8AxFAHK0V1X/C1vGv/AEGv/JWH/wCIo/4Wt41/6DX/AJKw/wDxFAHK0V1X/C1vGv8A0Gv/ACVh/wDiKP8Aha3jX/oNf+SsP/xFAHK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrRXVf8LW8a/9Br/yVh/+Io/4Wt41/wCg1/5Kw/8AxFAHK0V1X/C1vGv/AEGv/JWH/wCIo/4Wt41/6DX/AJKw/wDxFAHK0V1X/C1vGv8A0Gv/ACVh/wDiKP8Aha3jX/oNf+SsP/xFAHK0V1X/AAtbxr/0Gv8AyVh/+Io/4Wt41/6DX/krD/8AEUAcrXZ6dbzab8KvEVzeRtDHqc1rDaFxgylHLsQO4x39j6VW/wCFreNf+g1/5Kw//EVga14h1bxDcLPq19LdOuQu7AVc9cKMAfgKAMyilVGdgqKWY8AAZJoZGRirqVYcEEYIp2driOy0fR9D0vwxD4h8QwT3pu5XjsbCKTyxIE4d3ccgA8cfrnh/9v8Agr/oQv8AysTf4Ua//wAk08E/9v3/AKOFcjSGdd/b/gr/AKEL/wArE3+FH9v+Cv8AoQv/ACsTf4VyNFAXOu/t/wAFf9CF/wCVib/Cj+3/AAV/0IX/AJWJv8K5GigLnXf2/wCCv+hC/wDKxN/hR/b/AIK/6EL/AMrE3+FcjRQFzrv7f8Ff9CF/5WJv8KP7f8Ff9CF/5WJv8K5GigLnXf2/4K/6EL/ysTf4Uf2/4K/6EL/ysTf4VyNFAXOu/t/wV/0IX/lYm/wo/t/wV/0IX/lYm/wrkaKAudd/b/gr/oQv/KxN/hR/b/gr/oQv/KxN/hXI0UBc67+3/BX/AEIX/lYm/wAKP7f8Ff8AQhf+Vib/AArkaKAudd/b/gr/AKEL/wArE3+FH9v+Cv8AoQv/ACsTf4VyNFAXOu/t/wAFf9CF/wCVib/Cj+3/AAV/0IX/AJWJv8K5GigLnXf2/wCCv+hC/wDKxN/hR/b/AIK/6EL/AMrE3+FcjRQFzrv7f8Ff9CF/5WJv8KP7f8Ff9CF/5WJv8K5GigLnXf2/4K/6EL/ysTf4Uf2/4K/6EL/ysTf4VyNFAXOu/t/wV/0IX/lYm/wo/t/wV/0IX/lYm/wrkaKAudd/b/gr/oQv/KxN/hR/b/gr/oQv/KxN/hXI0UBc67+3/BX/AEIX/lYm/wAKP7f8Ff8AQhf+Vib/AArkaKAudd/b/gr/AKEL/wArE3+FH9v+Cv8AoQv/ACsTf4VyNFAXOu/t/wAFf9CF/wCVib/Cmaxo+h6p4Ym8Q+HoJ7I2kqR31hLJ5gjD8I6OeSCeOf0xzylddoH/ACTTxt/24/8Ao40Ac3oH/Ibt/wDgX/oJo1//AJDdx/wH/wBBFHh//kN2/wDwL/0E0eIP+Q3cf8B/9BFel/zLf+3/AP20v/l38zpNf/5Jp4J/7fv/AEcK5Guu1/8A5Jp4J/7fv/Rwrka80hhRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACuu0D/kmnjb/tx/9HGuRrrtA/5Jp42/7cf/AEcaBo5vw/8A8hu3/wCBf+gmjxB/yG7j/gP/AKCKPD//ACG7f/gX/oJo8Qf8hu4/4D/6CK9P/mW/9v8A/tpf/Lv5nSa//wAk08E/9v3/AKOFcjXXa/8A8k08E/8Ab9/6OFcjXmEMKKKKBBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV12gf8k08bf8Abj/6ONcjXXaB/wAk08bf9uP/AKONA0c34f8A+Q3b/wDAv/QTR4g/5Ddx/wAB/wDQRR4f/wCQ3b/8C/8AQTR4g/5Ddx/wH/0EV6f/ADLf+3//AG0v/l38zpNf/wCSaeCf+37/ANHCuc0pFk1iyR1DI1xGGVhkEbhwa6PX/wDkmngn/t+/9HCuRrzCDaXT47iwsWNtMoaBy9yuBGpDv97jnoO/TFZMxzKTuRuByi7R09MCo6KBBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV1Wk2V1B4dttQh0qO4uH1NBb+fbCRZwEfcgyPmGRggd/euVooA9BuNIvLjxFaXZ0F5bMwqbvT4bCNJrVJTIhUoiglgFZ1YjIBQnFZ9jpd3p95rOlCyt7vV9PBW2iNqkpfMih2CkHzDt5AIOAxIHGRx1FAztlgth4rnsorO0af7IJ0tvJRl+2/ZwWjA7gSFv3fTcAuD0qC9s531fSLMaZENSu4UN9aRWihlcSuRhAP3ZMaoSABweRzXIUUAaGvRpD4i1OKJFSNLuVVRRgKA5wAOwre0D/kmnjb/ALcf/Rxrka67QP8Akmnjb/tx/wDRxoBHN+H/APkN2/8AwL/0E0eIP+Q3cf8AAf8A0EUeH/8AkN2//Av/AEE0eIP+Q3cf8B/9BFen/wAy3/t//wBtL/5d/M6TX/8Akmngn/t+/wDRwrnNKRZNYskdQyNcRhlYZBG4cGuj1/8A5Jp4J/7fv/Rwrka8wg2Ut7MwXKR7WmtoW3sTkSHj5l+h49xg+tKUsvsgv2hK+aBHwwKhzw2FxxgfMOeMrWLRQBr3aTxSv/o0EVosn7uUwArjt82CWyPrWRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA67w7ZaRq+lH7fayl9NYyTyW8yQk2xyxZgUO8hht6g/vEH0uQNo+oae/iWbSkSSzLCeGB40t/MzmAGHZ8ytnBGRkRuT78LRQM9G0SwW+0GzkiiWV5dRlilubLQYrpQoit8Bt4XYAWboOSWP1l0/TYLqyZ7KxMUcmuXcRe10iLUVjiAh2KXfBVF3Ng98k15pRQB2lvFbT3usfYLWwmvIpJW0+xSMS7QZVBxlcTYTO0Hdxk4pYrTUjbXki6Jbt4gWSIG0+wIWSEq2XFvt25JC5O3gY6bsniqKAO30m3vpjrappllNqsFmzpZx6akjwubi3DHYUIJ2l8AZ2gt92rtrp9y1rdyLo1ufEI0xnazXT0cr/pUCq5g2lVco0gwFHygHHOT53RQB6BYWcTeIfDcOp2lhb391dwpeWT2iqZE89QuUC4jYjdkfLlQODu5fZ2Nw/iqxhu9NuMG0vXiSfw7Bbs7rbuRtiXiUghSAe+PWvPKKAO5srdm8d6VZ6hbRxxzXVoht73Ro7R5kM4yAiKVx1ySRkZHPSnad4RRTq1tLY642/Tt8Rm0fbMGFzACYk8w7vlYgkMMBjXCUUAWtSs20/UJrVo7mMxkfLdQeTJgjI3Jk46+prpNA/wCSaeNv+3H/ANHGuRrrtA/5Jp42/wC3H/0caAOb8P8A/Ibt/wDgX/oJo8Qf8hu4/wCA/wDoIo8P/wDIbt/+Bf8AoJo8Qf8AIbuP+A/+givT/wCZb/2//wC2l/8ALv5nSa//AMk08E/9v3/o4VnqNPsdA0+5l0yG6muHmDtJLIuApXGNrAd60Nf/AOSaeCf+37/0cKyYdVsG0q2sr3Tppzbs7I8dz5edxGcjYfQd64abSvclGhZ6Rp93q+jTRwv9iv2YNbu5JRl4YbhgkdCO/NU9Wtpba0Hm+G/7P3sAsxM3X0G5iKSPxCYtXsbtbREtrLiG1RyAAc5+Y5OSTkmmRajpFtdQXEOk3G6GQSbZLwMrY6AjYO+K0bptWX9beXr2HoW9V0ezttK2W6t/aFhs+3HcSG3+g7bDhTj1p39j2AW2uZUcW8WmrdzpG3zSuZCoAJzjJx+ArKtNVkg1C4urhDcC6WRLhC23eH684ODnB+oqyviB0ltWFsjRRWgtJopGysyZJOcYI6jp0IFClTbvYV0N8/TL64t4YtKFq7TIpKTsyspPIIbJz7gitHXdPNh9tVfDAgtkkZI7otNwN2Fblsc8VmSajpyPC1npRhZJVkZnuC5OD0HAAH1Bp2pajpd/JczpptxFczu0m83YZQxOT8uwfzpc0eV3av6f8D/INDIooornJCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArrtA/5Jp42/7cf/Rxrka67QP+SaeNv+3H/wBHGgaOb8P/APIbt/8AgX/oJo8Qf8hu4/4D/wCgijw//wAhu3/4F/6CaPEH/IbuP+A/+givT/5lv/b/AP7aX/y7+Z0Oj6xoeqeGIfD3iGeeyNpK8ljfxR+YIw/Lo6Dkgnnj9Mcv/sDwV/0Pv/lHm/xriaK8wg7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABo/sDwV/wBD7/5R5v8AGuJooA7b+wPBX/Q+/wDlHm/xo/sDwV/0Pv8A5R5v8a4migDtv7A8Ff8AQ+/+Ueb/ABpmsaxoel+GJvD3h6ee9N3Kkl9fyx+WJAnKIiHkAHnn9c8cZRQBpeH/APkN2/8AwL/0E0eIP+Q3cf8AAf8A0EVVsbtrG9juVUMUJ+UnGcjH9aL67a+vZLllClyPlBzjAx/Su320PqXsftc1/laxV1yW8zqbLQ9OlsLeR7fLvErMd7ckj61N/wAI/pf/AD6/+RG/xq1p3/IMtP8Arin/AKCKs19hRweHdOLdOOy6I6lCNtjM/wCEf0v/AJ9f/Ijf40f8I/pf/Pr/AORG/wAa06K0+pYb/n3H7kPkj2Mz/hH9L/59f/Ijf40f8I/pf/Pr/wCRG/xrToo+pYb/AJ9x+5ByR7GZ/wAI/pf/AD6/+RG/xo/4R/S/+fX/AMiN/jWnRR9Sw3/PuP3IOSPYzP8AhH9L/wCfX/yI3+NH/CP6X/z6/wDkRv8AGtOgYyM9O+KPqWG/59x+5ByR7GZ/wj+l/wDPr/5Eb/Gj/hH9L/59f/Ijf413EWjaXfWF5NaR6pGtvC0ou7gKIXKj7pAHyk9B8x5rOt9K87w3e6ptlzBcRRAgfJhg2c8dQdvf+L3rBUsG/wDl2t0tl12FaHY5j/hH9L/59f8AyI3+NH/CP6X/AM+v/kRv8a7HRtP0zUPJgNtq1zcucSG2ChYsnA4IORjnJK1FbaPBJqWrWrzmRbKGd0kiIw5Toe/B/wAmj2WDTadNaf3UFo9jk/8AhH9L/wCfX/yI3+NH/CP6X/z6/wDkRv8AGuw03TtObQZtSvYr2ZlulgVLaRU4KlsnKt6UiabZXtpqc9nFeRm2SLyopXV2ZmcKc4UZ68Ch0sIm17JaO2y/rqFo9jkP+Ef0v/n1/wDIjf40f8I/pf8Az6/+RG/xrtz4W+z3M0dzOJEWymmV4CMCWNfmjP0bg+xB71m6Np8WoyXizM6iCzmnXYQMsi5AOR0oVLBOLkoRsvJBaHY5r/hH9L/59f8AyI3+NH/CP6X/AM+v/kRv8a7FvDpmutMgtXYfabIXU8kpG2EbmDMTjhQF/wA5q9deE4je61a6b9quns4oHt1ABaTftLZAHoxPapccCnZwj9y72/NhaHY4D/hH9L/59f8AyI3+NH/CP6X/AM+v/kRv8a6y18Pzi8mj1RJrGG2h+0Tl4zv2ZAAUHGSSQB/9apf7P0jUra6OlPeRXNtE03lXRVhIi8tgqBggZOMHp1qnSwaf8NNd+VWC0Oxx3/CP6X/z6/8AkRv8aP8AhH9L/wCfX/yI3+Nd5D4RW6k0nyryGKO7t1llEtwgkBJYEImQTwBj371UXQVu7SRrSK4S5Ooi0jhmYZVSrH5uByMcngdeKlRwL+xH7kFodjjv+Ef0v/n1/wDIjf40f8I/pf8Az6/+RG/xrtG8PwWiajJcztPDbRwzQy25AWaN5ApIyD2JHsR3xUx8HytrAgS8s/sjN5iubqPzPIxu37M5+583SjlwPWEfuXk/1FaHY4X/AIR/S/8An1/8iN/jR/wj+l/8+v8A5Eb/ABrqIrC0ubDWLuEzBLUoYAzDJVn2/NxycemOatWvh5L2y0mSOYxvdNcGd35SNIgCWAAz0J+vHSrdHBx3pr/wFdr/AJDtDscb/wAI/pf/AD6/+RG/xo/4R/S/+fX/AMiN/jXa2+naHq1x9h02W/jvGB8hrnYUlYDO0gcrntyarLobXOnaQ9mskt3fyzRlMjHyFcY9OpyT6UvZYO9nTS9Yrs3+jC0exyf/AAj+l/8APr/5Eb/Gj/hH9L/59f8AyI3+Ndb4k0i10a5s4rW5NystqsrS/wALMWYHbx935eKxa0p4bCVIqUacbPyX+Q1GL6GZ/wAI/pf/AD6/+RG/xo/4R/S/+fX/AMiN/jWnRV/UsN/z7j9yDkj2Mz/hH9L/AOfX/wAiN/jR/wAI/pf/AD6/+RG/xrToo+pYb/n3H7kHJHsZn/CP6X/z6/8AkRv8aP8AhH9L/wCfX/yI3+NadFH1LDf8+4/cg5I9jM/4R/S/+fX/AMiN/jR/wj+l/wDPr/5Eb/GtOij6lhv+fcfuQckexW07/kGWn/XFP/QRVms6wv7NNOtVa7gVliQEGQAg4FWP7Rsf+fy3/wC/q/40Ua1P2cfeWy6gmrFmiq39o2P/AD+W/wD39X/Gj+0bH/n8t/8Av6v+Nae2pfzL7x3RZoqt/aNj/wA/lv8A9/V/xo/tGx/5/Lf/AL+r/jR7al/MvvC6LNFVv7Rsf+fy3/7+r/jR/aNj/wA/lv8A9/V/xo9tS/mX3hdFmgHBBxmq39o2P/P5b/8Af1f8aP7Rsf8An8t/+/q/40e2pfzL7wujrNb1fTdY8y4MupiZgPKtWK+TCemFOfujsNopi+IIILm0t4IpDpMUJhlhcANMH/1jHk/MTgjnjavpXLf2jY/8/lv/AN/V/wAaP7Rsf+fy3/7+r/jXOoYdRUebReYvdOtTV9Ml0iDTpptTght2cbbYLtuFLEhnBYYbHH8XQUzRr3Q7GK5aeXURLcW8sBSOFGVA3AOS4ycY7DmuV/tGx/5/Lf8A7+r/AI0f2jY/8/lv/wB/V/xocaNnFT380Gnc7LT9a03T9NubC21DWLZXuFmSe3jVXYBCCrASDufU9BTbPxJBpkuqzRS3d7cXMSCCe7UblkBB3N8x6dR15Arj/wC0bH/n8t/+/q/40f2jY/8AP5b/APf1f8aTpYd3vK999V5f5CtE6bRPEC6dYalZ3MbSxXUEixkcmOVlK7uT0IOD9B6VU0bUItOkvGmV2E9nNAuwA4Z1wCcnpWJ/aNj/AM/lv/39X/Gj+0bH/n8t/wDv6v8AjWj+r+97y97fUfunVal4kW40Ky0y0haIpbrFdSn70u0kqo5+6CSfc/SrMuv6XeXOri4F5HBfQ28atHGrMpjCZyCwHJX1rjP7Rsf+fy3/AO/q/wCNH9o2P/P5b/8Af1f8az9nhktJJfPzT/RBaJ0ltf6Zpt1IluLq7sbqEw3KTIsT4yCCpDMMggEZ9MU4ahpOm21yNKS8lubmJoTLdBVEaNw2ApOSRxnjr0rmf7Rsf+fy3/7+r/jR/aNj/wA/lv8A9/V/xq2qL3n667+oadzrZNQ0G8g01rttREtnbLC0cUaBX2sx4ctkfe9KfJ4t36dq6rb7LzULoyhxgiJGBDAHruIO3p0Jrj/7Rsf+fy3/AO/q/wCNH9o2P/P5b/8Af1f8aj2eHe8r/PzuFonTWuvrH4UvtHniZ3k2/ZpB/AN6syn2+XI9yfWlXXYB4fNv5Un9piM2qz8bfs5O4j13dV/3TiuY/tGx/wCfy3/7+r/jR/aNj/z+W/8A39X/ABquXD66re+/UPdOrsLzQLfR7u0mn1LzLtIxIUt4yEZTuOMycjPHaiPxBb2MOmxWkUkyWklyJFnUKJYpcDHBODtB+hx1rlP7Rsf+fy3/AO/q/wCNH9o2P/P5b/8Af1f8aThQbblO9/NdrfkGnc6q21HQ9JuPt2mxX8l4oPkLc7AkTEY3EjlsduBQniRbfwrDplrCy3e6VZLg/wAMbkEqvPfAyfQY71yv9o2P/P5b/wDf1f8AGj+0bH/n8t/+/q/40OGHbvKV/V9r/wCYe6berahFfx6asSuDbWawPuA5YMxyOenzCs2q39o2P/P5b/8Af1f8aP7Rsf8An8t/+/q/41tCpRgrKS+8d0WaKrf2jY/8/lv/AN/V/wAaP7Rsf+fy3/7+r/jVe2pfzL7wuizRVb+0bH/n8t/+/q/40f2jY/8AP5b/APf1f8aPbUv5l94XRZoqt/aNj/z+W/8A39X/ABo/tGx/5/Lf/v6v+NHtqX8y+8Los0VW/tGx/wCfy3/7+r/jR/aNj/z+W/8A39X/ABo9tS/mX3hdH//Z", + "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQBLa273V3Dbx/flkVF+pOK7q8Phvw9J/Z76SupXMQxNIz7FDegOCTXJ+Hf+Rn0n/r8h/9DFXtf/5GPU/+vuX/ANDNbQfLDmtrcpaK5q/274d/6FGD/wACT/8AE1d1GbS9J+yfbvBUEX2u2S6g/wBMDb4nztbgHGcHg81xte1XGh2L/wDCP+Kdej36Fo/hyyaWIxM/2mVt4SMdAcMVJyccqCMMSF7aXZfcv8gucPp02l6t9r+w+CoJfsls91P/AKYF2RJjc3IGcZHA5ql/bvh3/oUYP/Ak/wDxNei2+h2Kf8JB4p0GPZoWseHL1oohEyfZpV2B4z1AywYjBxwwAwoJ8Vo9tLsvuX+QXOusz4b8Qyf2emkrptzKMQyK+9S3oTgEVwt1bva3c1vJ9+KRkb6g4rc0D/kY9M/6+4v/AEMVR8Rf8jPq3/X5N/6Gac3zQ5ra3B6q5reF9KsGsLrWdVBa0t3ESxqATI5GcDP1FaB1rw4DgeE4COxNwef/AB2qdn/yTc/9hf8A9o1kVTlyJKKW3ZP8x7HTQ6poVxPHBB4OjlmkYIkaTszMxOAAAvJJrQ+z2n/CQ/2D/wAIGv8AanmeV9m+0HOeuc7cbcc7s4xznHNRfDqGK31q71+6jR7XRLSS8KyqNkkuNsUe48KxY5U4JyvA9O98+P7d/wALO+yw+V/YO/z8v5f9pZ8nZs3btv8AB/dxznPNT7aXZfcv8guebzapoVvPJBP4OjimjYo8bzsrKwOCCCvBBpg1rw4Tg+E4AO5FweP/AB2tH4lwWs3iGDXtOH/Ev1q2S7jKxhQr/dkQlSQXBGW7gtz6ni6PbS7L7l/kFzT8UaVYLYWus6UCtpcOYmjYAGNwM4OPoa5u1t3uruG3j+/LIqL9ScV1F5/yTcf9hf8A9o1i+Hf+Rn0n/r8h/wDQxROKc1bS9hNanWXh8N+HpP7PfSV1K5iGJpGfYob0BwSarf274d/6FGD/AMCT/wDE1la//wAjHqf/AF9y/wDoZrPpzqtSaSVvRDbPRtB0M+JrF73SPAEFzbpIYmf+0ETDAAkYbB6MPzo17Qz4ZsUvdX8AQW1u8giV/wC0EfLEEgYXJ6Kfyrk/B3/I76B/2Erf/wBGLR4x/wCR31//ALCVx/6Map9tLsvuX+Qrlv8At3w7/wBCjB/4En/4mrNmfDfiGT+z00ldNuZRiGRX3qW9CcAiuRrQ0D/kY9M/6+4v/QxVQqtySaVvRDTMO6t3tbua3k+/FIyN9QcV0nhfSrBrC61nVQWtLdxEsagEyORnAz9RWT4i/wCRn1b/AK/Jv/QzW1Z/8k3P/YX/APaNKEUpu+triS1Lh1rw4DgeE4COxNwef/Hams7/AES/vreztvB8ElxcSLFEn2rG5mOAMlcDk965atrwf/yO2g/9hG3/APRi0e2l2X3L/IdzZiXT59eOhw+B45NSEzQGBLrJDqSGGQMYGDk5wACc4qreX+iWF9cWdz4PgjuLeRopU+1Z2spwRkLg8jtXf2t74Lg8ea1ZWx1e31/Ubm4s47+dEaO1ndnUtFsIYZY4BPOMcqCxryHUrGXS9Uu9PnZGmtZngdkJKllYqcZxxkUe2l2X3L/ILmyNa8OE4PhOADuRcHj/AMdrP8UaVYLYWus6UCtpcOYmjYAGNwM4OPoazK17z/km4/7C/wD7RqlLnTUktuyX5BuclRRRXOQFFFFABRRRQAUUUUAFFFFAFiwumsdQtrxFDNBKsoB7lSD/AErs7/w/Lr95LqmgtHdwXLGVo/NVZImPJDAkd64SitITSXLJXQ0zsv8AhB/Ef/QO/wDI8f8A8VXSeJIPF/iHStG0s6Y9vY6baRwCAXcbLJIq7TKeRyRgAHOOcHk15TRTvS/lf3r/ACHdHq3huDxf4e0rWdLGmPcWOpWkkBgN3GqxyMu0Sjk8gZBAxnjJ4Fc3/wAIP4j/AOgd/wCR4/8A4quNoovS7P7/APgBdHd2Hh+XQLyLVNeaO0gtmEqx+arSSsOQFAJ71xl/dNfahc3jqFaeVpSB2LEn+tV6KU5prlirITZ1fhy4tr/Q7nQJ7iO3macXNrJKcIz7dpUntkdKt/8ACE+Ie1gGHYiaPB/8eriaKpVItJTW3nb9GO/c9Tt9N8SWvgq88PQaIiNeXaz3F0J4t0kagbYiOuAw3A59Rjk5meHxbJ4Aj8KNpriGO789ZVuo1Bj5PlFQfmG8l8knnHHAryaijmpfyv7/APgBdHqdxpviS68FWfh6fREdrO7ae3ujPFujjYHdEB1wWO4nPoMcDGF/whPiHvYBR3JmjwP/AB6uJoo5qX8r+/8A4AXR1fiO4trDQ7bQILiO4mWc3N1JEcor7doUHvgda5ywumsdQtrxFDNBKsoB7lSD/Sq9FRKblK60E2d3f+H5dfvJdU0Fo7uC5YytH5qrJEx5IYEjvVb/AIQfxH/0Dv8AyPH/APFVxtFW505O7i7+v/AHdHrXhXSZ9A8qe+8Ef2lqEFyJ4Lr+1RD5e3aVGwEg4YE5PrijxVpM+v8Amz2Pgj+zdQnuTPPdf2qJvM3biw2EgDLEHI9MV5LRS5qX8r+9f5BdHZf8IP4j/wCgd/5Hj/8Aiqs2Hh+XQLyLVNeaO0gtmEqx+arSSsOQFAJ71wlFNTpxd1F39f8AgBdFi/umvtQubx1CtPK0pA7FiT/Wuj8OXFtf6Hc6BPcR28zTi5tZJThGfbtKk9sjpXKUVEZuMrvUSZ23/CE+Ie1gGHYiaPB/8eq7o/hjxFpOt2Gpf2V5v2S5jn8v7RGu/YwbGcnGcdcV55RV81L+V/f/AMAd0e7G4Eery61bfDeFdWaR50uJtX81FmbJ3mM4BwTnAx7EHBHC3nhTxRf31xeXNl5lxcSNLK/mxDczHJOAcDk9q4Oijmpfyv7/APgBdHbf8IT4h72AUdyZo8D/AMeqp4juLaw0O20CC4juJlnNzdSRHKK+3aFB74HWuUoodSKTUFv53/RBfsFFFFYkhRRRQAUUUUAek3XgrR4vF+oaUhf7Tb3E8/2Pedi2oLbFDZ3FwoRzycq3qprAt9L0i60hRHLaJfNpAlXzbsRj7R9sKkfMwAbyR909ucZ5rnTf3hvXvTdzm7dmZp/MO9iepLdSTk5+tRyTyzLEssrusS7IwzEhFyTgegyScepNAy9r0Nlbap5NiY2ijggV2jk3qZREnmkNk5Hmb+nHpxis2iigR2HhvRtKs9DufE2vMz2sR2xQqN24k4ACngsSG68ADNX4dV065uGih8CLxCk5eS+gRVjcAoWYxbRkEcE57Vm6lEZ/hLp8SlFZ9UiUF2CqCRcDkngD3NRal9nv7KXR4tQsEukisH3tcp5Unl25jdRJnblWb155rScpKbinZK22m8U366sxhCNRc0tdX+Da/Q2YNS0+e8uLQeAwk1t/rvNvIY1j7DLNCAM9uee1Nl1fSoGkSXwMUkjmWBozcxbt7AkADycnODyOPzFZV5NaarZXOk21/aCeH7JieWURx3PlQmNsM2BwTxnqKi/tSztfGemXJlWa3shbRSzoCQ5jRVZxxzgjj1wKXPP+Z/eyvYU+x0N/e6XpkayXfglERmKblvIXAYdVJWI4b2PNVB4i8Nk/8imv/gRH/wDGay7iGPStAu7SS9tLqa6uYnjW3lEgCoHy5I6Z3AAHB68VkJ1o55/zP72HsKfY68a74bP/ADKi/wDf+P8A+M1KuseG2P8AyKy/9/4//jNcmnUfWrMfWjnn/M/vYewp9jp11Pw2xH/FLr/3+j/+NVIt74bb/mWV/wC/0f8A8arnY+oqzH1/Cjnn/M/vY/YU+xvLceG2/wCZbX/v7H/8aqRX8Nt/zLi/9/I//jVYsfX8Ksx9KOef8z+9i9hT7Gqq+Gz/AMy8v/fyP/41Uq2/htv+ZfX/AL7j/wDjVZqd60YLuWO3MKeWF3bt3lruB46NjI6etHPP+Z/ew9hT7FpNK0B4JJh4dHlxkKx3x8E5x/yz9jVp/DejRQiWTw4qqcZ+eLK56ZHl5GferVxrdzPaCQXTsszKJ4WlPBHXaM/dYHkYxnj0qadokbUbr7TFKl0CIlVssdzhuR2wB370c8/5n97H7Cn2KcPhbRZ2dU8PplH2NmSEDd6AlOT9Ki/sDw4GKtogVh1B8vI/8h1oW6Ld6bBCs8UTxSuzCR9uQwX5h69OnXpS3kyXF/PNH9x3JB9RnrRzz/mf3sPYU+xRHh3w2f8AmDr/AOQ//jdSjwx4bP8AzCV/KP8A+N1ZToPpVlaOef8AM/vYewp9iiPCXhsnH9lL+Uf/AMRUo8G+Gyf+QYv/AHzH/wDEVpJ94fWrCdR9aOef8z+9h7Cn2MlfBHhtj/yDl/74j/8AiKkXwH4bb/mHr/3xH/8AEVtx9asp1FHPP+Z/ew9hT7GAvw98Nt/y4r/37j/+IqRfhx4bb/lyX/v3H/8AEV0cdWY+v4Uc8/5n97D2FPscuvwz8Nt/y6L/AN+o/wD4mpV+F3htv+XVf+/Mf/xNdjAB5Y+6CWwSwzmp1AUEherHr/Kjnn/M/vYewp9ji1+FHhth/wAe6/8AfmP/AOJqO6+GGkWEBu7GytJpIxny7i1jdX9sba79AAxHYE06Xm1l/wB0/wAqipVqQg5KTul6/gxqhT6I+QfGcVlD4svU063Fva/u2WEdEJjUsB7bice1YNbfi7/kaLz/AIB/6AtYlbYiKjVlFdG/zJpSc6cZPqkFFFFYmgVreFbaG98X6La3MYkgmv4I5EboymRQQfwNZNbXg448b6Af+olb/wDoxaAPsSMxxRrHGoRFGFVQAAPQCneaKo+b7mjzfc1RZ89fHS0tbXx9C9tCkRuLFJpdoxvfe67j74UflXmVen/HVt3jeyOf+Yan/oyWvMKklnVax/yR+z/7CUf8rmuCT7orvdY/5I/Z/wDYSj/lc1wSfdFXU/iy/wC3f/SImVD4PnL/ANKZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hVmPpVaPr+FWY+lAFhO9Wo+n41VTvVqPp+NAFiPp+NWU+6KrR9Pxqyn3RQBYT7oqynQfSqyfdFWU6D6UAWU6D6VZWqydB9KsrQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FIC3C7KMA8delTxswzz71Wj6GrEfegCzGT196klObWX/dP8qjj6fjUkn/AB6y/wC6f5VnX/hS9H+Q1ufH3i7/AJGi8/4B/wCgLWJW34u/5Gi8/wCAf+gLWJXViv48/V/mcuH/AIMPRfkFFFFYGwVs+EjjxnoR9NQt/wD0YtY1a/hU48YaIf8Ap/g/9GLQB9Xed9KPO+lUfOo86qLPEvjc27xnZn/qHp/6MkrzWvRPjM27xhaH/pwT/wBGSV53Uks6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETKh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8Ksx9KALCd6tR9PxqqnerUfT8aALEfT8asp90VWj6fjVlPuigCwn3RVlOg+lVk+6Ksp0H0oAsp0H0qytVk6D6VZWgCyn3h9asJ1H1qun3h9asJ1H1oAsx9asp1FVo+tWU6imMsR1Zj6/hVaOrMfX8KQFmPoasR96rx9DViPvQBZj6fjUkn/AB6y/wC6f5VHH0/GpJP+PWX/AHT/ACrOv/Cl6P8AIa3Pj7xd/wAjRef8A/8AQFrErb8Xf8jRef8AAP8A0BaxK6sV/Hn6v8zlw/8ABh6L8gooorA2CtXwwceLNGPpfQf+jFrKrY8JRef4z0OHdt8zULdc4zjMiigD6R84+9HnH3rZ/wCEVb/n+/8AIP8A9ej/AIRVv+f7/wAg/wD16ZR8+fF5t3iy1P8A04p/6MkrgK9J+NmnnTfGdnCZfN3aejZ27f8AlpIPX2rzakI6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETKh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8K1NJ0271e9js7KEyzv0A7D1J7CgBid6tR9PxrvbX4S3BhBudXjjkPVY4C4H4lh/Kra/CnaP+Q1/wCSv/2dAHn8fT8asp90V3a/C3aP+Qz/AOSv/wBnUi/DPaP+Qv8A+S3/ANnQBxCfdFWU6D6V2S/DjaP+Qr/5L/8A2VSj4e4H/IU/8l//ALKgDkU6D6VZWtPVPC15pURmDLPAv3nUYK/UVmLQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf8AhS9H+Q1ufH3i7/kaLz/gH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBWt4VNyPF+imzEZuhfweSJc7C/mLt3Y5xnGaya3fBX/I+eHf8AsJ23/o1aAPpfzviL/wA+3hz/AL6m/wAaPO+Iv/Pt4c/76m/xrsaKZR8u/GRtabxfaHXUskuvsCbRZltmzzJMZ3c5zn9K88r0/wCPF5b3fj6BbeZZDb2CQy7Tna4kkJX64YV5hSEdVrH/ACR+z/7CUf8AK5rgk+6K73WP+SP2f/YSj/lc1wSfdFXU/iy/7d/9IiZUPg+cv/SmWU6D6VYToPpVdOg+lWE6D6VBqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4V7H8IbGJdIvtQ2gzPP5O7uFVQ382/QV45H1/CvbfhH/wAipc/9fr/+gR0AXvFPi2907V7TQ9DskvdWuBvKyE7I09Tgj0PcYA96YJviKRn7L4dHsWl/xrOtefjle57WAx/3yleh0Acd53xF/wCfbw5/31N/jR53xF/59vDn/fU3+NdjRQBx3nfEX/n28Of99S/41y2qfEfxXo+sNpk9hpNxcINzpaiR8DGSPvcEAZ6cV1HjXxbNpzR6Hoi/aNdvPljRBnyQf4j2zjpnp1PHWbwx4OtvDekzPPtudTuI2N1ctyWJ5KgnnH8+p9AAbOhavB4j0C21KOIpFcocxvzgglWHuMg/WvPruEW9/cwL92OVkH0BIrqPhp/yT3SvpL/6Neub1T/kMX3/AF8Sf+hGgBqfeH1qwnUfWq6feH1qwnUfWgCzH1qynUVWj61ZTqKYyxHVmPr+FVo6sx9fwpAWY+hqxH3qvH0NWI+9AFmPp+NSSf8AHrL/ALp/lUcfT8akk/49Zf8AdP8AKs6/8KXo/wAhrc+PvF3/ACNF5/wD/wBAWsStvxd/yNF5/wAA/wDQFrErqxX8efq/zOXD/wAGHovyCiiisDYK3fBX/I+eHf8AsJ23/o1awq2/BjKnjnw+zMFVdStiSTgAeatAH2VXFeMvFVzb3Mfh3w+vn63dfKdvP2dSPvH0OOfYcntl/i7xsmmKmmaLsvdaujsijjIcR5/ib39B+J4qz4N8Ir4etpLu8k+06xd/Pc3DHJBPJUH0z1Pc/hhlHz58U/DieGPEOn2XnNPPJp6TXEpOd0hkkBI9uBXDV6t+0B/yPlj/ANgyP/0bLXlNIR1Wsf8AJH7P/sJR/wArmuCT7orvdY/5I/Z/9hKP+VzXBJ90VdT+LL/t3/0iJlQ+D5y/9KZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hXtvwj/5FS5/6/X/APQI68Sj6/hXtvwj/wCRUuf+v1//AECOgDA1jX4PDnxmlvLoH7M8KQysOSisi/N+BA/DNen3+rafpmky6reXcUVjFH5jTlsrtPTGOucjAHJJAGc15pqugWXiT4wX1hf+Z5P2MP8Au2wQQigH8M5rA8XSat4c8J6t4Kvle6t5lSTTbkcZVZVYr+QPHUHjkEUAdxZ+OPFmq2qX2l/D+aawny1vLPqkULyR5+VijDIyOe454JGDWdcfFt55tR02z0C+ttURoorSC8QrK7OpJLx4+XHGBk7tw6c1pal8W/DcHhmLU7C9hnurhf3Vm7hZEbv5i5yoB/PsSDmuA8DaVr/ivxfret2/iH+ztQRLeQzSaesxdZUJG0SY2gKoAIHIPBx1AO00Czbwl4m0W31OD7brfiH7S0940v8Ax7+WgfaBj5s5wTkdO4r0W4/49pf9w/yry+bS9d034peC/wC2/Ef9seZ9u8r/AEJLfysQfN90/NnI69Me9eoXH/HtL/uH+VAHL/DP/knul/SX/wBGvXN6p/yGL7/r4k/9CNdJ8M/+Se6X9Jf/AEa9c3qn/IYvv+viT/0I0ANT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf+FL0f5DW58feLv+RovP8AgH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBWr4XtItQ8W6NZT58m4voIn2nB2tIoOPwNZVbngshfHfh4kgAanbEk/8AXVaAPqrQPBmieG3aWwtf37DBmlbc+PQHt+Fb9Rfabf8A57xf99ij7Tb/APPeL/vsUyj5m+N2qR6l8QWSJGUWdslsSf4mDOxP/j2PwrzivT/jvFbJ4+gktwmZrCOSVkOdzb5FyffCr+VeYUhHVax/yR+z/wCwlH/K5rgk+6K73WP+SP2f/YSj/lc1wSfdFXU/iy/7d/8ASImVD4PnL/0pllOg+lWE6D6VXToPpVhOg+lQalkVZTrVYVZTrTAsJ1H1qzH1qsnUfWrMfWgZZj6irMfX8KrR9RVmPr+FAFiPr+Fe2/CP/kVLn/r9f/0COvEo+v4V7b8I/wDkVLn/AK/X/wDQI6AIbT/kuV9/14D/ANBSu01fRdP12yNpqVsk8RORngqfUEcg1wt1cw6L8aPtN+4ggvbMJFK5wucAcntyuPxFeiC6tyMieLH++KAOV034YeEdNleUaRDdSP3u1EoH4EY/HGa6G10ewstVv9Tt4Nl5qHl/aZN7HzPLXanBOBgHsB71Z+02/wDz3i/77FH2m3/57xf99igDz7xlqF3deNtNstEsbebWdOgkuIZ53Ybd67WRRkKSVA5b8MVt+DPFEnirwzPc3EKxXUDNFKE+6x25BHp16e1WNc8OaNrszXE04iuWt2tzNFIMlD2OfTtTLeLQfBPhaaGG4jjto1Z2Z5AXlcj9ScAce1AEPwz/AOSe6X9Jf/Rr1zeqf8hi+/6+JP8A0I10nw0GPh7pWfSX/wBGvXN6p/yGL7/r4k/9CNADU+8PrVhOo+tV0+8PrVhOo+tAFmPrVlOoqtH1qynUUxliOrMfX8KrR1Zj6/hSAsx9DViPvVePoasR96ALMfT8akk/49Zf90/yqOPp+NSSf8esv+6f5VnX/hS9H+Q1ufH3i7/kaLz/AIB/6AtYlbfi7/kaLz/gH/oC1iV1Yr+PP1f5nLh/4MPRfkFFFFYGwVq+GbOLUfFej2UxYRXF9BC5U4O1nAOPfmsqrel3U1jq9leW77J4J0ljbAO1lYEHB4PIoA+nP+FQeGv+el//AN/l/wDiaP8AhUHhr/npf/8Af5f/AImvMP8AhaXjD/oLj/wGi/8AiKP+FpeMP+guP/AaL/4imUYvxd8N2PhfxXa2Vg0zRPYpMTKwY7i8g7AcfKK4Guh8Y6/qXiLV4rzVLn7ROkAiVvLVMKGY4woA6k1z1IR1Wsf8kfs/+wlH/K5rgk+6K73WP+SP2f8A2Eo/5XNcEn3RV1P4sv8At3/0iJlQ+D5y/wDSmWU6D6VYToPpVdOg+lWE6D6VBqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4V6p8J9dgt/tOjTuEeZxNASfvNgBl+uAMfjXlcfX8KtREqQykgjBBHagD6M1zw9pniOzFtqdsJVU5RgcMh9iOlcqfhD4aJ4e/H0mH/AMTXC2njjxLbQiKPVZCo6eYiSH82BNXU8e+JiOdS7/8APCP/AOJoA63/AIVB4a/56X//AH+X/wCJo/4VB4a/56X/AP3+X/4muYTx14kI51Hv/wA8I/8A4mp08beISBnUP/IMf/xNAHQf8Kg8Nf8APXUP+/y//E1NbfCjwvbzLI8VzOFOdks3yn64Arn08Za+QM3/AP5Bj/8AiamXxdrpHN92/wCeSf8AxNAHpE01ppGnbiEht4U2qigAADooFeZTTNcXMszcNI5c/UnNR3Wo3moOHu7h5SOgJ4H0HQULQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf+FL0f5DW58feLv+RovP8AgH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBUkBxPGf9ofzqOnIcSKfcUAbXmj1o80etUvOHqaPOHqaBkeoNunU/7P8AU1UqW4bdID7VFQI6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETOh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8Ksx9KALCd6tR9PxqqnerUfT8aALEfT8asp90VWj6fjVlPuigCwn3RVlOg+lVk+6Ksp0H0oAsp0H0qytVk6D6VZWgCyn3h9asJ1H1qun3h9asJ1H1oAsx9asp1FVo+tWU6imMsR1Zj6/hVaOrMfX8KQFmPoasR96rx9DViPvQBZj6fjUkn/AB6y/wC6f5VHH0/GpJP+PWX/AHT/ACrOv/Cl6P8AIa3Pj7xd/wAjRef8A/8AQFrErb8Xf8jRef8AAP8A0BaxK6sV/Hn6v8zlw/8ABh6L8gooorA2CjOOfSimucIx9jQA/wA76Ued9Ko+b7Ueb7Uxl3du5oqKBtyE+9S0hHVax/yR+z/7CUf8rmuCT7orvdY/5I/Z/wDYSj/lc1wSfdFXU/iy/wC3f/SImdD4PnL/ANKZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hVmPpVaPr+FWY+lAFhO9Wo+n41VTvVqPp+NAFiPp+NWU+6KrR9Pxqyn3RQBYT7oqynQfSqyfdFWU6D6UAWU6D6VZWqydB9KsrQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/wB0/wAqjj6fjUkn/HrL/un+VZ1/4UvR/kNbnx94u/5Gi8/4B/6AtYlbfi7/AJGi8/4B/wCgLWJXViv48/V/mcuH/gw9F+QUUUVgbBTXUsjKOpBFOq9ounf2xr2naZ5vk/bLqK38zbu2b2C5xkZxnpmgDn/s1x/d/wDHhR9muP7v/jwrsl8JXi6aL6aWNIzavcbV+ZkIAZVccbSysGHXIPscWn8J2I06K8TWfNRri3t38qFZMGVHbIVZC/BQjBVSew4xQM4+2jeOLD9Sc1NWnr2jtoOpHT5phJcxopm2rhFY8gKf4hgjnA5JxkYJzKBHVax/yR+z/wCwlH/K5rgk+6K9A1SKSX4OwMilhFqEbvj+Ff365P4so/EV5+n3RVVP4sv+3f8A0iJnR+D5y/8ASmWU6D6VYToPpVdOg+lWE6D6VJqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4VZj6VWj6/hVmPpQBYTvVqPp+NVU71aj6fjQBYj6fjVlPuiq0fT8asp90UAWE+6Ksp0H0qsn3RVlOg+lAFlOg+lWVqsnQfSrK0AWU+8PrVhOo+tV0+8PrVhOo+tAFmPrVlOoqtH1qynUUxliOrMfX8KrR1Zj6/hSAsx9DViPvVePoasR96ALMfT8akk/49Zf90/yqOPp+NPmYLaSliANp5P0rOv8Awpej/Ia3Pj/xd/yNF5/wD/0BaxK2/F3/ACNF5/wD/wBAWsSurFfx5+r/ADObD/wYei/IKKKKwNQq3peoS6Tq1lqUCo01pOk8ayAlSyMGAOCDjI9aqUUAbEXibU431ZjKsn9qoUuQ68HJzuAHQjkD0BI6Gqp1rVWS2RtTvStrzADO2IuMfLz8vHHFUaKAJJJ5ZljWWV3WJdkYZidi5JwPQZJOPc1HRRQB0XhnxVLoiz2d1Al3ps4IeFwGwD1G08EHAOOMHmrp1PwIWLf8IsQSc8STAfl51chRV8yfxJN/12sZumm7ptHYDVfAo6eF2/7+zf8Ax6nDWfBA6eGG/wC/s3/x6uNopXj/AC/i/wDMXsv7zO1/tzwV/wBCy3/fyX/49Th4g8GDp4bb/v5L/wDHq4iii8f5fxf+Yez/ALzO5HiTweOnhxv++5f/AI9Th4o8Ijp4db/vuT/49XCUUXj/AC/i/wDMPZv+ZnejxX4THTw83/fUn/x6njxf4VHTw+3/AH1J/wDHq8/oovH+X8X/AJh7N/zM9CHjPwwOmgN+cn/x2nDxv4aHTQW/N/8A47XndFF4/wAv4v8AzD2b/mZ6MPHXhwdNCb83/wDjtOHj7w+OmiN/4/8A/Ha83oovH+X8X/mHs3/Mz0ofELQR00Vv/H//AI7Tx8RdDHTRm/Jv/jteZUUXj/L+L/zD2b/mZ6ePiToo6aO35N/8dpw+JukDppDf98t/8dry6ii8f5fxf+Y/Zv8AmZ6mPihpQ6aS3/fLf/Had/wtTTB/zCm/75P/AMcryqii8f5fxf8AmHs3/Mz1gfFjTx00tv8Avg//ABynD4uWI6aY3/fB/wDjleS0UXj/AC/i/wDMPZv+Znrg+MFmOmnN/wB+/wD7ZTh8Y7YdNPb/AL9//bK8hoovH+X8X/mHs3/Mz2AfGeAdLBv+/X/2ynD41xDpYt/36/8AtleO0UXj/L+L/wAw9m/5meyj43KOlk3/AH5H/wAcpw+OWOlm3/fkf/F14xRReP8AL+L/AMw9m/5me0j47MOlo3/fkf8AxdRz/GmHUU+z3q3kNs3EhtoE3EenL141RT5o78q/F/m7B7Lu395reJtXh13xDd6jb232aCQqscWclVVQgye5IUE+5NZNFFS227s0CiiikAqKXdUXqxwKtfYc3ZhEo2gZEmOD6fqcVDbyCGUSEElQduPXHFP+0j7GIgCJAcbv9kc4/M1lPnv7v9f8MehhVhVC9bV79enT/t5vfdW8yuQQcHrVhYI/Kjd5HBfOAsee+PWo53WSZnUEBjkj37/rVmG6VIYl86eMpnIQcHnPrRNy5U0LC06HtZxqNNLb715rpfqVZozDM8ZIJU4yKIozLIEBA6kk9AB1NJK4eV3C7QzEgelOhl8qTcRuUgqwzjIIxV+9y+ZgvZOvr8F/wv8AeLIkSrmOYuc4IKYqKpZPIC/ujITn+IAYFRUR2JrpKeiS9Ltfi2FFFFUYhRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV1uj+ELG/XTBd6zJbS6jaSXFvGlqJC7rK8flAmRRuOzIyRknHXGeSrrbzUfC15Bpdi82si3sLRoluVt4lfeZnkOY95BGHx98HigZmvpuiC8MI1u4iRZVRmubAoyrtYsSqu3IIVQM87u2DV8+DP7QjtJvD+oLfQXLTIDdKtoyNEqu+QzlcbWByG9c4xUOs65p2t63cPLBJBZzyxM915QkusJHsJ+8qkufnYZ69+ObniXxTBd3mi32k6jqj3unxBGkuYliUFCNjIiu4BI+8OASM45NAFbU/B40fTbG9vdWs9t3BK4W2mjnIkUuFUbHOVYoAXHClsHkU1fDWn3un3Umk6017e2kCzywG0aNGUsqnY5bLEFxwVXPOKraprVrcaibi0tc2727oLS5BaO1eQHf5QDcKGYsvTBPIOMnX1HxTYy+H4LbTbu8s5kt7ZJLSLToI4pZIwu5nmVt7Aspf5lPOOnUAFTVvCVvp0Gpxw6qbjUNJC/boDbFEXLrGdj7jvw7KDlV65GRXL12ninxjF4hsZ2S7vo5rqUSz2jW8Xl5yTjzgQ7qCflDDjjniuLoA2PD2jwaxcXguruW2gtbVrl2hgEzkKVGApZf73r2qXWNBtrLSLTVbC9muLS4mkgAubbyJA6BScKGYFcMOQevUCpPCGtwaFf3ss91fWn2ize3S4sVDSxMWU7hl1/unv3qXxV4hg1m0022ju9R1CS080vfaiAJZA5UhMBm+VcHGWP3j0oA5miiigRpaZpP8Aadjqcsc+LiygFwsGzPmoGAcg54KghsYOQD6Vo6b4e03VbdYbbWy2rNbyTi1+yMI/kVnKGQt97ap/hxnvVvw1qfhjS5NNvbt9TjvYGkW7jhtkljuY2yCmWlUjKEqeO9TnxJpEXhn+zrC6v7GZYZ4WMWm25a5DSOy75t4kAKsqsBkYHQ9wZiafoC6haxXS3RFuFlN0Vj3NCURnwBkbtyqSDkchh/DmqGqWP9m6jLa+Z5gXaysV2kqwDDIycHBGRng8V07eMIF+ypE98sJysoGFa2QqgVYSG/gZd4J25PGOWzx8sjyyvJI7O7sWZ2OSxPUk+tAH/9k=", "export_temp_image": false, "force_export_images": false, "flat_export": false, @@ -23,7 +23,7 @@ "theme_color1": 5, "theme_color2": 0, "custom_variable_prefix": "uic", - "backup_cnt": 67, + "backup_cnt": 72, "autosave_cnt": 0, "group_color_cnt": 0, "lvgl_version": "9.1.0", diff --git a/ui/PyroVision.spj b/ui/PyroVision.spj index 7a115b7..8363e16 100644 --- a/ui/PyroVision.spj +++ b/ui/PyroVision.spj @@ -2416,536 +2416,562 @@ ], "saved_objtypeKey": "LABEL", "tree_closed": true + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Main StatusBar", + "InheritedType": 10 }, { - "guid": "GUID80595604-430558S178244357", - "deepid": -245967836, - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Label Main MinTemp", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 65, - 0 - ], - "InheritedType": 7 - }, + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 320, + 8 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ { - "nid": 60, - "flags": 51, - "strtype": "OBJECT/Size", - "intarray": [ - 1, - 1 + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 10620, + "strtype": "_style/Bg_Image_opa", + "integer": 180, + "InheritedType": 6 + } ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "LEFT_MID", - "InheritedType": 3 - }, - { - "nid": 90, - "flags": 1048576, - "strtype": "OBJECT/Flags", "InheritedType": 1 - }, - { - "nid": 100, - "strtype": "OBJECT/Hidden", - "strval": "True", - "InheritedType": 2 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, + } + ], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID69843562-430548S5034357", + "deepid": 1933161859, + "children": [ + { + "guid": "GUID40000558-68999S1814355", + "deepid": -1577322599, + "children": [ { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "nid": 1010, - "strtype": "LABEL/Label", - "InheritedType": 1 - }, - { - "nid": 1020, - "strtype": "LABEL/Long_mode", - "strval": "WRAP", - "InheritedType": 3 - }, - { - "nid": 1030, - "strtype": "LABEL/Text", - "strval": "-99.99 °C", - "InheritedType": 10 - }, - { - "part": "lv.PART.MAIN", - "childs": [ + "guid": "GUID90690797-862847S1705954", + "deepid": 1275935300, + "dont_export": false, + "locked": false, + "properties": [ { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Main Thermal Scene ROI", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 240, + 180 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "OFF", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", "childs": [ { - "nid": 10410, - "strtype": "_style/Text_Color", - "intarray": [ - 0, - 77, - 255, - 255 + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 240, + 63, + 238, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } ], - "InheritedType": 7 - }, - { - "nid": 10450, - "strtype": "_style/Text_Font", - "strval": "montserrat_12", - "InheritedType": 3 + "InheritedType": 1 } ], - "InheritedType": 1 + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 } ], - "nid": 1040, - "strtype": "LABEL/Style_main", - "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "LABEL" - }, - { - "guid": "GUID52255350-430560S2614357", - "deepid": 1196125914, - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Label Main MaxTemp", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 + "saved_objtypeKey": "PANEL", + "tree_closed": true }, { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 130, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 51, - "strtype": "OBJECT/Size", - "intarray": [ - 1, - 1 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "LEFT_MID", - "InheritedType": 3 - }, - { - "nid": 90, - "flags": 1048576, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 100, - "strtype": "OBJECT/Hidden", - "strval": "True", - "InheritedType": 2 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "nid": 1010, - "strtype": "LABEL/Label", - "InheritedType": 1 - }, - { - "nid": 1020, - "strtype": "LABEL/Long_mode", - "strval": "WRAP", - "InheritedType": 3 - }, - { - "nid": 1030, - "strtype": "LABEL/Text", - "strval": "+99.99 °C", - "InheritedType": 10 - }, - { - "part": "lv.PART.MAIN", - "childs": [ + "guid": "GUID41153353-862846S1193154", + "deepid": 1275935300, + "dont_export": false, + "locked": false, + "properties": [ { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10410, - "strtype": "_style/Text_Color", - "intarray": [ - 255, - 0, - 0, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10450, - "strtype": "_style/Text_Font", - "strval": "montserrat_12", - "InheritedType": 3 - } + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Main Thermal Spotmeter ROI", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 119, + 89 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", "InheritedType": 1 - } - ], - "nid": 1040, - "strtype": "LABEL/Style_main", - "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "LABEL" - } - ], - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Container Main StatusBar", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 0, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 33, - "strtype": "OBJECT/Size", - "intarray": [ - 320, - 8 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "TOP_MID", - "InheritedType": 3 - }, - { - "nid": 90, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 130, - "strtype": "OBJECT/Press_lock", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 140, - "strtype": "OBJECT/Click_focusable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 210, - "strtype": "OBJECT/Gesture_bubble", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 220, - "strtype": "OBJECT/Snappable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 230, - "strtype": "OBJECT/Scrollable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "part": "lv.PART.MAIN", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ + }, { - "nid": 10520, - "strtype": "_style/Bg_Color", - "intarray": [ - 0, - 0, - 0, - 0 + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "OFF", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } ], - "InheritedType": 7 + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 }, { - "nid": 10620, - "strtype": "_style/Bg_Image_opa", - "integer": 180, - "InheritedType": 6 + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 } ], - "InheritedType": 1 - } - ], - "nid": 1010, - "strtype": "CONTAINER/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", - "InheritedType": 11 - }, - { - "part": "lv.PART.SCROLLBAR", - "childs": [], - "nid": 1020, - "strtype": "CONTAINER/Style_scrollbar", - "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "CONTAINER" - }, - { - "guid": "GUID69843562-430548S5034357", - "deepid": 1933161859, - "children": [ - { - "guid": "GUID40000558-68999S1814355", - "deepid": -1577322599, - "children": [ + "saved_objtypeKey": "PANEL", + "tree_closed": true + }, { - "guid": "GUID34728151-155431S6754356", + "guid": "GUID326283-862848S2227654", "deepid": 1275935300, "dont_export": false, "locked": false, @@ -2953,7 +2979,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Image Main Thermal ROI", + "strval": "Image Main Thermal Video Focus ROI", "InheritedType": 10 }, { @@ -2994,15 +3020,15 @@ "flags": 17, "strtype": "OBJECT/Size", "intarray": [ - 60, - 60 + 238, + 178 ], "InheritedType": 7 }, { "nid": 70, "strtype": "OBJECT/Align", - "strval": "TOP_LEFT", + "strval": "CENTER", "InheritedType": 3 }, { @@ -3092,9 +3118,9 @@ "nid": 10710, "strtype": "_style/Border_Color", "intarray": [ - 123, - 63, + 235, 240, + 63, 255 ], "InheritedType": 7 @@ -3123,18 +3149,19 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "PANEL" + "saved_objtypeKey": "PANEL", + "tree_closed": true }, { - "guid": "GUID49515181-98916S7624362", - "deepid": 869040931, + "guid": "GUID34728151-155431S6754356", + "deepid": 1275935300, "dont_export": false, "locked": false, "properties": [ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label Main Thermal Crosshair", + "strval": "Image Main Thermal AGC ROI", "InheritedType": 10 }, { @@ -3172,11 +3199,11 @@ }, { "nid": 60, - "flags": 51, + "flags": 17, "strtype": "OBJECT/Size", "intarray": [ - 1, - 1 + 240, + 180 ], "InheritedType": 7 }, @@ -3188,15 +3215,197 @@ }, { "nid": 90, - "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "OFF", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 63, + 150, + 240, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL", + "tree_closed": true + }, + { + "guid": "GUID49515181-98916S7624362", + "deepid": 869040931, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Thermal Crosshair", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 }, { "nid": 225, @@ -3412,21 +3621,21 @@ "strval": "DEFAULT", "childs": [ { - "nid": 10450, - "strtype": "_style/Text_Font", - "strval": "montserrat_14", - "InheritedType": 3 - }, - { - "nid": 10520, - "strtype": "_style/Bg_Color", + "nid": 10410, + "strtype": "_style/Text_Color", "intarray": [ 255, 255, 255, - 127 + 192 ], "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_14", + "InheritedType": 3 } ], "InheritedType": 1 @@ -3439,430 +3648,554 @@ } ], "saved_objtypeKey": "LABEL" - } - ], - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Image Thermal", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 10, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 17, - "strtype": "OBJECT/Size", - "intarray": [ - 240, - 180 - ], - "InheritedType": 7 }, { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "nid": 90, - "flags": 1048576, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 130, - "strtype": "OBJECT/Press_lock", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 140, - "strtype": "OBJECT/Click_focusable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 210, - "strtype": "OBJECT/Gesture_bubble", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 220, - "strtype": "OBJECT/Snappable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 230, - "strtype": "OBJECT/Scrollable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "nid": 1010, - "strtype": "IMAGE/Image", - "InheritedType": 1 - }, - { - "nid": 1020, - "strtype": "IMAGE/Asset", - "strval": "-", - "InheritedType": 5 - }, - { - "nid": 1030, - "strtype": "IMAGE/Pivot", - "intarray": [ - 0, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 1040, - "strtype": "IMAGE/Rotation", - "InheritedType": 6 - }, - { - "nid": 1050, - "strtype": "IMAGE/Scale", - "integer": 256, - "InheritedType": 6 - }, - { - "nid": 1060, - "strtype": "IMAGE/Inner_align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "part": "lv.PART.MAIN", - "childs": [ + "guid": "GUID87870619-989445S5396453", + "deepid": 565092003, + "children": [ { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ + "guid": "GUID1108541-989447S92453", + "deepid": -1719762389, + "dont_export": false, + "locked": false, + "properties": [ { - "nid": 10510, - "strtype": "_style/Bg_Radius", - "integer": 3, - "InheritedType": 6 + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Thermal Scene Max", + "InheritedType": 10 }, { - "nid": 10520, - "strtype": "_style/Bg_Color", + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", "intarray": [ 0, - 0, - 0, - 255 + 0 ], "InheritedType": 7 }, { - "nid": 10530, - "strtype": "_style/Bg_gradiens_Color", + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", "intarray": [ - 255, - 255, - 255 + 1, + 1 ], "InheritedType": 7 }, { - "nid": 10550, - "strtype": "_style/Gradient direction", - "strval": "HOR", + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "100.0", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 192 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + }, + { + "nid": 10620, + "strtype": "_style/Bg_Image_opa", + "integer": 255, + "InheritedType": 6 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 5, + 0, + 0, + 0 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 } ], - "InheritedType": 1 - } - ], - "nid": 1070, - "strtype": "IMAGE/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Image, Transform", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "IMAGE" - }, - { - "guid": "GUID78751988-155420S8764356", - "deepid": -1253876820, - "children": [ - { - "guid": "GUID884834-155424S6724356", - "deepid": 809747492, - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Label TempScaleMax", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 0, - -80 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 18, - "strtype": "OBJECT/Size", - "intarray": [ - 100, - 20 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "nid": 90, - "flags": 1048576, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "nid": 1010, - "strtype": "LABEL/Label", - "InheritedType": 1 + "saved_objtypeKey": "LABEL" }, { - "nid": 1020, - "strtype": "LABEL/Long_mode", - "strval": "WRAP", - "InheritedType": 3 - }, - { - "nid": 1030, - "strtype": "LABEL/Text", - "strval": "Max", - "InheritedType": 10 - }, - { - "part": "lv.PART.MAIN", - "childs": [ + "guid": "GUID15732503-989449S57553", + "deepid": -1719762389, + "dont_export": false, + "locked": false, + "properties": [ { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10410, - "strtype": "_style/Text_Color", - "intarray": [ - 255, - 255, - 255, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10430, - "strtype": "_style/Text_Align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "nid": 10440, - "strtype": "_style/Text_Decor", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 10450, - "strtype": "_style/Text_Font", - "strval": "montserrat_10", - "InheritedType": 3 - } + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Thermal Scene Min", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", "InheritedType": 1 - } - ], - "nid": 1040, - "strtype": "LABEL/Style_main", - "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "LABEL", - "tree_closed": true - }, - { - "guid": "GUID79834816-155425S5454356", - "deepid": -1310920733, - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Image Gradient", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "-40.0", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 192 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + }, + { + "nid": 10620, + "strtype": "_style/Bg_Image_opa", + "integer": 255, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID77339875-989450S1050253", + "deepid": -1719762389, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Main Thermal Scene Mean", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "RIGHT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "80.0", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 192 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + }, + { + "nid": 10620, + "strtype": "_style/Bg_Image_opa", + "integer": 255, + "InheritedType": 6 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 5, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Main Thermal Scene Statistics", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 }, { "Flow": 0, @@ -3897,15 +4230,15 @@ "flags": 18, "strtype": "OBJECT/Size", "intarray": [ - 50, - 150 + 100, + 20 ], "InheritedType": 7 }, { "nid": 70, "strtype": "OBJECT/Align", - "strval": "CENTER", + "strval": "BOTTOM_MID", "InheritedType": 3 }, { @@ -3914,6 +4247,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "flags": 1048576, @@ -3957,106 +4296,1083 @@ "InheritedType": 1 }, { + "part": "lv.PART.MAIN", + "childs": [], "nid": 1010, - "strtype": "IMAGE/Image", - "InheritedType": 1 + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 }, { + "part": "lv.PART.SCROLLBAR", + "childs": [], "nid": 1020, - "strtype": "IMAGE/Asset", - "strval": "-", - "InheritedType": 5 - }, - { - "nid": 1030, - "strtype": "IMAGE/Pivot", - "intarray": [ - 0, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 1040, - "strtype": "IMAGE/Rotation", - "InheritedType": 6 - }, - { - "nid": 1050, - "strtype": "IMAGE/Scale", - "integer": 256, - "InheritedType": 6 - }, - { - "nid": 1060, - "strtype": "IMAGE/Inner_align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "part": "lv.PART.MAIN", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10510, - "strtype": "_style/Bg_Radius", - "integer": 3, - "InheritedType": 6 - }, - { - "nid": 10520, - "strtype": "_style/Bg_Color", - "intarray": [ - 0, - 0, - 0, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10530, - "strtype": "_style/Bg_gradiens_Color", - "intarray": [ - 255, - 255, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10550, - "strtype": "_style/Gradient direction", - "strval": "VER", - "InheritedType": 3 - } - ], - "InheritedType": 1 - } - ], - "nid": 1070, - "strtype": "IMAGE/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Image, Transform", + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", "InheritedType": 11 } ], - "saved_objtypeKey": "IMAGE", - "tree_closed": true + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Thermal", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 10, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 240, + 180 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "IMAGE/Image", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "IMAGE/Asset", + "strval": "-", + "InheritedType": 5 + }, + { + "nid": 1030, + "strtype": "IMAGE/Pivot", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1040, + "strtype": "IMAGE/Rotation", + "InheritedType": 6 + }, + { + "nid": 1050, + "strtype": "IMAGE/Scale", + "integer": 256, + "InheritedType": 6 + }, + { + "nid": 1060, + "strtype": "IMAGE/Inner_align", + "strval": "CENTER", + "InheritedType": 3 }, { - "guid": "GUID76026531-155422S4054356", - "deepid": 809747492, + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 3, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10530, + "strtype": "_style/Bg_gradiens_Color", + "intarray": [ + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10550, + "strtype": "_style/Gradient direction", + "strval": "HOR", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1070, + "strtype": "IMAGE/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Image, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "IMAGE" + }, + { + "guid": "GUID78751988-155420S8764356", + "deepid": -1253876820, + "children": [ + { + "guid": "GUID884834-155424S6724356", + "deepid": 809747492, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label TempScaleMax", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + -80 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 20 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Max", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 10440, + "strtype": "_style/Text_Decor", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + }, + { + "guid": "GUID79834816-155425S5454356", + "deepid": -1310920733, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Image Gradient", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 150 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "IMAGE/Image", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "IMAGE/Asset", + "strval": "-", + "InheritedType": 5 + }, + { + "nid": 1030, + "strtype": "IMAGE/Pivot", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 1040, + "strtype": "IMAGE/Rotation", + "InheritedType": 6 + }, + { + "nid": 1050, + "strtype": "IMAGE/Scale", + "integer": 256, + "InheritedType": 6 + }, + { + "nid": 1060, + "strtype": "IMAGE/Inner_align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 3, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 0, + 0, + 0, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10530, + "strtype": "_style/Bg_gradiens_Color", + "intarray": [ + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10550, + "strtype": "_style/Gradient direction", + "strval": "VER", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1070, + "strtype": "IMAGE/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Image, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "IMAGE", + "tree_closed": true + }, + { + "guid": "GUID76026531-155422S4054356", + "deepid": 809747492, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label TempScaleMin", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 90 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 18, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 20 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Min", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Gradient", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + -135, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 40, + 190 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Main Thermal", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 10 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 75 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID12873756-430552S3484357", + "deepid": -741119918, + "children": [ + { + "guid": "GUID15522018-73173S422354359", + "deepid": -755641011, + "children": [ + { + "guid": "GUID60809533-73172S422354359", + "deepid": -1351592592, "dont_export": false, "locked": false, "properties": [ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label TempScaleMin", + "strval": "Label Main Button WiFi", "InheritedType": 10 }, { @@ -4088,17 +5404,17 @@ "strtype": "OBJECT/Position", "intarray": [ 0, - 90 + 0 ], "InheritedType": 7 }, { "nid": 60, - "flags": 18, + "flags": 51, "strtype": "OBJECT/Size", "intarray": [ - 100, - 20 + 1, + 1 ], "InheritedType": 7 }, @@ -4170,7 +5486,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "Min", + "strval": "W", "InheritedType": 10 }, { @@ -4192,16 +5508,10 @@ ], "InheritedType": 7 }, - { - "nid": 10430, - "strtype": "_style/Text_Align", - "strval": "CENTER", - "InheritedType": 3 - }, { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "fa", "InheritedType": 3 } ], @@ -4214,8 +5524,7 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" } ], "dont_export": false, @@ -4224,7 +5533,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Container Gradient", + "strval": "Button Main WiFi", "InheritedType": 10 }, { @@ -4233,7 +5542,7 @@ "InheritedType": 1 }, { - "Flow": 1, + "Flow": 0, "Wrap": false, "Reversed": false, "MainAlignment": 0, @@ -4255,18 +5564,18 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - -135, + -20, 0 ], "InheritedType": 7 }, { "nid": 60, - "flags": 17, + "flags": 33, "strtype": "OBJECT/Size", "intarray": [ - 40, - 190 + 50, + 95 ], "InheritedType": 7 }, @@ -4278,19 +5587,11 @@ }, { "nid": 90, - "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, { "nid": 225, - "flags": 1048576, "strtype": "OBJECT/Scrolling", "InheritedType": 1 }, @@ -4300,6 +5601,24 @@ "strval": "False", "InheritedType": 2 }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, { "nid": 300, "strtype": "OBJECT/Scrollbar_mode", @@ -4332,165 +5651,123 @@ }, { "part": "lv.PART.MAIN", - "childs": [], + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 50, + 50, + 50, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], "nid": 1010, - "strtype": "CONTAINER/Style_main", + "strtype": "BUTTON/Style_main", "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", "InheritedType": 11 }, { - "part": "lv.PART.SCROLLBAR", - "childs": [], - "nid": 1020, - "strtype": "CONTAINER/Style_scrollbar", - "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "CONTAINER" - } - ], - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Container Main Thermal", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 0, - 10 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 34, - "strtype": "OBJECT/Size", - "intarray": [ - 100, - 75 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "nid": 90, - "flags": 1048576, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 230, - "strtype": "OBJECT/Scrollable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "part": "lv.PART.MAIN", - "childs": [], - "nid": 1010, - "strtype": "CONTAINER/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", - "InheritedType": 11 + "disabled": false, + "nid": 1000441, + "strtype": "_event/EventHandler", + "strval": "CLICKED", + "childs": [ + { + "nid": 1000442, + "strtype": "_event/name", + "strval": "ButtonMainWiFiClicked", + "InheritedType": 10 + }, + { + "nid": 1000443, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000444, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000445, + "strtype": "_event/action", + "strval": "CALL FUNCTION", + "childs": [ + { + "nid": 1000446, + "strtype": "CALL FUNCTION/Name", + "strval": "CALL FUNCTION", + "InheritedType": 10 + }, + { + "nid": 1000447, + "strtype": "CALL FUNCTION/Call", + "strval": "<{Function_name}>( event_struct )", + "InheritedType": 10 + }, + { + "nid": 1000448, + "strtype": "CALL FUNCTION/CallC", + "strval": "<{Function_name}>( e );", + "InheritedType": 10 + }, + { + "nid": 1000449, + "strtype": "CALL FUNCTION/Function_name", + "strval": "ButtonMainWiFiClicked", + "InheritedType": 10 + }, + { + "nid": 1000450, + "strtype": "CALL FUNCTION/Dont_export_function", + "strval": "False", + "InheritedType": 2 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "BUTTON" }, { - "part": "lv.PART.SCROLLBAR", - "childs": [], - "nid": 1020, - "strtype": "CONTAINER/Style_scrollbar", - "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "CONTAINER" - }, - { - "guid": "GUID12873756-430552S3484357", - "deepid": -741119918, - "children": [ - { - "guid": "GUID15522018-73173S422354359", + "guid": "GUID29848968-155427S6724356", "deepid": -755641011, "children": [ { - "guid": "GUID60809533-73172S422354359", + "guid": "GUID77308716-155429S1584356", "deepid": -1351592592, "dont_export": false, "locked": false, @@ -4498,7 +5775,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label Main Button WiFi", + "strval": "Label Main Button ROI", "InheritedType": 10 }, { @@ -4612,7 +5889,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "W", + "strval": "R", "InheritedType": 10 }, { @@ -4659,7 +5936,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Button Main WiFi", + "strval": "Button Main ROI", "InheritedType": 10 }, { @@ -4690,7 +5967,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - -20, + 100, 0 ], "InheritedType": 7 @@ -4713,6 +5990,7 @@ }, { "nid": 90, + "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, @@ -4819,89 +6097,24 @@ "strtype": "BUTTON/Style_main", "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", "InheritedType": 11 - }, - { - "disabled": false, - "nid": 1000441, - "strtype": "_event/EventHandler", - "strval": "CLICKED", - "childs": [ - { - "nid": 1000442, - "strtype": "_event/name", - "strval": "ButtonMainWiFiClicked", - "InheritedType": 10 - }, - { - "nid": 1000443, - "strtype": "_event/condition_C", - "strval": "", - "InheritedType": 10 - }, - { - "nid": 1000444, - "strtype": "_event/condition_P", - "strval": "", - "InheritedType": 10 - }, - { - "nid": 1000445, - "strtype": "_event/action", - "strval": "CALL FUNCTION", - "childs": [ - { - "nid": 1000446, - "strtype": "CALL FUNCTION/Name", - "strval": "CALL FUNCTION", - "InheritedType": 10 - }, - { - "nid": 1000447, - "strtype": "CALL FUNCTION/Call", - "strval": "<{Function_name}>( event_struct )", - "InheritedType": 10 - }, - { - "nid": 1000448, - "strtype": "CALL FUNCTION/CallC", - "strval": "<{Function_name}>( e );", - "InheritedType": 10 - }, - { - "nid": 1000449, - "strtype": "CALL FUNCTION/Function_name", - "strval": "ButtonMainWiFiClicked", - "InheritedType": 10 - }, - { - "nid": 1000450, - "strtype": "CALL FUNCTION/Dont_export_function", - "strval": "False", - "InheritedType": 2 - } - ], - "InheritedType": 10 - } - ], - "InheritedType": 4 } ], "saved_objtypeKey": "BUTTON" }, { - "guid": "GUID29848968-155427S6724356", - "deepid": -755641011, + "guid": "GUID61733416-934770S366964356", + "deepid": -211345156, "children": [ { - "guid": "GUID77308716-155429S1584356", - "deepid": -1351592592, + "guid": "GUID96116950-934769S366964356", + "deepid": 986580644, "dont_export": false, "locked": false, "properties": [ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label Main Button ROI", + "strval": "Label Main Button Info", "InheritedType": 10 }, { @@ -5015,7 +6228,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "R", + "strval": "I", "InheritedType": 10 }, { @@ -5026,17 +6239,6 @@ "strtype": "_style/StyleState", "strval": "DEFAULT", "childs": [ - { - "nid": 10410, - "strtype": "_style/Text_Color", - "intarray": [ - 255, - 255, - 255, - 255 - ], - "InheritedType": 7 - }, { "nid": 10450, "strtype": "_style/Text_Font", @@ -5053,7 +6255,8 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL" + "saved_objtypeKey": "LABEL", + "tree_closed": true } ], "dont_export": false, @@ -5062,7 +6265,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Button Main ROI", + "strval": "Button Main Info", "InheritedType": 10 }, { @@ -5093,7 +6296,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 100, + 40, 0 ], "InheritedType": 7 @@ -5194,7 +6397,7 @@ 50, 50, 50, - 255 + 200 ], "InheritedType": 7 }, @@ -5210,29 +6413,104 @@ "InheritedType": 7 }, { - "nid": 10720, - "strtype": "_style/Border width", - "integer": 2, + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000292, + "strtype": "_event/EventHandler", + "strval": "CLICKED", + "childs": [ + { + "nid": 1000293, + "strtype": "_event/name", + "strval": "ButtonMainInfoClicked", + "InheritedType": 10 + }, + { + "nid": 1000294, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000295, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000296, + "strtype": "_event/action", + "strval": "CHANGE SCREEN", + "childs": [ + { + "nid": 1000297, + "strtype": "CHANGE SCREEN/Name", + "strval": "CHANGE SCREEN", + "InheritedType": 10 + }, + { + "nid": 1000298, + "strtype": "CHANGE SCREEN/Call", + "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", + "InheritedType": 10 + }, + { + "nid": 1000299, + "strtype": "CHANGE SCREEN/CallC", + "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", + "InheritedType": 10 + }, + { + "nid": 1000300, + "strtype": "CHANGE SCREEN/Screen_to", + "strval": "GUID10820859-155348S7984356", + "InheritedType": 9 + }, + { + "nid": 1000301, + "strtype": "CHANGE SCREEN/Fade_mode", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 1000302, + "strtype": "CHANGE SCREEN/Speed", + "InheritedType": 6 + }, + { + "nid": 1000303, + "strtype": "CHANGE SCREEN/Delay", "InheritedType": 6 } ], - "InheritedType": 1 + "InheritedType": 10 } ], - "nid": 1010, - "strtype": "BUTTON/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", - "InheritedType": 11 + "InheritedType": 4 } ], "saved_objtypeKey": "BUTTON" }, { - "guid": "GUID61733416-934770S366964356", + "guid": "GUID93999632-650710S271964356", "deepid": -211345156, "children": [ { - "guid": "GUID96116950-934769S366964356", + "guid": "GUID5832432-650712S5674356", "deepid": 986580644, "dont_export": false, "locked": false, @@ -5240,7 +6518,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label Main Button Info", + "strval": "Label Main Button Menu", "InheritedType": 10 }, { @@ -5354,7 +6632,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "I", + "strval": "M", "InheritedType": 10 }, { @@ -5391,7 +6669,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Button Main Info", + "strval": "Button Main Menu", "InheritedType": 10 }, { @@ -5422,7 +6700,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 40, + -80, 0 ], "InheritedType": 7 @@ -5555,70 +6833,70 @@ }, { "disabled": false, - "nid": 1000292, + "nid": 1000268, "strtype": "_event/EventHandler", "strval": "CLICKED", "childs": [ { - "nid": 1000293, + "nid": 1000269, "strtype": "_event/name", - "strval": "ButtonMainInfoClicked", + "strval": "ButtonMainMenuClicked", "InheritedType": 10 }, { - "nid": 1000294, + "nid": 1000270, "strtype": "_event/condition_C", "strval": "", "InheritedType": 10 }, { - "nid": 1000295, + "nid": 1000271, "strtype": "_event/condition_P", "strval": "", "InheritedType": 10 }, { - "nid": 1000296, + "nid": 1000272, "strtype": "_event/action", "strval": "CHANGE SCREEN", "childs": [ { - "nid": 1000297, + "nid": 1000273, "strtype": "CHANGE SCREEN/Name", "strval": "CHANGE SCREEN", "InheritedType": 10 }, { - "nid": 1000298, + "nid": 1000274, "strtype": "CHANGE SCREEN/Call", "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", "InheritedType": 10 }, { - "nid": 1000299, + "nid": 1000275, "strtype": "CHANGE SCREEN/CallC", "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", "InheritedType": 10 }, { - "nid": 1000300, + "nid": 1000276, "strtype": "CHANGE SCREEN/Screen_to", - "strval": "GUID10820859-155348S7984356", + "strval": "GUID40629891-934771S164356", "InheritedType": 9 }, { - "nid": 1000301, + "nid": 1000277, "strtype": "CHANGE SCREEN/Fade_mode", "strval": "NONE", "InheritedType": 3 }, { - "nid": 1000302, + "nid": 1000278, "strtype": "CHANGE SCREEN/Speed", "InheritedType": 6 }, { - "nid": 1000303, + "nid": 1000279, "strtype": "CHANGE SCREEN/Delay", "InheritedType": 6 } @@ -5626,176 +6904,371 @@ "InheritedType": 10 } ], - "InheritedType": 4 + "InheritedType": 4 + } + ], + "saved_objtypeKey": "BUTTON" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Main Buttons", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 106, + -14 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 10 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "isPage": true, + "editor_posx": 800, + "editor_posy": -400, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Main", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "SCREEN/Screen", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "SCREEN/Temporary", + "strval": "False", + "InheritedType": 2 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 } ], - "saved_objtypeKey": "BUTTON" + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "SCREEN/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1050, + "strtype": "SCREEN/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000248, + "strtype": "_event/EventHandler", + "strval": "SCREEN_LOADED", + "childs": [ + { + "nid": 1000249, + "strtype": "_event/name", + "strval": "ScreenMainLoaded", + "InheritedType": 10 }, { - "guid": "GUID93999632-650710S271964356", - "deepid": -211345156, - "children": [ - { - "guid": "GUID5832432-650712S5674356", - "deepid": 986580644, - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Label Main Button Menu", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 0, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 51, - "strtype": "OBJECT/Size", - "intarray": [ - 1, - 1 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "nid": 90, - "flags": 1048576, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "nid": 1010, - "strtype": "LABEL/Label", - "InheritedType": 1 - }, - { - "nid": 1020, - "strtype": "LABEL/Long_mode", - "strval": "WRAP", - "InheritedType": 3 - }, - { - "nid": 1030, - "strtype": "LABEL/Text", - "strval": "M", - "InheritedType": 10 - }, - { - "part": "lv.PART.MAIN", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10450, - "strtype": "_style/Text_Font", - "strval": "fa", - "InheritedType": 3 - } - ], - "InheritedType": 1 - } - ], - "nid": 1040, - "strtype": "LABEL/Style_main", - "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "nid": 1000250, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000251, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000252, + "strtype": "_event/action", + "strval": "CALL FUNCTION", + "childs": [ + { + "nid": 1000253, + "strtype": "CALL FUNCTION/Name", + "strval": "CALL FUNCTION", + "InheritedType": 10 + }, + { + "nid": 1000254, + "strtype": "CALL FUNCTION/Call", + "strval": "<{Function_name}>( event_struct )", + "InheritedType": 10 + }, + { + "nid": 1000255, + "strtype": "CALL FUNCTION/CallC", + "strval": "<{Function_name}>( e );", + "InheritedType": 10 + }, + { + "nid": 1000256, + "strtype": "CALL FUNCTION/Function_name", + "strval": "ScreenMainLoaded", + "InheritedType": 10 + }, + { + "nid": 1000257, + "strtype": "CALL FUNCTION/Dont_export_function", + "strval": "False", + "InheritedType": 2 } ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "SCREEN" + }, + { + "guid": "GUID40629891-934771S164356", + "deepid": 871077125, + "children": [ + { + "guid": "GUID32876125-838323S38634360", + "deepid": 1097060484, + "children": [ + { + "guid": "GUID67585624-838322S38634360", + "deepid": 894182266, "dont_export": false, "locked": false, "properties": [ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Button Main Menu", + "strval": "Label Menu Header", "InheritedType": 10 }, { @@ -5826,18 +7299,18 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - -80, + 0, 0 ], "InheritedType": 7 }, { "nid": 60, - "flags": 33, + "flags": 51, "strtype": "OBJECT/Size", "intarray": [ - 50, - 95 + 1, + 1 ], "InheritedType": 7 }, @@ -5849,39 +7322,45 @@ }, { "nid": 90, - "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, { - "nid": 225, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 }, { - "nid": 230, - "strtype": "OBJECT/Scrollable", + "nid": 130, + "strtype": "OBJECT/Press_lock", "strval": "False", "InheritedType": 2 }, { - "nid": 240, - "strtype": "OBJECT/Scroll_elastic", + "nid": 140, + "strtype": "OBJECT/Click_focusable", "strval": "False", "InheritedType": 2 }, { - "nid": 250, - "strtype": "OBJECT/Scroll_momentum", + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", "strval": "False", "InheritedType": 2 }, { - "nid": 270, - "strtype": "OBJECT/Scroll_chain", + "nid": 220, + "strtype": "OBJECT/Snappable", "strval": "False", "InheritedType": 2 }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, { "nid": 300, "strtype": "OBJECT/Scrollbar_mode", @@ -5912,6 +7391,23 @@ "strtype": "OBJECT/States", "InheritedType": 1 }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "MENU", + "InheritedType": 10 + }, { "part": "lv.PART.MAIN", "childs": [ @@ -5921,119 +7417,33 @@ "strval": "DEFAULT", "childs": [ { - "nid": 10520, - "strtype": "_style/Bg_Color", - "intarray": [ - 50, - 50, - 50, - 200 - ], - "InheritedType": 7 - }, - { - "nid": 10710, - "strtype": "_style/Border_Color", + "nid": 10410, + "strtype": "_style/Text_Color", "intarray": [ - 185, - 152, + 255, + 255, 255, 255 ], "InheritedType": 7 }, { - "nid": 10720, - "strtype": "_style/Border width", - "integer": 2, - "InheritedType": 6 + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_14", + "InheritedType": 3 } ], "InheritedType": 1 } ], - "nid": 1010, - "strtype": "BUTTON/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", "InheritedType": 11 - }, - { - "disabled": false, - "nid": 1000268, - "strtype": "_event/EventHandler", - "strval": "CLICKED", - "childs": [ - { - "nid": 1000269, - "strtype": "_event/name", - "strval": "ButtonMainMenuClicked", - "InheritedType": 10 - }, - { - "nid": 1000270, - "strtype": "_event/condition_C", - "strval": "", - "InheritedType": 10 - }, - { - "nid": 1000271, - "strtype": "_event/condition_P", - "strval": "", - "InheritedType": 10 - }, - { - "nid": 1000272, - "strtype": "_event/action", - "strval": "CHANGE SCREEN", - "childs": [ - { - "nid": 1000273, - "strtype": "CHANGE SCREEN/Name", - "strval": "CHANGE SCREEN", - "InheritedType": 10 - }, - { - "nid": 1000274, - "strtype": "CHANGE SCREEN/Call", - "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", - "InheritedType": 10 - }, - { - "nid": 1000275, - "strtype": "CHANGE SCREEN/CallC", - "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", - "InheritedType": 10 - }, - { - "nid": 1000276, - "strtype": "CHANGE SCREEN/Screen_to", - "strval": "GUID40629891-934771S164356", - "InheritedType": 9 - }, - { - "nid": 1000277, - "strtype": "CHANGE SCREEN/Fade_mode", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 1000278, - "strtype": "CHANGE SCREEN/Speed", - "InheritedType": 6 - }, - { - "nid": 1000279, - "strtype": "CHANGE SCREEN/Delay", - "InheritedType": 6 - } - ], - "InheritedType": 10 - } - ], - "InheritedType": 4 } ], - "saved_objtypeKey": "BUTTON" + "saved_objtypeKey": "LABEL" } ], "dont_export": false, @@ -6042,7 +7452,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Container Main Buttons", + "strval": "Panel Menu Header", "InheritedType": 10 }, { @@ -6073,36 +7483,59 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 11, - 97 + 1, + 1 ], "InheritedType": 7 }, { "nid": 60, - "flags": 34, + "flags": 33, "strtype": "OBJECT/Size", "intarray": [ - 100, - 10 + 320, + 8 ], "InheritedType": 7 }, { "nid": 70, "strtype": "OBJECT/Align", - "strval": "CENTER", + "strval": "TOP_MID", "InheritedType": 3 }, { "nid": 90, - "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, { - "nid": 110, - "strtype": "OBJECT/Clickable", + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", "strval": "False", "InheritedType": 2 }, @@ -6150,9 +7583,45 @@ }, { "part": "lv.PART.MAIN", - "childs": [], + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], "nid": 1010, - "strtype": "CONTAINER/Style_main", + "strtype": "PANEL/Style_main", "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", "InheritedType": 11 }, @@ -6160,241 +7629,316 @@ "part": "lv.PART.SCROLLBAR", "childs": [], "nid": 1020, - "strtype": "CONTAINER/Style_scrollbar", + "strtype": "PANEL/Style_scrollbar", "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", "InheritedType": 11 } ], - "saved_objtypeKey": "CONTAINER" - } - ], - "isPage": true, - "editor_posx": 800, - "editor_posy": -400, - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Main", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 1, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 1, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 90, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 130, - "strtype": "OBJECT/Press_lock", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 230, - "strtype": "OBJECT/Scrollable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "nid": 1010, - "strtype": "SCREEN/Screen", - "InheritedType": 1 - }, - { - "nid": 1020, - "strtype": "SCREEN/Temporary", - "strval": "False", - "InheritedType": 2 + "saved_objtypeKey": "PANEL" }, { - "part": "lv.PART.MAIN", - "childs": [ + "guid": "GUID16541557-838428S3954360", + "deepid": -1892524658, + "dont_export": false, + "locked": false, + "properties": [ { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10520, - "strtype": "_style/Bg_Color", - "intarray": [ - 30, - 30, - 30, - 255 - ], - "InheritedType": 7 - } - ], + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Menu", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", "InheritedType": 1 - } - ], - "nid": 1040, - "strtype": "SCREEN/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Pad, Text", - "InheritedType": 11 - }, - { - "part": "lv.PART.SCROLLBAR", - "childs": [], - "nid": 1050, - "strtype": "SCREEN/Style_scrollbar", - "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", - "InheritedType": 11 - }, - { - "disabled": false, - "nid": 1000248, - "strtype": "_event/EventHandler", - "strval": "SCREEN_LOADED", - "childs": [ + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 15 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 75 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, { - "nid": 1000249, - "strtype": "_event/name", - "strval": "ScreenMainLoaded", - "InheritedType": 10 + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 }, { - "nid": 1000250, - "strtype": "_event/condition_C", - "strval": "", - "InheritedType": 10 + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 }, { - "nid": 1000251, - "strtype": "_event/condition_P", - "strval": "", - "InheritedType": 10 + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 }, { - "nid": 1000252, - "strtype": "_event/action", - "strval": "CALL FUNCTION", - "childs": [ - { - "nid": 1000253, - "strtype": "CALL FUNCTION/Name", - "strval": "CALL FUNCTION", - "InheritedType": 10 - }, - { - "nid": 1000254, - "strtype": "CALL FUNCTION/Call", - "strval": "<{Function_name}>( event_struct )", - "InheritedType": 10 - }, - { - "nid": 1000255, - "strtype": "CALL FUNCTION/CallC", - "strval": "<{Function_name}>( e );", - "InheritedType": 10 - }, - { - "nid": 1000256, - "strtype": "CALL FUNCTION/Function_name", - "strval": "ScreenMainLoaded", - "InheritedType": 10 - }, + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + }, + { + "guid": "GUID84576620-989468S627153", + "deepid": -741119918, + "children": [ + { + "guid": "GUID258430-989467S627153", + "deepid": -211345156, + "children": [ { - "nid": 1000257, - "strtype": "CALL FUNCTION/Dont_export_function", - "strval": "False", - "InheritedType": 2 + "guid": "GUID30745183-989466S627153", + "deepid": 986580644, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Menu Back", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "B", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "fa", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true } ], - "InheritedType": 10 - } - ], - "InheritedType": 4 - } - ], - "saved_objtypeKey": "SCREEN" - }, - { - "guid": "GUID40629891-934771S164356", - "deepid": 871077125, - "children": [ - { - "guid": "GUID32876125-838323S38634360", - "deepid": 1097060484, - "children": [ - { - "guid": "GUID67585624-838322S38634360", - "deepid": 894182266, "dont_export": false, "locked": false, "properties": [ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label Menu Header", + "strval": "Button Menu Back", "InheritedType": 10 }, { @@ -6425,18 +7969,18 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 0, + -80, 0 ], "InheritedType": 7 }, { "nid": 60, - "flags": 51, + "flags": 33, "strtype": "OBJECT/Size", "intarray": [ - 1, - 1 + 50, + 95 ], "InheritedType": 7 }, @@ -6448,45 +7992,39 @@ }, { "nid": 90, + "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 }, { - "nid": 130, - "strtype": "OBJECT/Press_lock", + "nid": 230, + "strtype": "OBJECT/Scrollable", "strval": "False", "InheritedType": 2 }, { - "nid": 140, - "strtype": "OBJECT/Click_focusable", + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", "strval": "False", "InheritedType": 2 }, { - "nid": 210, - "strtype": "OBJECT/Gesture_bubble", + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", "strval": "False", "InheritedType": 2 }, { - "nid": 220, - "strtype": "OBJECT/Snappable", + "nid": 270, + "strtype": "OBJECT/Scroll_chain", "strval": "False", "InheritedType": 2 }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, { "nid": 300, "strtype": "OBJECT/Scrollbar_mode", @@ -6518,260 +8056,136 @@ "InheritedType": 1 }, { - "nid": 1010, - "strtype": "LABEL/Label", - "InheritedType": 1 - }, - { - "nid": 1020, - "strtype": "LABEL/Long_mode", - "strval": "WRAP", - "InheritedType": 3 - }, - { - "nid": 1030, - "strtype": "LABEL/Text", - "strval": "MENU", - "InheritedType": 10 - }, - { - "part": "lv.PART.MAIN", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10410, - "strtype": "_style/Text_Color", - "intarray": [ - 255, - 255, - 255, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10450, - "strtype": "_style/Text_Font", - "strval": "montserrat_14", - "InheritedType": 3 - } - ], - "InheritedType": 1 - } - ], - "nid": 1040, - "strtype": "LABEL/Style_main", - "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "LABEL" - } - ], - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Panel Menu Header", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 1, - 1 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 33, - "strtype": "OBJECT/Size", - "intarray": [ - 320, - 12 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "TOP_MID", - "InheritedType": 3 - }, - { - "nid": 90, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 130, - "strtype": "OBJECT/Press_lock", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 140, - "strtype": "OBJECT/Click_focusable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 210, - "strtype": "OBJECT/Gesture_bubble", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 220, - "strtype": "OBJECT/Snappable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 230, - "strtype": "OBJECT/Scrollable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "part": "lv.PART.MAIN", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", + "part": "lv.PART.MAIN", "childs": [ { - "nid": 10510, - "strtype": "_style/Bg_Radius", - "InheritedType": 6 + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 50, + 50, + 50, + 200 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1000268, + "strtype": "_event/EventHandler", + "strval": "CLICKED", + "childs": [ + { + "nid": 1000269, + "strtype": "_event/name", + "strval": "ButtonMenuBackClicked", + "InheritedType": 10 }, { - "nid": 10520, - "strtype": "_style/Bg_Color", - "intarray": [ - 123, - 63, - 240, - 255 - ], - "InheritedType": 7 + "nid": 1000270, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 }, { - "nid": 10710, - "strtype": "_style/Border_Color", - "intarray": [ - 123, - 63, - 240, - 255 + "nid": 1000271, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000272, + "strtype": "_event/action", + "strval": "CHANGE SCREEN", + "childs": [ + { + "nid": 1000273, + "strtype": "CHANGE SCREEN/Name", + "strval": "CHANGE SCREEN", + "InheritedType": 10 + }, + { + "nid": 1000274, + "strtype": "CHANGE SCREEN/Call", + "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", + "InheritedType": 10 + }, + { + "nid": 1000275, + "strtype": "CHANGE SCREEN/CallC", + "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", + "InheritedType": 10 + }, + { + "nid": 1000276, + "strtype": "CHANGE SCREEN/Screen_to", + "strval": "GUID63572141-853113S4094354", + "InheritedType": 9 + }, + { + "nid": 1000277, + "strtype": "CHANGE SCREEN/Fade_mode", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 1000278, + "strtype": "CHANGE SCREEN/Speed", + "InheritedType": 6 + }, + { + "nid": 1000279, + "strtype": "CHANGE SCREEN/Delay", + "InheritedType": 6 + } ], - "InheritedType": 7 + "InheritedType": 10 } ], - "InheritedType": 1 + "InheritedType": 4 } ], - "nid": 1010, - "strtype": "PANEL/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", - "InheritedType": 11 - }, - { - "part": "lv.PART.SCROLLBAR", - "childs": [], - "nid": 1020, - "strtype": "PANEL/Style_scrollbar", - "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", - "InheritedType": 11 + "saved_objtypeKey": "BUTTON" } ], - "saved_objtypeKey": "PANEL" - }, - { - "guid": "GUID16541557-838428S3954360", - "deepid": -1892524658, "dont_export": false, "locked": false, "properties": [ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Container Menu", + "strval": "Container Menu Buttons", "InheritedType": 10 }, { @@ -6803,17 +8217,17 @@ "strtype": "OBJECT/Position", "intarray": [ 0, - 15 + 100 ], "InheritedType": 7 }, { "nid": 60, - "flags": 18, + "flags": 34, "strtype": "OBJECT/Size", "intarray": [ 100, - 210 + 10 ], "InheritedType": 7 }, @@ -6921,7 +8335,7 @@ "MainAlignment": 0, "CrossAlignment": 0, "TrackAlignment": 0, - "LayoutType": 0, + "LayoutType": 1, "nid": 30, "strtype": "OBJECT/Layout_type", "strval": "No_layout", @@ -7420,11 +8834,11 @@ }, { "nid": 60, - "flags": 17, + "flags": 33, "strtype": "OBJECT/Size", "intarray": [ 320, - 30 + 8 ], "InheritedType": 7 }, @@ -14298,141 +15712,689 @@ "locked": false, "properties": [ { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Info Container7", - "InheritedType": 10 + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Container7", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 2, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 172, + -2 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 }, { - "nid": 20, - "strtype": "OBJECT/Layout", + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", "InheritedType": 1 }, { - "Flow": 1, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 2, - "LayoutType": 1, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 }, { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Container Lepton", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "TOP_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [], + "nid": 1010, + "strtype": "CONTAINER/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "CONTAINER/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "CONTAINER" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Panel Lepton", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 80 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 17, + "strtype": "OBJECT/Size", + "intarray": [ + 300, + 140 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 6, + "InheritedType": 6 }, { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", + "nid": 10520, + "strtype": "_style/Bg_Color", "intarray": [ - 172, - -2 + 37, + 37, + 37, + 255 ], "InheritedType": 7 }, { - "nid": 60, - "flags": 34, - "strtype": "OBJECT/Size", + "nid": 11110, + "strtype": "_style/Padding", "intarray": [ - 50, - 100 + 5, + 5, + 5, + 0 ], "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "nid": 90, - "flags": 1048576, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 230, - "strtype": "OBJECT/Scrollable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "part": "lv.PART.MAIN", - "childs": [], - "nid": 1010, - "strtype": "CONTAINER/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", - "InheritedType": 11 - }, - { - "part": "lv.PART.SCROLLBAR", - "childs": [], - "nid": 1020, - "strtype": "CONTAINER/Style_scrollbar", - "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", - "InheritedType": 11 } ], - "saved_objtypeKey": "CONTAINER" + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Panel Info Content", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + -276, + 104 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 320, + 75 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "ON", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "VER", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 30, + 30, + 30, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 10, + 10 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "PANEL/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "part": "lv.PART.SCROLLBAR", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10510, + "strtype": "_style/Bg_Radius", + "integer": 2, + "InheritedType": 6 + }, + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 123, + 63, + 240, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "InheritedType": 6 } ], + "InheritedType": 1 + } + ], + "nid": 1020, + "strtype": "PANEL/Style_scrollbar", + "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "PANEL" + }, + { + "guid": "GUID26295868-989474S771453", + "deepid": -741119918, + "children": [ + { + "guid": "GUID79481689-989473S771453", + "deepid": -211345156, + "children": [ + { + "guid": "GUID14912377-989472S771453", + "deepid": 986580644, "dont_export": false, "locked": false, "properties": [ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Container Lepton", + "strval": "Label Info Back", "InheritedType": 10 }, { @@ -14447,7 +16409,7 @@ "MainAlignment": 0, "CrossAlignment": 0, "TrackAlignment": 0, - "LayoutType": 1, + "LayoutType": 0, "nid": 30, "strtype": "OBJECT/Layout_type", "strval": "No_layout", @@ -14470,18 +16432,18 @@ }, { "nid": 60, - "flags": 34, + "flags": 51, "strtype": "OBJECT/Size", "intarray": [ - 100, - 100 + 1, + 1 ], "InheritedType": 7 }, { "nid": 70, "strtype": "OBJECT/Align", - "strval": "TOP_MID", + "strval": "CENTER", "InheritedType": 3 }, { @@ -14502,12 +16464,6 @@ "strtype": "OBJECT/Scrolling", "InheritedType": 1 }, - { - "nid": 230, - "strtype": "OBJECT/Scrollable", - "strval": "False", - "InheritedType": 2 - }, { "nid": 300, "strtype": "OBJECT/Scrollbar_mode", @@ -14539,23 +16495,48 @@ "InheritedType": 1 }, { - "part": "lv.PART.MAIN", - "childs": [], "nid": 1010, - "strtype": "CONTAINER/Style_main", - "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", - "InheritedType": 11 + "strtype": "LABEL/Label", + "InheritedType": 1 }, { - "part": "lv.PART.SCROLLBAR", - "childs": [], "nid": 1020, - "strtype": "CONTAINER/Style_scrollbar", - "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "B", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "fa", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", "InheritedType": 11 } ], - "saved_objtypeKey": "CONTAINER" + "saved_objtypeKey": "LABEL", + "tree_closed": true } ], "dont_export": false, @@ -14564,7 +16545,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Panel Lepton", + "strval": "Button Info Back", "InheritedType": 10 }, { @@ -14573,13 +16554,13 @@ "InheritedType": 1 }, { - "Flow": 1, + "Flow": 0, "Wrap": false, "Reversed": false, "MainAlignment": 0, "CrossAlignment": 0, "TrackAlignment": 0, - "LayoutType": 1, + "LayoutType": 0, "nid": 30, "strtype": "OBJECT/Layout_type", "strval": "No_layout", @@ -14595,66 +16576,35 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 0, - 80 + -80, + 0 ], "InheritedType": 7 }, { "nid": 60, - "flags": 17, + "flags": 33, "strtype": "OBJECT/Size", "intarray": [ - 300, - 140 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "CENTER", - "InheritedType": 3 - }, - { - "nid": 90, - "flags": 1048576, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 130, - "strtype": "OBJECT/Press_lock", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 140, - "strtype": "OBJECT/Click_focusable", - "strval": "False", - "InheritedType": 2 + 50, + 95 + ], + "InheritedType": 7 }, { - "nid": 210, - "strtype": "OBJECT/Gesture_bubble", - "strval": "False", - "InheritedType": 2 + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 }, { - "nid": 220, - "strtype": "OBJECT/Snappable", - "strval": "False", - "InheritedType": 2 + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 }, { "nid": 225, - "flags": 1048576, "strtype": "OBJECT/Scrolling", "InheritedType": 1 }, @@ -14720,53 +16670,120 @@ "strtype": "_style/StyleState", "strval": "DEFAULT", "childs": [ - { - "nid": 10510, - "strtype": "_style/Bg_Radius", - "integer": 6, - "InheritedType": 6 - }, { "nid": 10520, "strtype": "_style/Bg_Color", "intarray": [ - 37, - 37, - 37, - 255 + 50, + 50, + 50, + 200 ], "InheritedType": 7 }, { - "nid": 11110, - "strtype": "_style/Padding", + "nid": 10710, + "strtype": "_style/Border_Color", "intarray": [ - 5, - 5, - 5, - 0 + 185, + 152, + 255, + 255 ], "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 } ], "InheritedType": 1 } ], "nid": 1010, - "strtype": "PANEL/Style_main", + "strtype": "BUTTON/Style_main", "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", "InheritedType": 11 }, { - "part": "lv.PART.SCROLLBAR", - "childs": [], - "nid": 1020, - "strtype": "PANEL/Style_scrollbar", - "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", - "InheritedType": 11 + "disabled": false, + "nid": 1000268, + "strtype": "_event/EventHandler", + "strval": "CLICKED", + "childs": [ + { + "nid": 1000269, + "strtype": "_event/name", + "strval": "ButtonInfoBackClicked", + "InheritedType": 10 + }, + { + "nid": 1000270, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000271, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1000272, + "strtype": "_event/action", + "strval": "CHANGE SCREEN", + "childs": [ + { + "nid": 1000273, + "strtype": "CHANGE SCREEN/Name", + "strval": "CHANGE SCREEN", + "InheritedType": 10 + }, + { + "nid": 1000274, + "strtype": "CHANGE SCREEN/Call", + "strval": "ChangeScreen( <{Screen_to}>, lv.SCR_LOAD_ANIM.<{Fade_mode}>, <{Speed}>, <{Delay}>)", + "InheritedType": 10 + }, + { + "nid": 1000275, + "strtype": "CHANGE SCREEN/CallC", + "strval": "_ui_screen_change( &<{Screen_to}>, LV_SCR_LOAD_ANIM_<{Fade_mode}>, <{Speed}>, <{Delay}>, &<{Screen_to}>_screen_init);", + "InheritedType": 10 + }, + { + "nid": 1000276, + "strtype": "CHANGE SCREEN/Screen_to", + "strval": "GUID63572141-853113S4094354", + "InheritedType": 9 + }, + { + "nid": 1000277, + "strtype": "CHANGE SCREEN/Fade_mode", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 1000278, + "strtype": "CHANGE SCREEN/Speed", + "InheritedType": 6 + }, + { + "nid": 1000279, + "strtype": "CHANGE SCREEN/Delay", + "InheritedType": 6 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 } ], - "saved_objtypeKey": "PANEL" + "saved_objtypeKey": "BUTTON" } ], "dont_export": false, @@ -14775,7 +16792,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Panel Info Content", + "strval": "Container Info Buttons", "InheritedType": 10 }, { @@ -14784,13 +16801,13 @@ "InheritedType": 1 }, { - "Flow": 1, + "Flow": 0, "Wrap": false, "Reversed": false, "MainAlignment": 0, "CrossAlignment": 0, "TrackAlignment": 0, - "LayoutType": 1, + "LayoutType": 0, "nid": 30, "strtype": "OBJECT/Layout_type", "strval": "No_layout", @@ -14807,46 +16824,60 @@ "strtype": "OBJECT/Position", "intarray": [ 0, - 30 + 100 ], "InheritedType": 7 }, { "nid": 60, - "flags": 17, + "flags": 34, "strtype": "OBJECT/Size", "intarray": [ - 320, - 210 + 100, + 10 ], "InheritedType": 7 }, { "nid": 70, "strtype": "OBJECT/Align", - "strval": "TOP_MID", + "strval": "CENTER", "InheritedType": 3 }, { "nid": 90, + "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, + "flags": 1048576, "strtype": "OBJECT/Scrolling", "InheritedType": 1 }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, { "nid": 300, "strtype": "OBJECT/Scrollbar_mode", - "strval": "ON", + "strval": "AUTO", "InheritedType": 3 }, { "nid": 310, "strtype": "OBJECT/Scroll_direction", - "strval": "VER", + "strval": "ALL", "InheritedType": 3 }, { @@ -14863,105 +16894,28 @@ }, { "nid": 320, + "flags": 1048576, "strtype": "OBJECT/States", "InheritedType": 1 }, { "part": "lv.PART.MAIN", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10510, - "strtype": "_style/Bg_Radius", - "InheritedType": 6 - }, - { - "nid": 10520, - "strtype": "_style/Bg_Color", - "intarray": [ - 30, - 30, - 30, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10710, - "strtype": "_style/Border_Color", - "intarray": [ - 30, - 30, - 30, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 11110, - "strtype": "_style/Padding", - "intarray": [ - 0, - 0, - 10, - 10 - ], - "InheritedType": 7 - } - ], - "InheritedType": 1 - } - ], + "childs": [], "nid": 1010, - "strtype": "PANEL/Style_main", + "strtype": "CONTAINER/Style_main", "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", "InheritedType": 11 }, { "part": "lv.PART.SCROLLBAR", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10510, - "strtype": "_style/Bg_Radius", - "integer": 2, - "InheritedType": 6 - }, - { - "nid": 10520, - "strtype": "_style/Bg_Color", - "intarray": [ - 123, - 63, - 240, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10720, - "strtype": "_style/Border width", - "InheritedType": 6 - } - ], - "InheritedType": 1 - } - ], + "childs": [], "nid": 1020, - "strtype": "PANEL/Style_scrollbar", + "strtype": "CONTAINER/Style_scrollbar", "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", "InheritedType": 11 } ], - "saved_objtypeKey": "PANEL" + "saved_objtypeKey": "CONTAINER" } ], "isPage": true, @@ -14982,13 +16936,13 @@ "InheritedType": 1 }, { - "Flow": 0, + "Flow": 1, "Wrap": false, "Reversed": false, "MainAlignment": 0, "CrossAlignment": 0, "TrackAlignment": 0, - "LayoutType": 0, + "LayoutType": 1, "nid": 30, "strtype": "OBJECT/Layout_type", "strval": "No_layout", @@ -15289,7 +17243,7 @@ "theme_color1": 5, "theme_color2": 0, "custom_variable_prefix": "uic", - "backup_cnt": 66, + "backup_cnt": 71, "autosave_cnt": 0, "group_color_cnt": 0, "lvgl_version": "9.1.0", diff --git a/ui/project.info b/ui/project.info index 34c7657..0504663 100644 --- a/ui/project.info +++ b/ui/project.info @@ -1,7 +1,7 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2025-12-31T14:34:25.0600669+01:00", + "datetime": "2026-01-05T13:41:48.0249747+01:00", "editor_version": "1.5.4", - "project_version": 84, + "project_version": 92, "user": "Kampert Daniel" } \ No newline at end of file From 2c32e9d6c624f55fecd41df96a49818e01a2047d Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Mon, 12 Jan 2026 16:09:41 +0100 Subject: [PATCH 03/26] Feature: Issue #6 Signed-off-by: Daniel Kampert --- data/default_settings.json | 34 +++ .../Network/Provisioning/provisioning.cpp | 20 +- .../Manager/Network/network_types.h | 10 + .../Manager/Settings/settingsManager.cpp | 247 ++++++++++++++++-- .../Manager/Settings/settingsManager.h | 8 +- .../Manager/Settings/settings_types.h | 24 +- main/Application/Tasks/Lepton/leptonTask.cpp | 3 +- .../Application/Tasks/Network/networkTask.cpp | 13 +- main/CMakeLists.txt | 2 +- main/main.cpp | 5 + partitions.csv | 8 +- platformio.ini | 13 +- sdkconfig.debug | 17 -- 13 files changed, 322 insertions(+), 82 deletions(-) create mode 100644 data/default_settings.json diff --git a/data/default_settings.json b/data/default_settings.json new file mode 100644 index 0000000..34e5493 --- /dev/null +++ b/data/default_settings.json @@ -0,0 +1,34 @@ +{ + "lepton" : { + "emissivity" : [ + { + "name" : "Concrete", + "value" : 0.92 + }, + { + "name" : "Human Skin", + "value" : 0.98 + }, + { + "name" : "Water", + "value" : 0.96 + }, + { + "name" : "Asphalt", + "value" : 0.95 + } + ] + }, + "wifi" : { + "ssid" : "", + "password" : "", + "maxRetries" : 5, + "retryInterval" : 2000, + "autoConnect" : true + }, + "provisioning" : { + "name" : "PyroVision_PROV", + "pop" : "pyrovision123", + "timeout" : 300 + } +} diff --git a/main/Application/Manager/Network/Provisioning/provisioning.cpp b/main/Application/Manager/Network/Provisioning/provisioning.cpp index c4bd720..6ec5064 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.cpp +++ b/main/Application/Manager/Network/Provisioning/provisioning.cpp @@ -177,23 +177,11 @@ esp_err_t Provisioning_Init(Network_WiFi_STA_Config_t *p_Config) } ESP_LOGD(TAG, "Initializing Provisioning Manager"); -#ifdef CONFIG_NETWORK_PROV_BLE_DEVICE_NAME - strncpy(_Provisioning_State.device_name, CONFIG_NETWORK_PROV_BLE_DEVICE_NAME, + strncpy(_Provisioning_State.device_name, p_Config->ProvConfig.DeviceName, sizeof(_Provisioning_State.device_name) - 1); -#else - strncpy(_Provisioning_State.device_name, "PyroVision_PROV", - sizeof(_Provisioning_State.device_name) - 1); -#endif -#ifdef CONFIG_NETWORK_PROV_POP - strncpy(_Provisioning_State.pop, CONFIG_NETWORK_PROV_POP, sizeof(_Provisioning_State.pop) - 1); -#else - strncpy(_Provisioning_State.pop, "pyrovision123", sizeof(_Provisioning_State.pop) - 1); -#endif -#ifdef CONFIG_NETWORK_PROV_TIMEOUT_SEC - _Provisioning_State.timeout_sec = CONFIG_NETWORK_PROV_TIMEOUT_SEC; -#else - _Provisioning_State.timeout_sec = 300; -#endif + strncpy(_Provisioning_State.pop, p_Config->ProvConfig.PoP, sizeof(_Provisioning_State.pop) - 1); + _Provisioning_State.timeout_sec = p_Config->ProvConfig.Timeout; + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &on_Prov_Event, NULL)); _Provisioning_State.timeout_timer = xTimerCreate("prov_timeout", diff --git a/main/Application/Manager/Network/network_types.h b/main/Application/Manager/Network/network_types.h index 5886d1b..d1e7620 100644 --- a/main/Application/Manager/Network/network_types.h +++ b/main/Application/Manager/Network/network_types.h @@ -188,12 +188,22 @@ typedef struct { char Password[65]; } Network_WiFi_Credentials_t; +/** @brief WiFi provisioning configuration. + */ +typedef struct +{ + char DeviceName[32]; + char PoP[32]; + uint32_t Timeout; +} Network_Provisioning_Config_t; + /** @brief WiFi station configuration. */ typedef struct { Network_WiFi_Credentials_t Credentials; uint8_t MaxRetries; uint16_t RetryInterval; + Network_Provisioning_Config_t ProvConfig; } Network_WiFi_STA_Config_t; /** @brief Server configuration. diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index a2fb7bb..350aa91 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -25,11 +25,14 @@ #include #include #include +#include #include #include #include +#include +#include #include "settingsManager.h" @@ -57,7 +60,7 @@ static SettingsManager_State_t _State = { /** @brief Initialize settings with factory defaults. */ -static void _SettingsManager_InitDefaults(App_Settings_t *p_Settings) +static void SettingsManager_InitDefaults(App_Settings_t *p_Settings) { uint8_t Mac[6]; @@ -94,7 +97,11 @@ static void _SettingsManager_InitDefaults(App_Settings_t *p_Settings) p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].h = 157; p_Settings->Lepton.EnableSceneStatistics = true; - p_Settings->Lepton.Emissivity = 95; + + /* No emissiviy values available */ + p_Settings->Lepton.EmissivityCount = 1; + p_Settings->Lepton.EmissivityPresets[0].Value = 100.0f; + strncpy(p_Settings->Lepton.EmissivityPresets[0].Description, "Unknown", sizeof(p_Settings->Lepton.EmissivityPresets[0].Description)); /* WiFi defaults */ strncpy(p_Settings->WiFi.SSID, "", sizeof(p_Settings->WiFi.SSID)); @@ -119,6 +126,181 @@ static void _SettingsManager_InitDefaults(App_Settings_t *p_Settings) strncpy(p_Settings->System.Timezone, "CET-1CEST,M3.5.0,M10.5.0/3", sizeof(p_Settings->System.Timezone)); } +/** @brief Initialize the settings presets from the NVS by using a config JSON file. + */ +static esp_err_t SettingsManager_LoadDefaultsFromJSON(void) +{ + uint8_t ConfigLoaded = 0; + esp_err_t Error; + cJSON *json = NULL; + cJSON *lepton = NULL; + cJSON *emissivity_array = NULL; + size_t Total = 0; + size_t Used = 0; + size_t BytesRead = 0; + FILE* SettingsFile = NULL; + char *SettingsBuffer = NULL; + long FileSize; + esp_vfs_littlefs_conf_t LittleFS_Config = { + .base_path = "/littlefs", + .partition_label = "storage", + .format_if_mount_failed = true, + .dont_mount = false + }; + + Error = nvs_get_u8(_State.NVS_Handle, "config_loaded", &ConfigLoaded); + if ((Error == ESP_OK) && (ConfigLoaded == true)) { + ESP_LOGI(TAG, "Default config already loaded, skipping"); + //return ESP_OK; + } + + ESP_LOGI(TAG, "Initializing LittleFS"); + + Error = esp_vfs_littlefs_register(&LittleFS_Config); + if (Error != ESP_OK) { + if (Error == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount or format filesystem!"); + } else if (Error == ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to find LittleFS partition!"); + } else { + ESP_LOGE(TAG, "Failed to initialize LittleFS: %d!", Error); + } + + return ESP_FAIL; + } + + Error = esp_littlefs_info(LittleFS_Config.partition_label, &Total, &Used); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to get LittleFS partition information: %d!", Error); + } else { + ESP_LOGI(TAG, "Partition size: total: %zu, used: %zu", Total, Used); + } + + ESP_LOGI(TAG, "Opening settings file..."); + SettingsFile = fopen("/littlefs/default_settings.json", "r"); + if (SettingsFile == NULL) { + ESP_LOGE(TAG, "Failed to open file for reading!"); + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + return ESP_FAIL; + } + + /* Get file size */ + fseek(SettingsFile, 0, SEEK_END); + FileSize = ftell(SettingsFile); + fseek(SettingsFile, 0, SEEK_SET); + + if (FileSize <= 0) { + ESP_LOGE(TAG, "Invalid file size: %ld!", FileSize); + fclose(SettingsFile); + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + return ESP_FAIL; + } + + ESP_LOGI(TAG, "File size: %ld bytes", FileSize); + + /* Allocate buffer for file content */ + SettingsBuffer = (char*)heap_caps_malloc(FileSize + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (SettingsBuffer == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory for file buffer!"); + fclose(SettingsFile); + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + return ESP_ERR_NO_MEM; + } + + /* Read file content */ + BytesRead = fread(SettingsBuffer, 1, FileSize, SettingsFile); + fclose(SettingsFile); + SettingsFile = NULL; + + if (BytesRead != FileSize) { + ESP_LOGE(TAG, "Failed to read file (read %zu of %ld bytes)", BytesRead, FileSize); + heap_caps_free(SettingsBuffer); + + return ESP_FAIL; + } + + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + ESP_LOGI(TAG, "File read successfully, parsing JSON..."); + + /* Parse JSON */ + json = cJSON_Parse(SettingsBuffer); + heap_caps_free(SettingsBuffer); + SettingsBuffer = NULL; + + if (json == NULL) { + const char *error_ptr = cJSON_GetErrorPtr(); + if (error_ptr != NULL) { + ESP_LOGE(TAG, "JSON Parse Error: %s", error_ptr); + } else { + ESP_LOGE(TAG, "JSON Parse Error: Unknown"); + } + + return ESP_FAIL; + } + + ESP_LOGI(TAG, "JSON parsed successfully"); + + /* Extract lepton settings */ + lepton = cJSON_GetObjectItem(json, "lepton"); + if (lepton != NULL) { + emissivity_array = cJSON_GetObjectItem(lepton, "emissivity"); + if (cJSON_IsArray(emissivity_array)) { + _State.Settings.Lepton.EmissivityCount = cJSON_GetArraySize(emissivity_array); + + ESP_LOGI(TAG, "Found %d emissivity presets in JSON", _State.Settings.Lepton.EmissivityCount); + + for (uint32_t i = 0; i < _State.Settings.Lepton.EmissivityCount; i++) { + cJSON *preset = cJSON_GetArrayItem(emissivity_array, i); + cJSON *name = cJSON_GetObjectItem(preset, "name"); + cJSON *value = cJSON_GetObjectItem(preset, "value"); + + if (cJSON_IsString(name) && cJSON_IsNumber(value)) { + _State.Settings.Lepton.EmissivityPresets[i].Value = (float)(value->valuedouble); + + /* Cap the emissivity value between 0 and 100 */ + if (_State.Settings.Lepton.EmissivityPresets[i].Value < 0.0f) { + _State.Settings.Lepton.EmissivityPresets[i].Value = 0.0f; + } else if (_State.Settings.Lepton.EmissivityPresets[i].Value > 100.0f) { + _State.Settings.Lepton.EmissivityPresets[i].Value = 100.0f; + } + + strncpy(_State.Settings.Lepton.EmissivityPresets[i].Description, name->valuestring, + sizeof(_State.Settings.Lepton.EmissivityPresets[i].Description)); + } else { + _State.Settings.Lepton.EmissivityPresets[i].Value = 100.0f; + strncpy(_State.Settings.Lepton.EmissivityPresets[i].Description, "Unknown", + sizeof(_State.Settings.Lepton.EmissivityPresets[i].Description)); + } + + ESP_LOGI(TAG, " Preset %d: %s = %.2f", i, name->valuestring, value->valuedouble); + } + } + } + + cJSON_Delete(json); + + /* Mark config as loaded */ + Error = nvs_set_u8(_State.NVS_Handle, "config_loaded", true); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set config_loaded flag: %d!", Error); + return Error; + } + + Error = nvs_commit(_State.NVS_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit config_loaded flag: %d!", Error); + return Error; + } + + ESP_LOGI(TAG, "Default config loaded and marked as valid"); + + return ESP_OK; +} + esp_err_t SettingsManager_Init(void) { esp_err_t Error; @@ -135,27 +317,40 @@ esp_err_t SettingsManager_Init(void) _State.Mutex = xSemaphoreCreateMutex(); if (_State.Mutex == NULL) { ESP_LOGE(TAG, "Failed to create mutex!"); + return ESP_ERR_NO_MEM; } Error = nvs_open(SETTINGS_NVS_NAMESPACE, NVS_READWRITE, &_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to open NVS handle: %d!", Error); + vSemaphoreDelete(_State.Mutex); + return Error; } _State.isInitialized = true; _State.PendingChanges = false; + /* Load the settings from the NVS */ Error = SettingsManager_Load(&_State.Settings); - if (Error == ESP_ERR_NVS_NOT_FOUND) { + if (Error != ESP_OK) { ESP_LOGI(TAG, "No settings found, using factory defaults"); - _SettingsManager_InitDefaults(&_State.Settings); + + /* Try to load default settings from JSON first (on first boot) */ + if (SettingsManager_LoadDefaultsFromJSON() != ESP_OK) { + ESP_LOGW(TAG, "Failed to load default settings from JSON, using built-in defaults"); + + /* Use built-in defaults */ + SettingsManager_InitDefaults(&_State.Settings); + } + + /* Save the default settings to NVS */ SettingsManager_Save(&_State.Settings); - } else if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to load settings: %d!", Error); - _SettingsManager_InitDefaults(&_State.Settings); + + /* Load the JSON presets into the settings structure */ + SettingsManager_Load(&_State.Settings); } ESP_LOGI(TAG, "Settings Manager initialized (version %lu)", _State.Settings.Version); @@ -212,6 +407,7 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) ESP_LOGW(TAG, "Settings size mismatch (expected %u, got %u), using defaults", sizeof(App_Settings_t), RequiredSize); xSemaphoreGive(_State.Mutex); + return ESP_ERR_INVALID_SIZE; } @@ -219,6 +415,7 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to read settings: %d!", Error); xSemaphoreGive(_State.Mutex); + return Error; } @@ -226,13 +423,21 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) if (p_Settings->Version != SETTINGS_VERSION) { ESP_LOGW(TAG, "Settings version mismatch (expected %d, got %lu), migration needed", SETTINGS_VERSION, p_Settings->Version); + /* TODO: Implement migration logic here */ + + ESP_LOGW(TAG, "Settings migration not implemented, using defaults"); + xSemaphoreGive(_State.Mutex); + + return ESP_FAIL; } xSemaphoreGive(_State.Mutex); ESP_LOGI(TAG, "Settings loaded from NVS"); + // TODO: Remove me + return ESP_FAIL; return ESP_OK; } @@ -406,29 +611,19 @@ esp_err_t SettingsManager_ResetToDefaults(void) return Error; } - _SettingsManager_InitDefaults(&_State.Settings); - _State.PendingChanges = false; + /* Reset config_loaded flag to allow reloading default config */ + Error = nvs_set_u8(_State.NVS_Handle, "config_loaded", false); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set config_loaded flag: %d!", Error); + return Error; + } xSemaphoreGive(_State.Mutex); - SettingsManager_Save(&_State.Settings); - - ESP_LOGI(TAG, "Settings reset to factory defaults"); - - esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_CHANGED, &_State.Settings, - sizeof(App_Settings_t), portMAX_DELAY); - - return ESP_OK; -} - -esp_err_t SettingsManager_GetDefaults(App_Settings_t *p_Settings) -{ - if (p_Settings == NULL) { - return ESP_ERR_INVALID_ARG; - } - - _SettingsManager_InitDefaults(p_Settings); + /* Reboot the ESP to allow reloading the settings config */ + esp_restart(); + /* Never reached */ return ESP_OK; } diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h index 886c705..85638bc 100644 --- a/main/Application/Manager/Settings/settingsManager.h +++ b/main/Application/Manager/Settings/settingsManager.h @@ -37,7 +37,7 @@ */ #define SETTINGS_VERSION 1 -/** @brief Initialize the Settings Manager. +/** @brief Initialize the Settings Manager and load settings from NVS. * @return ESP_OK on success, ESP_ERR_* on failure */ esp_err_t SettingsManager_Init(void); @@ -100,12 +100,6 @@ esp_err_t SettingsManager_SetSystem(const App_Settings_System_t *p_System); */ esp_err_t SettingsManager_ResetToDefaults(void); -/** @brief Get factory default settings. - * @param p_Settings Pointer to settings structure to populate with defaults - * @return ESP_OK on success - */ -esp_err_t SettingsManager_GetDefaults(App_Settings_t *p_Settings); - /** @brief Commit cached settings to NVS storage. * Should be called periodically or on shutdown to persist changes. * @return ESP_OK on success diff --git a/main/Application/Manager/Settings/settings_types.h b/main/Application/Manager/Settings/settings_types.h index 5b4d932..ce854cd 100644 --- a/main/Application/Manager/Settings/settings_types.h +++ b/main/Application/Manager/Settings/settings_types.h @@ -35,7 +35,6 @@ ESP_EVENT_DECLARE_BASE(SETTINGS_EVENTS); enum { SETTINGS_EVENT_LOADED, /**< Settings loaded from NVS. */ SETTINGS_EVENT_SAVED, /**< Settings saved to NVS. */ - SETTINGS_EVENT_CHANGED, /**< Settings changed. Data contains App_Settings_t structure. */ SETTINGS_EVENT_LEPTON_CHANGED, /**< Lepton settings changed. Data contains App_Settings_Lepton_t. */ SETTINGS_EVENT_WIFI_CHANGED, /**< WiFi settings changed. @@ -58,6 +57,13 @@ typedef enum { ROI_TYPE_VIDEO_FOCUS, /**< Video focus ROI. */ } App_Settings_ROI_Type_t; +/** @brief Emissivity setting definition. + */ +typedef struct { + float Value; /**< Emissivity value (0-100). */ + char Description[32]; /**< Description of the emissivity setting. */ +} App_Settings_Emissivity_t; + /** @brief Region of Interest (ROI) rectangle definition (based on Display coordinates). */ typedef struct { @@ -74,7 +80,8 @@ typedef struct { App_Settings_ROI_t ROI[4]; /**< Camera ROIs. */ uint8_t Emissivity; /**< Emissivity (0-100). */ bool EnableSceneStatistics; /**< Enable scene statistics calculation. */ - uint8_t Reserved[100]; /**< Reserved for future use. */ + App_Settings_Emissivity_t EmissivityPresets[128]; /**< Array of emissivity presets. */ + size_t EmissivityCount; /**< Number of emissivity presets. */ } __attribute__((packed)) App_Settings_Lepton_t; /** @brief WiFi settings. @@ -83,9 +90,19 @@ typedef struct { char SSID[33]; /**< WiFi SSID. */ char Password[65]; /**< WiFi password. */ bool AutoConnect; /**< Automatically connect to known WiFi networks. */ - uint8_t Reserved[100]; /**< Reserved for future use. */ + uint8_t MaxRetries; /**< Maximum number of connection retries. */ + uint16_t RetryInterval; /**< Interval between connection retries in milliseconds. */ } __attribute__((packed)) App_Settings_WiFi_t; +/** @brief Provisioning settings. + */ +typedef struct { + char DeviceName[32]; /**< Device name for provisioning. */ + char PoP[32]; /**< Proof of Possession for provisioning. */ + uint32_t Timeout; /**< Provisioning timeout in seconds. */ + uint8_t Reserved[100]; /**< Reserved for future use. */ +} __attribute__((packed)) App_Settings_Provisioning_t; + /** @brief Display settings. */ typedef struct { @@ -110,6 +127,7 @@ typedef struct { uint32_t Version; /**< Settings version for migration. */ App_Settings_Lepton_t Lepton; /**< Lepton camera settings. */ App_Settings_WiFi_t WiFi; /**< WiFi settings. */ + App_Settings_Provisioning_t ProvConfig; /**< Provisioning settings. */ App_Settings_Display_t Display; /**< Display settings. */ App_Settings_System_t System; /**< System settings. */ } __attribute__((packed)) App_Settings_t; diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp index f509b88..000281d 100644 --- a/main/Application/Tasks/Lepton/leptonTask.cpp +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -154,6 +154,7 @@ static void Task_Lepton(void *p_Parameters) esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_READY, &DeviceInfo, sizeof(App_Lepton_Device_t), portMAX_DELAY); + /* Lepton_FluxLinearParams_t FluxParams; Lepton_GetFluxLinearParameters(&_LeptonTask_State.Lepton, &FluxParams); ESP_LOGI(TAG, "Flux Linear Parameters - Scene Emissivity: %u, TBkgK: %u, TauWindow: %u, TWindowK: %u, TauAtm: %u, TAtmK: %u, ReflWindow: %u, TReflK: %u", @@ -171,7 +172,7 @@ static void Task_Lepton(void *p_Parameters) if (Lepton_SetEmissivity(&_LeptonTask_State.Lepton, (Lepton_Emissivity_t)App_Context->Settings.Lepton.Emissivity) != LEPTON_ERR_OK) { ESP_LOGE(TAG, "Failed to set emissivity!"); } - +*/ if (Lepton_StartCapture(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrameQueue) != LEPTON_ERR_OK) { ESP_LOGE(TAG, "Can not start image capturing!"); esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index cdbabfe..2e485a1 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -336,11 +336,22 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) return Error; } - /* Copy WiFi credentials from settings to network config */ + /* Copy the required WiFi settings from settings to network config */ strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID, p_AppContext->Settings.WiFi.SSID, sizeof(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) - 1); strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.Password, p_AppContext->Settings.WiFi.Password, sizeof(_NetworkTask_State.AppContext->STA_Config.Credentials.Password) - 1); + _NetworkTask_State.AppContext->STA_Config.MaxRetries = p_AppContext->Settings.WiFi.MaxRetries; + _NetworkTask_State.AppContext->STA_Config.RetryInterval = p_AppContext->Settings.WiFi.RetryInterval; + + /* Copy the required Provisioning settings from settings to network config */ + strncpy(_NetworkTask_State.AppContext->STA_Config.ProvConfig.DeviceName, + p_AppContext->Settings.ProvConfig.DeviceName, + sizeof(_NetworkTask_State.AppContext->STA_Config.ProvConfig.DeviceName) - 1); + strncpy(_NetworkTask_State.AppContext->STA_Config.ProvConfig.PoP, + p_AppContext->Settings.ProvConfig.PoP, + sizeof(_NetworkTask_State.AppContext->STA_Config.ProvConfig.PoP) - 1); + _NetworkTask_State.AppContext->STA_Config.ProvConfig.Timeout = p_AppContext->Settings.ProvConfig.Timeout; Error = NetworkManager_Init(&_NetworkTask_State.AppContext->STA_Config); if (Error != ESP_OK) { diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 070d80a..9b3552b 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -10,4 +10,4 @@ target_compile_definitions(${COMPONENT_LIB} PUBLIC PYROVISION_VERSION_MAJOR=1 PYROVISION_VERSION_MINOR=0 PYROVISION_VERSION_BUILD=0 -) \ No newline at end of file +) diff --git a/main/main.cpp b/main/main.cpp index e388ee5..33546e5 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -62,6 +62,11 @@ extern "C" void app_main(void) ESP_ERROR_CHECK(SettingsManager_Init()); + while(1) + { + vTaskDelay(pdMS_TO_TICKS(100)); + } + ESP_LOGI(TAG, "Loading settings..."); ESP_ERROR_CHECK(SettingsManager_Get(&_App_Context.Settings)); diff --git a/partitions.csv b/partitions.csv index ffa972d..7dcdaba 100644 --- a/partitions.csv +++ b/partitions.csv @@ -1,8 +1,8 @@ # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xD000, 0x2000, -phy_init, data, phy, 0xF000, 0x1000, +nvs_keys, data, nvs_keys, 0xD000, 0x1000, +otadata, data, ota, 0xE000, 0x2000, app0, app, ota_0, 0x10000, 0x2F0000, app1, app, ota_1, 0x300000, 0x2F0000, -settings, data, nvs, 0x5F0000, 0x10000, -nvs_keys, data, nvs_keys, 0x600000, 0x1000, \ No newline at end of file +storage, data, spiffs, 0x5F0000, 0x160000, +settings, data, nvs, 0x750000, 0x10000, \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 3e1a419..033e746 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,7 +8,7 @@ framework = espidf platform_packages = -extra_scripts = +extra_scripts = pre:scripts/clean.py scripts/format.py @@ -25,18 +25,19 @@ board_build.extra_flags = -DBOARD_HAS_PSRAM board_upload.flash_size = 8MB board_upload.maximum_size = 8388608 board_build.partitions = partitions.csv -board_build.embed_txtfiles = LICENSE +board_build.filesystem = littlefs +board_build.embed_txtfiles = + LICENSE debug_tool = esp-builtin debug_port = /dev/ttyUSB0 upload_speed = 921600 -upload_port = ${sysenv.PIO_UPLOAD_PORT, COM22} +upload_port = ${sysenv.PIO_UPLOAD_PORT, /dev/ttyUSB0} monitor_speed = 115200 monitor_filters = esp32_exception_decoder -monitor_port = ${sysenv.PIO_UPLOAD_PORT, COM22} - +monitor_port = ${sysenv.PIO_UPLOAD_PORT, /dev/ttyUSB0} [env:debug] build_type = debug build_flags = @@ -59,4 +60,4 @@ lib_deps = ${env.lib_deps} extra_scripts = - ${env.extra_scripts} \ No newline at end of file + ${env.extra_scripts} diff --git a/sdkconfig.debug b/sdkconfig.debug index e6d7fc4..e6c33d3 100644 --- a/sdkconfig.debug +++ b/sdkconfig.debug @@ -2747,23 +2747,6 @@ CONFIG_LEPTON_MISC_ERROR_BASE=0xB000 # end of Misc # end of ESP32-Lepton -# -# ADC Battery Estimation -# -CONFIG_OCV_SOC_MODEL_1=y -# CONFIG_OCV_SOC_MODEL_2 is not set -CONFIG_ADC_FILTER_WINDOW_SIZE=10 -CONFIG_BATTERY_CAPACITY_LPF_COEFFICIENT=2 -CONFIG_BATTERY_STATE_SOFTWARE_ESTIMATION=y - -# -# Software Estimation Configuration -# -CONFIG_SOFTWARE_ESTIMATION_SAMPLE_COUNT=10 -CONFIG_SOFTWARE_ESTIMATION_SAMPLE_INTERVAL=20000 -# end of Software Estimation Configuration -# end of ADC Battery Estimation - # # CMake Utilities # From dbde8c89f5366f6cb7e95bd20aedc2f71cdf1603 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Wed, 14 Jan 2026 09:33:50 +0100 Subject: [PATCH 04/26] Feature: Rework Settings logic - Add documentation with AsciiDocs - Change Settings logic to allow loading default settings from JSON - All settings are handled via the Settings Manager and not with local copies of the settings Signed-off-by: Daniel Kampert --- .github/copilot-instructions.md | 537 ++++++++ .github/workflows/documentation.yml | 233 ++++ .github/workflows/firmware.yml | 10 +- data/default_settings.json | 45 + docs/DeviceManager.adoc | 855 ++++++++++++ docs/NetworkManager.adoc | 1213 +++++++++++++++++ docs/SettingsManager.adoc | 799 +++++++++++ docs/TimeManager.adoc | 998 ++++++++++++++ .../Manager/Devices/devicesManager.h | 2 - .../Network/Provisioning/provisioning.cpp | 20 +- .../Network/Provisioning/provisioning.h | 6 +- .../Manager/Network/Server/http_server.cpp | 8 +- .../Manager/Network/Server/http_server.h | 2 +- .../{image_encoder.cpp => imageEncoder.cpp} | 26 +- .../{image_encoder.h => imageEncoder.h} | 18 +- .../Manager/Network/Server/server.h | 11 +- .../Network/Server/websocket_handler.cpp | 6 +- .../Network/Server/websocket_handler.h | 2 +- .../Manager/Network/VISA/CMakeLists.txt | 5 - .../visaCommands.cpp} | 35 +- .../visaCommands.h} | 25 +- .../Manager/Network/VISA/README.md | 554 -------- .../VISA/{visa_server.cpp => visaServer.cpp} | 45 +- .../VISA/{visa_server.h => visaServer.h} | 33 +- .../Manager/Network/networkManager.cpp | 2 +- .../Manager/Network/networkManager.h | 2 +- .../{network_types.h => networkTypes.h} | 3 +- main/Application/Manager/SD/sdManager.cpp | 78 +- main/Application/Manager/SD/sdManager.h | 13 +- .../Private/settingsDefaultLoader.cpp | 159 +++ .../Settings/Private/settingsJSONLoader.cpp | 405 ++++++ .../Manager/Settings/Private/settingsLoader.h | 104 ++ .../Manager/Settings/settingsManager.cpp | 461 ++----- .../Manager/Settings/settingsManager.h | 133 +- .../{settings_types.h => settingsTypes.h} | 37 +- .../Application/Tasks/GUI/Private/guiHelper.h | 2 +- main/Application/Tasks/GUI/guiTask.cpp | 44 +- main/Application/Tasks/Lepton/leptonTask.cpp | 27 +- .../Application/Tasks/Network/networkTask.cpp | 71 +- main/Application/Tasks/Network/networkTask.h | 2 +- main/Application/application.h | 7 +- main/Application/bitmap.h | 122 -- main/main.cpp | 26 +- 43 files changed, 5805 insertions(+), 1381 deletions(-) create mode 100644 .github/copilot-instructions.md create mode 100644 .github/workflows/documentation.yml create mode 100644 docs/DeviceManager.adoc create mode 100644 docs/NetworkManager.adoc create mode 100644 docs/SettingsManager.adoc create mode 100644 docs/TimeManager.adoc rename main/Application/Manager/Network/Server/{image_encoder.cpp => imageEncoder.cpp} (89%) rename main/Application/Manager/Network/Server/{image_encoder.h => imageEncoder.h} (78%) delete mode 100644 main/Application/Manager/Network/VISA/CMakeLists.txt rename main/Application/Manager/Network/VISA/{visa_commands.cpp => Private/visaCommands.cpp} (94%) rename main/Application/Manager/Network/VISA/{visa_commands.h => Private/visaCommands.h} (79%) delete mode 100644 main/Application/Manager/Network/VISA/README.md rename main/Application/Manager/Network/VISA/{visa_server.cpp => visaServer.cpp} (91%) rename main/Application/Manager/Network/VISA/{visa_server.h => visaServer.h} (73%) rename main/Application/Manager/Network/{network_types.h => networkTypes.h} (98%) create mode 100644 main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp create mode 100644 main/Application/Manager/Settings/Private/settingsJSONLoader.cpp create mode 100644 main/Application/Manager/Settings/Private/settingsLoader.h rename main/Application/Manager/Settings/{settings_types.h => settingsTypes.h} (79%) delete mode 100644 main/Application/bitmap.h diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..abae2e5 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,537 @@ +# GitHub Copilot Instructions for PyroVision Firmware + +## Project Overview + +PyroVision is an ESP32-S3 based thermal imaging camera firmware using the ESP-IDF framework. The project manages a Lepton thermal camera with WiFi connectivity, web interface, VISA server, and comprehensive settings management. + +**Key Technologies:** +- Platform: ESP32-S3 (ESP-IDF framework) +- Build System: PlatformIO +- RTOS: FreeRTOS +- GUI: LVGL +- Storage: NVS, LittleFS, SD Card +- Networking: WiFi (STA/AP), HTTP Server, WebSockets, VISA/SCPI + +--- + +## Code Style and Formatting + +### General Formatting Rules + +The project uses **Artistic Style (AStyle)** with a K&R-based configuration (`scripts/astyle.cfg`): + +- **Style**: K&R (Kernighan & Ritchie) +- **Indentation**: 4 spaces (no tabs) +- **Line Length**: Maximum 120 characters +- **Braces**: K&R style (opening brace on same line for functions, control structures) +- **Operators**: Space padding around operators: `a = bar((b - c) * a, d--);` +- **Headers**: Space between header and bracket: `if (condition) {` +- **Pointers/References**: Stick to name: `char *pThing`, `char &thing` +- **Conditionals**: Always use braces, even for single-line blocks +- **Switch**: Indent case statements + +**Example:** +```cpp +esp_err_t MyFunction(uint8_t *p_Buffer, size_t Size) +{ + if (p_Buffer == NULL) { + return ESP_ERR_INVALID_ARG; + } + + for (size_t i = 0; i < Size; i++) { + p_Buffer[i] = ProcessByte(p_Buffer[i]); + } + + return ESP_OK; +} +``` + +### Naming Conventions + +#### Functions +- **Public API**: `ModuleName_FunctionName()` using PascalCase + - Examples: `SettingsManager_Init()`, `NetworkManager_Connect()`, `TimeManager_SetTimezone()` +- **Private/Static**: `snake_case` with descriptive names + - Examples: `on_WiFi_Event()`, `run_astyle()` + +#### Variables +- **Local variables**: `PascalCase` for important variables, `lowercase` for simple counters + - Examples: `RetryCount`, `EventGroup`, `Error`, `i`, `x` +- **Pointers**: Prefix with `p` (e.g., `p_Settings`, `p_Buffer`, `p_Data`) +- **Global/Static module state**: Prefix with underscore: `_State`, `_Network_Manager_State`, `_App_Context` + +#### Constants and Macros +- **All UPPERCASE** with underscores: `WIFI_CONNECTED_BIT`, `NVS_NAMESPACE`, `SETTINGS_VERSION` +- Module-specific macros should include module name: `SETTINGS_NVS_NAMESPACE`, `VISA_MAX_CLIENTS` + +#### Types +- **Structs/Enums**: `ModuleName_Description_t` with `_t` suffix + - Examples: `App_Settings_t`, `Network_State_t`, `App_Settings_WiFi_t` +- **Enums**: Use descriptive prefix for values + - Example: `SETTINGS_EVENT_LOADED`, `NETWORK_EVENT_WIFI_CONNECTED` + +#### File Names +- Header files: `moduleName.h` +- Implementation files: `moduleName.cpp` +- Types/definitions: `moduleTypes.h` +- Private implementations: `Private/internalModule.cpp` + +### Code Organization + +#### Directory Structure +``` +main/ +├── main.cpp # Application entry point +├── Application/ +│ ├── application.h # Application-wide types and events +│ ├── Manager/ # All manager modules +│ │ ├── managers.h # Manager includes +│ │ ├── Settings/ # Settings management +│ │ ├── Network/ # Network management +│ │ ├── Devices/ # Device drivers +│ │ ├── Time/ # Time management +│ │ └── SD/ # SD card management +│ └── Tasks/ # FreeRTOS tasks +│ ├── tasks.h # Task declarations +│ ├── GUI/ # GUI task +│ ├── Lepton/ # Camera task +│ └── Network/ # Network task +``` + +#### Private Implementations +Use `Private/` subdirectories for internal module implementations that should not be exposed: +``` +Manager/Settings/ +├── settingsManager.h # Public API +├── settingsManager.cpp # Implementation +├── settingsTypes.h # Public types +└── Private/ + ├── settingsLoader.h # Internal interface + ├── settingsJSONLoader.cpp + └── settingsDefaultLoader.cpp +``` + +--- + +## License and Copyright + +### File Headers + +**Every source file** (`.cpp`, `.h`, `.py`) must include the following header: + +```cpp +/* + * filename.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Brief description of the file's purpose. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ +``` + +For Python files: +```python +""" +filename.py + +Copyright (C) Daniel Kampert, 2026 +Website: www.kampis-elektroecke.de +File info: Brief description of the file's purpose. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" +``` + +**License**: GNU General Public License v3.0 +**Copyright Holder**: Daniel Kampert +**Contact**: DanielKampert@kampis-elektroecke.de +**Website**: www.kampis-elektroecke.de + +--- + +## Documentation Standards + +### Code Comments + +#### Doxygen-Style Documentation +Use Doxygen comments for all public API functions: + +```cpp +/** @brief Brief description of the function. + * @param p_Param Description of parameter + * @param Size Description of size parameter + * @return ESP_OK on success, ESP_ERR_* on failure + */ +esp_err_t MyFunction(uint8_t *p_Param, size_t Size); +``` + +#### Inline Comments +- Use `//` for single-line comments +- Use `/* */` for block comments +- Add explanatory comments for complex logic +- Comment "why", not "what" (the code shows what) + +**Example:** +```cpp +/* Reset config_loaded flag to allow reloading default config */ +Error = nvs_set_u8(_State.NVS_Handle, "config_loaded", false); +``` + +### Structure Documentation + +Document struct members inline: + +```cpp +typedef struct { + uint16_t Port; /**< HTTP server port. */ + uint16_t WSPingIntervalSec; /**< WebSocket ping interval in seconds. */ + uint8_t MaxClients; /**< Maximum number of simultaneous clients. */ +} App_Settings_HTTP_Server_t; +``` + +### Enum Documentation + +```cpp +/** @brief Settings event identifiers. + */ +enum { + SETTINGS_EVENT_LOADED, /**< Settings loaded from NVS. */ + SETTINGS_EVENT_SAVED, /**< Settings saved to NVS. */ + SETTINGS_EVENT_WIFI_CHANGED,/**< WiFi settings changed. + Data contains App_Settings_WiFi_t. */ +}; +``` + +### External Documentation + +For complex modules, create documentation in `docs/` directory: +- Use **AsciiDoc** (`.adoc`) for technical documentation +- Use **Markdown** (`.md`) for README-style documentation +- Include architecture diagrams, API references, usage examples, and troubleshooting + +--- + +## ESP-IDF Specific Conventions + +### Error Handling + +- **Always check return values** from ESP-IDF functions +- Use `ESP_ERROR_CHECK()` for critical initialization that should abort on failure +- Use manual error handling for recoverable errors: + +```cpp +esp_err_t Error = nvs_open(NAMESPACE, NVS_READWRITE, &Handle); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to open NVS: %d", Error); + return Error; +} +``` + +### Logging + +Use ESP-IDF logging macros with appropriate levels: +- `ESP_LOGE(TAG, ...)` - Errors +- `ESP_LOGW(TAG, ...)` - Warnings +- `ESP_LOGI(TAG, ...)` - Information +- `ESP_LOGD(TAG, ...)` - Debug + +Define TAG at the top of each file: +```cpp +static const char *TAG = "module_name"; +``` + +### Event System + +- Use ESP Event system for module communication +- Define event bases: `ESP_EVENT_DEFINE_BASE(MODULE_EVENTS);` +- Declare in headers: `ESP_EVENT_DECLARE_BASE(MODULE_EVENTS);` +- Use descriptive event IDs in enums +- Always include documentation about event data payload + +### FreeRTOS + +- Task names should be descriptive: `"DevicesTask"`, `"NetworkTask"` +- Use appropriate priorities (defined in task headers) +- Always check if queue/semaphore creation succeeded +- Use `portMAX_DELAY` for blocking operations unless timeout is critical +- Prefer queues for inter-task communication + +--- + +## Module Design Patterns + +### Manager Pattern + +Managers are stateful modules that provide a cohesive API for a subsystem: + +```cpp +// Public API pattern +esp_err_t ModuleName_Init(void); +esp_err_t ModuleName_Deinit(void); +esp_err_t ModuleName_GetConfig(Module_Config_t *p_Config); +esp_err_t ModuleName_UpdateConfig(Module_Config_t *p_Config); +esp_err_t ModuleName_Save(void); + +// Internal state (static in .cpp) +static Module_State_t _State; +``` + +### Thread-Safe Access Pattern + +For shared resources: + +```cpp +typedef struct { + SemaphoreHandle_t Mutex; + // ... data fields +} Module_State_t; + +esp_err_t Module_GetData(Data_t *p_Data) +{ + if (p_Data == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(p_Data, &_State.Data, sizeof(Data_t)); + xSemaphoreGive(_State.Mutex); + + return ESP_OK; +} +``` + +### Event-Driven Updates + +When updating module state: +1. Validate parameters +2. Acquire mutex +3. Update state +4. Release mutex +5. Post event to notify listeners + +```cpp +esp_err_t Module_Update(Config_t *p_Config) +{ + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(&_State.Config, p_Config, sizeof(Config_t)); + xSemaphoreGive(_State.Mutex); + + esp_event_post(MODULE_EVENTS, MODULE_EVENT_CONFIG_CHANGED, + p_Config, sizeof(Config_t), portMAX_DELAY); + + return ESP_OK; +} +``` + +--- + +## Settings Management + +### Settings Structure + +- Settings are organized into categories (WiFi, Display, System, etc.) +- Each category has a dedicated struct type: `App_Settings_CategoryName_t` +- Use `__attribute__((packed))` for settings structures stored in NVS +- Include reserved fields for future expansion + +### Settings API Pattern + +Each settings category follows this pattern: + +```cpp +esp_err_t SettingsManager_GetCategory(App_Settings_Category_t* p_Settings); +esp_err_t SettingsManager_UpdateCategory(App_Settings_Category_t* p_Settings); +``` + +**Important**: `Update` functions modify RAM only. Call `SettingsManager_Save()` to persist changes! + +### Factory Defaults + +Two-tier default system: +1. **JSON Config** (`data/default_settings.json`) - Preferred, loaded on first boot +2. **Hardcoded Defaults** - Fallback in code + +--- + +## Network and Communication + +### WiFi Management + +- Support both STA (Station) and AP (Access Point) modes +- Implement retry logic with configurable max attempts +- Use ESP Event system for connection state changes +- Store credentials securely in NVS + +### HTTP/WebSocket Server + +- Maximum clients defined by `WS_MAX_CLIENTS` +- Implement proper client tracking and cleanup +- Use WebSocket for real-time data streaming +- Regular ping intervals to detect disconnections + +### VISA/SCPI Server + +- Standard port: 5025 +- Implement SCPI command parsing +- Return standard SCPI error codes +- Support concurrent clients (up to `VISA_MAX_CLIENTS`) + +--- + +## Device Integration + +### I2C/SPI Devices + +- Initialize buses in device manager +- Create device handles for each peripheral +- Implement proper error handling and recovery +- Use appropriate clock speeds and configurations + +### Lepton Camera + +- Interface through custom ESP32-Lepton component +- Handle frame buffers efficiently (DMA, PSRAM) +- Implement ROI (Region of Interest) calculations +- Support multiple ROI types (Spotmeter, Scene, AGC, Video Focus) + +--- + +## Build and Tooling + +### PlatformIO Configuration + +- Default environment: `debug` +- Board: `esp32-s3-devkitc-1` +- Flash size: 8MB +- PSRAM: OPI mode +- Filesystem: LittleFS + +### Pre/Post Build Scripts + +- `scripts/clean.py` - Clean build artifacts (pre-build) +- `scripts/format.py` - Format code with AStyle (post-build) + +### Formatting + +Run formatting manually: +```bash +astyle --options=scripts/astyle.cfg "main/**/*.cpp" "main/**/*.h" +``` + +--- + +## Testing and Debugging + +### Debugging + +- Use `ESP_LOGD` for debug output (disabled in release builds) +- Enable debug build type for verbose logging: `build_type = debug` +- Use ESP-IDF monitor with exception decoder: `monitor_filters = esp32_exception_decoder` + +### Error Reporting + +- Log errors with context: function name, error code, relevant parameters +- Include error strings when available +- Use descriptive error messages + +--- + +## Best Practices + +### Memory Management + +- Check malloc/calloc/queue/semaphore creation success +- Free resources in deinit functions +- Use PSRAM for large buffers (frame buffers, JSON parsing) +- Be mindful of stack sizes for tasks + +### Initialization Order + +1. Event loop +2. NVS Flash +3. Settings Manager (loads from NVS) +4. Device Manager (I2C, SPI, peripherals) +5. Time Manager (requires RTC from Device Manager) +6. Network Manager +7. Tasks (GUI, Lepton, Network, etc.) + +### Configuration + +- All configurable parameters should go through Settings Manager +- Avoid hardcoded values that users might want to change +- Provide sensible defaults +- Document valid ranges and constraints + +### Maintainability + +- Keep functions focused and small +- Extract complex logic into separate functions +- Use descriptive variable names +- Document assumptions and constraints +- Write self-documenting code where possible + +--- + +## Common Pitfalls to Avoid + +❌ **Don't:** +- Mix tabs and spaces +- Exceed 120 character line length +- Forget error checking on ESP-IDF calls +- Access shared state without mutex protection +- Forget to call `SettingsManager_Save()` after updates +- Use blocking operations in ISRs +- Ignore compiler warnings + +✅ **Do:** +- Use consistent naming conventions +- Document all public APIs +- Include license headers in all files +- Test error paths +- Use appropriate log levels +- Clean up resources on failure +- Follow the established module patterns + +--- + +## Additional Resources + +- **ESP-IDF Documentation**: https://docs.espressif.com/projects/esp-idf/ +- **FreeRTOS Documentation**: https://www.freertos.org/ +- **LVGL Documentation**: https://docs.lvgl.io/ +- **Project Repository**: (Add if applicable) + +--- + +**Last Updated**: January 14, 2026 +**Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml new file mode 100644 index 0000000..fe2be94 --- /dev/null +++ b/.github/workflows/documentation.yml @@ -0,0 +1,233 @@ +name: Documentation + +on: + push: + branches: + - main + - master + paths: + - docs/** + - .github/workflows/documentation.yml + pull_request: + paths: + - docs/** + - .github/workflows/documentation.yml + workflow_dispatch: + +permissions: + contents: write + pages: write + +jobs: + + asciidoctor: + runs-on: ubuntu-latest + name: Documentation (AsciiDoc) + + steps: + + - name: 🧰 Repository Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install AsciiDoctor + run: | + sudo apt-get update + sudo apt-get install -y asciidoctor ruby-asciidoctor-pdf + + - name: Build AsciiDoc Documentation + run: | + cd docs + mkdir -p public/pdf + + # Find all .adoc files and process them + echo "Processing AsciiDoc files..." + for adoc_file in *.adoc; do + if [ -f "$adoc_file" ]; then + base_name="${adoc_file%.adoc}" + echo " - Building $base_name..." + + # Generate HTML + asciidoctor "$adoc_file" -o "public/${base_name}.html" + + # Generate PDF + asciidoctor-pdf "$adoc_file" -o "public/pdf/${base_name}.pdf" + fi + done + + # Copy any markdown files as supplementary documentation + if ls *.md 1> /dev/null 2>&1; then + cp *.md public/ + fi + + # Create index page listing all documentation + cat > public/index.html << EOF + + + + + + PyroVision Firmware Documentation + + + +

📚 PyroVision Firmware Documentation

+

Complete documentation for the PyroVision ESP32-S3 thermal imaging camera firmware.

+ +
+ + + + + EOF + + - name: Upload Artifact - Documentation + uses: actions/upload-artifact@v4 + with: + name: PyroVision-Documentation + path: docs/public + + + deploy: + if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || contains(github.ref, 'refs/tags/')) + needs: + - asciidoctor + runs-on: ubuntu-latest + name: Deploy to Releases and Pages + + steps: + + - name: Repository Checkout + uses: actions/checkout@v4 + + - name: Download Artifacts + uses: actions/download-artifact@v4 + + - name: Organize public subdir and create a tarball + run: | + mv PyroVision-Documentation public + mv public/pdf ./ + tar zvcf PyroVision-Docs-nightly.tar.gz -C public . + # Rename all PDFs with nightly suffix + cd pdf + for pdf_file in *.pdf; do + if [ -f "$pdf_file" ]; then + base_name="${pdf_file%.pdf}" + mv "$pdf_file" "${base_name}-nightly.pdf" + fi + done + + # Tagged: create a pre-release or a release (semver) + # Untagged: update the assets of pre-release nightly + - name: Deploy to GitHub-Releases + env: + GITHUB_TOKEN: ${{ github.token }} + run: | + # Create nightly release if it doesnt exist + gh release view nightly 2>/dev/null || gh release create nightly --title "Nightly Build" --notes "Automatically generated documentation" --prerelease + # Upload tarball and all PDFs + gh release upload nightly PyroVision-Docs-nightly.tar.gz pdf/*.pdf --clobber + + - name: Deploy to GitHub-Pages + run: | + cd public + git init + # use authenticated remote (GITHUB_TOKEN is available as a secret) + git remote add origin "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" + touch .nojekyll + git add . + git config --local user.email "push@gha" + git config --local user.name "GHA" + git commit -am "update documentation ${{ github.sha }}" + git push -u origin +HEAD:gh-pages --force diff --git a/.github/workflows/firmware.yml b/.github/workflows/firmware.yml index 52f7f77..5c6e530 100644 --- a/.github/workflows/firmware.yml +++ b/.github/workflows/firmware.yml @@ -61,7 +61,6 @@ jobs: pip install --upgrade platformio - name: Format source code - working-directory: firmware run: | pio run -t format @@ -79,7 +78,6 @@ jobs: echo "VERSION=${BASE_VERSION}" >> ${GITHUB_ENV} - name: Update version numbers - working-directory: firmware shell: bash run: | echo "Using version: ${{ env.VERSION }}" @@ -89,19 +87,17 @@ jobs: sed -i "s/^## \[Unreleased\]/## [${{ env.VERSION }}] - $(date +'%Y-%m-%d')/" CHANGELOG.md - name: Build PlatformIO Project - working-directory: firmware run: | pio run - name: Prepare upload - working-directory: firmware run: | mkdir -p debug - + - name: Upload Firmware uses: actions/upload-artifact@v4.3.3 with: name: debug path: | - firmware/debug - if-no-files-found: ignore \ No newline at end of file + debug + if-no-files-found: ignore diff --git a/data/default_settings.json b/data/default_settings.json index 34e5493..51de673 100644 --- a/data/default_settings.json +++ b/data/default_settings.json @@ -17,6 +17,36 @@ "name" : "Asphalt", "value" : 0.95 } + ], + "roi" : [ + { + "name" : "spotmeter", + "x" : 60, + "y" : 60, + "width" : 40, + "height" : 40 + }, + { + "name" : "scene", + "x" : 0, + "y" : 0, + "width" : 160, + "height" : 120 + }, + { + "name" : "agc", + "x" : 0, + "y" : 0, + "width" : 160, + "height" : 120 + }, + { + "name" : "video-focus", + "x" : 1, + "y" : 1, + "width" : 157, + "height" : 117 + } ] }, "wifi" : { @@ -30,5 +60,20 @@ "name" : "PyroVision_PROV", "pop" : "pyrovision123", "timeout" : 300 + }, + "display" : { + "brightness" : 80, + "timeout" : 60 + }, + "system" : { + "timezone" : "CET-1CEST,M3.5.0,M10.5.0/3" + }, + "http-server" : { + "port" : 80, + "ws-ping-interval" : 30, + "max-clients" : 4 + }, + "visa-server": { + "port" : 5025 } } diff --git a/docs/DeviceManager.adoc b/docs/DeviceManager.adoc new file mode 100644 index 0000000..fcb3e31 --- /dev/null +++ b/docs/DeviceManager.adoc @@ -0,0 +1,855 @@ += PyroVision Device Manager Documentation +Daniel Kampert +v1.0, 2026-01-14 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The Device Manager is the central hardware abstraction component for the PyroVision firmware. It initializes and manages all peripheral hardware interfaces including I2C, SPI, ADC, RTC (Real-Time Clock), and port expander. The Device Manager provides a unified API for accessing hardware resources throughout the application. + +=== Key Features + +* *Bus Management*: Centralized I2C and SPI bus initialization +* *Hardware Abstraction*: Unified interface for all peripherals +* *Battery Monitoring*: ADC-based battery voltage and percentage measurement +* *RTC Integration*: Real-time clock access for Time Manager +* *Port Expander*: GPIO expansion via I2C for additional pins +* *Power Management*: Controlled battery voltage measurement +* *Resource Sharing*: Safe sharing of I2C/SPI buses across components + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Manager/Devices/ +├── devicesManager.h # Public API +├── devicesManager.cpp # Implementation +├── devices.h # Device definitions +├── I2C/ # I2C master driver +│ ├── i2c.h +│ └── i2c.cpp +├── SPI/ # SPI master driver +│ ├── spi.h +│ └── spi.cpp +├── ADC/ # ADC driver for battery +│ ├── adc.h +│ └── adc.cpp +├── RTC/ # RTC driver (DS3231/DS1307) +│ ├── rtc.h +│ └── rtc.cpp +└── PortExpander/ # I2C port expander + ├── portexpander.h + └── portexpander.cpp +---- + +=== Hardware Buses + +==== I2C Bus + +* *Port*: Configured via `CONFIG_DEVICES_I2C_HOST` +* *SDA Pin*: Configured via `CONFIG_DEVICES_I2C_SDA` +* *SCL Pin*: Configured via `CONFIG_DEVICES_I2C_SCL` +* *Clock Source*: Default (typically APB) +* *Pull-ups*: External (internal pull-ups disabled) +* *Glitch Filter*: 7 cycles + +*Connected Devices*: + +* RTC (DS3231 or DS1307) +* Port Expander (PCF8574/PCF8575 or similar) +* Other I2C peripherals + +==== SPI Bus (SPI3) + +* *Host*: SPI3_HOST +* *MOSI Pin*: `CONFIG_SPI_MOSI` +* *MISO Pin*: `CONFIG_SPI_MISO` +* *SCLK Pin*: `CONFIG_SPI_SCLK` +* *Max Transfer Size*: `CONFIG_SPI_TRANSFER_SIZE` +* *DMA*: Auto-selected channel + +*Connected Devices*: + +* ILI9341 LCD Display +* XPT2046 Touch Controller +* SD Card (optional) + +==== ADC + +* *Purpose*: Battery voltage measurement +* *Channel*: Configured for battery input +* *Resolution*: 12-bit (configurable) +* *Attenuation*: Configured for voltage range + +--- + +== Internal State + +=== State Structure + +[source,cpp] +---- +typedef struct { + bool initialized; // Manager initialization status + i2c_master_dev_handle_t RTC_Handle; // RTC device handle + i2c_master_bus_handle_t I2C_Bus_Handle; // I2C bus handle +} Devices_Manager_State_t; +---- + +The state is maintained privately within the module and accessed only through the public API. + +--- + +== API Reference + +=== Initialization and Lifecycle + +==== `DevicesManager_Init()` + +[source,cpp] +---- +esp_err_t DevicesManager_Init(void); +---- + +*Description*: Initializes all peripheral hardware interfaces. + +*Initialization Sequence*: + +1. Initialize I2C master bus +2. Initialize SPI3 master bus +3. Initialize ADC for battery measurement +4. Initialize port expander via I2C +5. Wait 2 seconds for camera power stabilization +6. Initialize RTC via I2C +7. Disable battery voltage measurement (default off) + +*Return Value*: + +* `ESP_OK` on success +* `ESP_FAIL` if any peripheral initialization fails + +*Important Notes*: + +* Must be called before any other device operations +* Automatically waits for Lepton camera stabilization (~2 seconds) +* Battery measurement is disabled by default to save power +* All buses are configured from menuconfig settings + +*Example*: + +[source,cpp] +---- +void app_main(void) +{ + ESP_LOGI(TAG, "Initializing Device Manager..."); + + if (DevicesManager_Init() != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize devices!"); + return; + } + + ESP_LOGI(TAG, "All devices initialized successfully"); + + // Continue with application initialization... +} +---- + +==== `DevicesManager_Deinit()` + +[source,cpp] +---- +esp_err_t DevicesManager_Deinit(void); +---- + +*Description*: Deinitializes all peripheral hardware and releases resources. + +*Deinitialization Sequence*: + +1. Disable battery voltage measurement +2. Deinitialize ADC +3. Deinitialize RTC +4. Deinitialize port expander +5. Deinitialize I2C bus +6. Deinitialize SPI3 bus + +*Return Value*: + +* `ESP_OK` on success +* Error code from bus deinitialization (if any) + +*Example*: + +[source,cpp] +---- +void shutdown_system(void) +{ + ESP_LOGI(TAG, "Shutting down device manager..."); + DevicesManager_Deinit(); + + // Continue with full system shutdown... +} +---- + +--- + +=== Bus Access + +==== `DevicesManager_GetI2CBusHandle()` + +[source,cpp] +---- +i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void); +---- + +*Description*: Gets the I2C bus handle for adding additional I2C devices. + +*Return Value*: + +* I2C bus handle on success +* `NULL` if Device Manager not initialized + +*Use Case*: When additional I2C devices need to be added to the bus dynamically. + +*Example*: + +[source,cpp] +---- +// Add a custom I2C sensor +i2c_master_bus_handle_t i2c_bus = DevicesManager_GetI2CBusHandle(); +if (i2c_bus != NULL) { + i2c_device_config_t sensor_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = 0x48, // Custom sensor address + .scl_speed_hz = 100000, + }; + + i2c_master_dev_handle_t sensor_handle; + ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus, &sensor_cfg, &sensor_handle)); + + // Use sensor_handle for I2C transactions... +} +---- + +--- + +=== Hardware Access + +==== `DevicesManager_GetBatteryVoltage()` + +[source,cpp] +---- +esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage); +---- + +*Description*: Measures battery voltage and calculates remaining percentage. + +*Process*: + +1. Enables battery voltage measurement circuit (via port expander) +2. Reads ADC value from battery measurement pin +3. Calculates actual voltage using voltage divider compensation +4. Calculates percentage based on LiPo voltage curve +5. Disables battery voltage measurement circuit + +*Parameters*: + +* `p_Voltage`: Pointer to store voltage in millivolts (mV) +* `p_Percentage`: Pointer to store percentage (0-100%) + +*Voltage Calculation*: + +[source] +---- +Actual Voltage = ADC Reading × (R1 + R2) / R2 + +R1 = 10kΩ (upper resistor) +R2 = 3.3kΩ (lower resistor) +---- + +*Percentage Calculation*: + +[source] +---- +Battery Range: 3.3V (0%) to 4.2V (100%) + +Percentage = (Voltage - 3300) × 100 / (4200 - 3300) + = (Voltage - 3300) × 100 / 900 + +Clamped to [0, 100] range +---- + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if Device Manager not initialized +* `ESP_ERR_INVALID_ARG` if parameters are NULL +* Error code from ADC read operation + +*Example*: + +[source,cpp] +---- +int voltage_mv, percentage; + +if (DevicesManager_GetBatteryVoltage(&voltage_mv, &percentage) == ESP_OK) { + ESP_LOGI(TAG, "Battery: %d mV (%d%%)", voltage_mv, percentage); + + if (percentage < 10) { + ESP_LOGW(TAG, "Low battery warning!"); + display_low_battery_icon(); + } +} else { + ESP_LOGE(TAG, "Failed to read battery voltage"); +} +---- + +==== `DevicesManager_GetRTCHandle()` + +[source,cpp] +---- +esp_err_t DevicesManager_GetRTCHandle(i2c_master_dev_handle_t *p_Handle); +---- + +*Description*: Gets the RTC device handle for Time Manager integration. + +*Parameters*: + +* `p_Handle`: Pointer to store the RTC device handle + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if Device Manager not initialized +* `ESP_ERR_INVALID_ARG` if `p_Handle` is NULL + +*Use Case*: Time Manager requires the RTC handle for time synchronization and backup. + +*Example*: + +[source,cpp] +---- +i2c_master_dev_handle_t rtc_handle; + +if (DevicesManager_GetRTCHandle(&rtc_handle) == ESP_OK) { + // Pass RTC handle to Time Manager + TimeManager_Init(&rtc_handle); +} else { + ESP_LOGW(TAG, "RTC not available, Time Manager will use SNTP only"); + TimeManager_Init(NULL); +} +---- + +--- + +== Usage + +=== Basic Initialization Workflow + +[source,cpp] +---- +#include "devicesManager.h" +#include "timeManager.h" + +void app_main(void) +{ + // Initialize NVS (required for WiFi) + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + // Initialize event loop + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // Initialize Settings Manager + ESP_ERROR_CHECK(SettingsManager_Init()); + + // Initialize Device Manager (MUST be before Time Manager) + ESP_ERROR_CHECK(DevicesManager_Init()); + + // Get RTC handle for Time Manager + i2c_master_dev_handle_t rtc_handle; + ESP_ERROR_CHECK(DevicesManager_GetRTCHandle(&rtc_handle)); + + // Initialize Time Manager with RTC support + ESP_ERROR_CHECK(TimeManager_Init(&rtc_handle)); + + // Continue with other initializations... +} +---- + +--- + +=== Battery Monitoring Task + +[source,cpp] +---- +void battery_monitor_task(void *pvParameters) +{ + int voltage_mv, percentage; + int last_percentage = -1; + + while (1) { + if (DevicesManager_GetBatteryVoltage(&voltage_mv, &percentage) == ESP_OK) { + // Only update display if percentage changed + if (percentage != last_percentage) { + ESP_LOGI(TAG, "Battery: %d mV (%d%%)", voltage_mv, percentage); + update_battery_indicator(percentage); + last_percentage = percentage; + } + + // Check critical battery level + if (percentage <= 5) { + ESP_LOGE(TAG, "Critical battery level! Shutting down..."); + initiate_safe_shutdown(); + break; + } + + // Low battery warning + if (percentage <= 15) { + ESP_LOGW(TAG, "Low battery warning"); + enable_power_saving_mode(); + } + } + + // Check battery every 30 seconds + vTaskDelay(pdMS_TO_TICKS(30000)); + } + + vTaskDelete(NULL); +} + +// Create task +xTaskCreate(battery_monitor_task, "BatteryMonitor", 2048, NULL, 5, NULL); +---- + +--- + +=== Adding Custom I2C Devices + +[source,cpp] +---- +typedef struct { + i2c_master_dev_handle_t handle; + uint8_t address; +} CustomSensor_t; + +esp_err_t CustomSensor_Init(CustomSensor_t *p_Sensor, uint8_t address) +{ + i2c_master_bus_handle_t i2c_bus = DevicesManager_GetI2CBusHandle(); + if (i2c_bus == NULL) { + ESP_LOGE(TAG, "I2C bus not available!"); + return ESP_ERR_INVALID_STATE; + } + + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = address, + .scl_speed_hz = 100000, + }; + + esp_err_t ret = i2c_master_bus_add_device(i2c_bus, &dev_cfg, &p_Sensor->handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to add I2C device: %d", ret); + return ret; + } + + p_Sensor->address = address; + ESP_LOGI(TAG, "Custom sensor initialized at address 0x%02X", address); + + return ESP_OK; +} + +esp_err_t CustomSensor_Read(CustomSensor_t *p_Sensor, uint8_t reg, uint8_t *p_Data, size_t len) +{ + return i2c_master_transmit_receive(p_Sensor->handle, + ®, 1, + p_Data, len, + 1000); +} +---- + +--- + +=== Battery Voltage Calculation Example + +For understanding the voltage measurement: + +[source,cpp] +---- +/* + * Hardware Setup: + * + * VBAT (4.2V max) + * | + * R1 (10kΩ) + * | + * +---- ADC Input (measures this point) + * | + * R2 (3.3kΩ) + * | + * GND + * + * Voltage at ADC = VBAT × R2 / (R1 + R2) + * = VBAT × 3300 / 13300 + * = VBAT × 0.248 + * + * So for 4.2V battery: ADC sees ~1.04V (safe for ESP32 ADC) + */ + +// Internal calculation in DevicesManager_GetBatteryVoltage(): +int adc_voltage_mv = 1040; // Example: ADC reads 1.04V + +// Compensate for voltage divider +int actual_voltage_mv = adc_voltage_mv * (10000 + 3300) / 3300; +// actual_voltage_mv = 1040 × 13300 / 3300 = 4193 mV ≈ 4.2V + +// Calculate percentage (LiPo: 3.3V = empty, 4.2V = full) +int percentage = (actual_voltage_mv - 3300) * 100 / (4200 - 3300); +// percentage = (4193 - 3300) × 100 / 900 = 99% +---- + +--- + +== Configuration + +=== Menuconfig Settings + +Device Manager uses several menuconfig settings (defined in `Kconfig.projbuild` or component configs): + +==== I2C Configuration + +[source] +---- +CONFIG_DEVICES_I2C_HOST # I2C port number (0 or 1) +CONFIG_DEVICES_I2C_SDA # SDA GPIO pin +CONFIG_DEVICES_I2C_SCL # SCL GPIO pin +---- + +*Example*: +[source] +---- +CONFIG_DEVICES_I2C_HOST=1 +CONFIG_DEVICES_I2C_SDA=21 +CONFIG_DEVICES_I2C_SCL=22 +---- + +==== SPI Configuration + +[source] +---- +CONFIG_SPI_MOSI # MOSI GPIO pin +CONFIG_SPI_MISO # MISO GPIO pin +CONFIG_SPI_SCLK # Clock GPIO pin +CONFIG_SPI_TRANSFER_SIZE # Max transfer size (bytes) +---- + +*Example*: +[source] +---- +CONFIG_SPI_MOSI=23 +CONFIG_SPI_MISO=19 +CONFIG_SPI_SCLK=18 +CONFIG_SPI_TRANSFER_SIZE=32768 +---- + +==== Battery Voltage Divider + +If you use different resistor values, update in `devicesManager.cpp`: + +[source,cpp] +---- +#define BATTERY_R1 10000 // Upper resistor (Ω) +#define BATTERY_R2 3300 // Lower resistor (Ω) +#define BATTERY_MIN_VOLTAGE 3300 // Empty voltage (mV) +#define BATTERY_MAX_VOLTAGE 4200 // Full voltage (mV) +---- + +--- + +== Hardware Dependencies + +=== Required Components + +[cols="2,3,2"] +|=== +|Component |Purpose |Interface + +|ESP32-S3 +|Main controller +|N/A + +|DS3231/DS1307 +|Real-time clock with battery backup +|I2C + +|PCF8574/PCF8575 +|GPIO port expander +|I2C + +|ILI9341 +|LCD display +|SPI + +|XPT2046 +|Touch controller +|SPI + +|Voltage Divider +|Battery voltage measurement (10kΩ + 3.3kΩ) +|ADC + +|Lepton Camera +|Thermal imaging sensor +|SPI (via separate component) +|=== + +=== Pin Assignments + +Typical pin configuration (adjust via menuconfig): + +[cols="2,2,3"] +|=== +|Function |Pin |Notes + +|I2C SDA +|GPIO 21 +|External 4.7kΩ pull-up recommended + +|I2C SCL +|GPIO 22 +|External 4.7kΩ pull-up recommended + +|SPI MOSI +|GPIO 23 +|Shared by LCD, Touch, SD + +|SPI MISO +|GPIO 19 +|Shared by LCD, Touch, SD + +|SPI CLK +|GPIO 18 +|Shared by LCD, Touch, SD + +|Battery ADC +|GPIO 34-39 +|ADC1 channel (varies by design) +|=== + +--- + +== Best Practices + +=== DO's + +* ✓ Initialize Device Manager early (after NVS, before Time Manager) +* ✓ Check return values from all API calls +* ✓ Use `DevicesManager_GetI2CBusHandle()` for additional I2C devices +* ✓ Monitor battery periodically (not continuously to save power) +* ✓ Implement low battery warnings and automatic shutdown +* ✓ Use external pull-ups on I2C bus for reliability + +=== DON'Ts + +* ✗ Don't directly access hardware buses without Device Manager +* ✗ Don't call device APIs before `DevicesManager_Init()` +* ✗ Don't continuously poll battery voltage (wastes power) +* ✗ Don't exceed I2C bus speed for slowest device +* ✗ Don't forget 2-second camera stabilization is automatic + +--- + +== Troubleshooting + +=== I2C Communication Failures + +*Symptom*: Device Manager initialization fails with I2C errors + +*Possible Causes*: + +* Missing external pull-ups (4.7kΩ recommended) +* Wrong GPIO pins configured +* Device address conflict +* Faulty hardware or loose connections + +*Solution*: + +[source,cpp] +---- +// Enable I2C debugging +esp_log_level_set("i2c", ESP_LOG_DEBUG); + +// Check I2C bus with scanner +void i2c_scanner(void) +{ + i2c_master_bus_handle_t bus = DevicesManager_GetI2CBusHandle(); + ESP_LOGI(TAG, "Scanning I2C bus..."); + + for (uint8_t addr = 1; addr < 127; addr++) { + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = addr, + .scl_speed_hz = 100000, + }; + + i2c_master_dev_handle_t temp_handle; + if (i2c_master_bus_add_device(bus, &dev_cfg, &temp_handle) == ESP_OK) { + uint8_t dummy; + if (i2c_master_receive(temp_handle, &dummy, 1, 100) == ESP_OK) { + ESP_LOGI(TAG, "Found device at 0x%02X", addr); + } + i2c_master_bus_rm_device(temp_handle); + } + } +} +---- + +--- + +=== RTC Not Found + +*Symptom*: Warning "Failed to initialize RTC" + +*Possible Causes*: + +* RTC not connected +* Wrong I2C address +* Faulty RTC module +* Insufficient power + +*Solution*: + +* Verify RTC is DS3231 or DS1307 compatible +* Check I2C address (typically 0x68) +* Verify VCC (3.3V or 5V) and GND connections +* Check battery in RTC module + +Time Manager will still work using SNTP only if RTC fails. + +--- + +=== Battery Voltage Reads Zero + +*Symptom*: Battery voltage always returns 0 or very low values + +*Possible Causes*: + +* Port expander not enabling measurement circuit +* Wrong ADC channel configured +* Voltage divider resistors incorrect +* ADC pin not connected + +*Solution*: + +[source,cpp] +---- +// Test ADC directly +int voltage, percentage; +for (int i = 0; i < 10; i++) { + DevicesManager_GetBatteryVoltage(&voltage, &percentage); + ESP_LOGI(TAG, "Test %d: %d mV (%d%%)", i, voltage, percentage); + vTaskDelay(pdMS_TO_TICKS(500)); +} + +// Check if port expander is working +PortExpander_EnableBatteryVoltage(true); +vTaskDelay(pdMS_TO_TICKS(100)); +// Manually read ADC here +PortExpander_EnableBatteryVoltage(false); +---- + +--- + +=== SPI Display Issues + +*Symptom*: Display not working or garbled output + +*Possible Causes*: + +* Wrong SPI pins +* Insufficient DMA buffer size +* CS/DC/RST pins misconfigured (not managed by Device Manager) + +*Solution*: + +* Verify `CONFIG_SPI_TRANSFER_SIZE` is large enough (≥32768) +* Check SPI3_HOST is not used by other peripherals +* Increase `CONFIG_SPI_TRANSFER_SIZE` if needed for large displays + +--- + +== Technical Details + +=== I2C Bus Sharing + +The I2C bus is shared among multiple devices: + +* RTC (typically 0x68) +* Port Expander (typically 0x20-0x27) +* Additional sensors (if added) + +All devices use the same bus handle, and the ESP-IDF I2C master driver handles arbitration and locking automatically. + +=== Power Sequencing + +Device Manager ensures proper power-up sequence: + +1. Initialize I2C/SPI buses (fast, <10ms) +2. Initialize ADC and Port Expander +3. **Wait 2 seconds** for camera power stabilization +4. Initialize RTC (time-critical component last) + +This sequence ensures the Lepton camera has adequate boot time (~1.5 seconds required). + +=== Battery Percentage Accuracy + +The percentage calculation is linear and optimized for LiPo batteries: + +* Uses 3.3V as "empty" (safe cutoff for LiPo) +* Uses 4.2V as "full" (fully charged LiPo) +* Provides reasonable accuracy for most applications +* Does not account for battery aging or temperature + +For improved accuracy, implement a lookup table based on actual discharge curve. + +--- + +== Dependencies + +Device Manager depends on: + +* ESP-IDF I2C Master Driver (`driver/i2c_master.h`) +* ESP-IDF SPI Master Driver (`driver/spi_master.h`) +* ESP-IDF ADC Driver (`driver/adc.h`) +* FreeRTOS (`freertos/FreeRTOS.h`, `freertos/task.h`) + +Device Manager is required by: + +* Time Manager (needs RTC handle) +* GUI Task (needs SPI for display) +* Application tasks (needs battery monitoring) + +--- + +== License + +Copyright (C) Daniel Kampert, 2026 + +This software is licensed under the GNU General Public License v3.0. +Website: www.kampis-elektroecke.de + +--- + +== Contact + +Please report bugs and suggestions to: DanielKampert@kampis-elektroecke.de diff --git a/docs/NetworkManager.adoc b/docs/NetworkManager.adoc new file mode 100644 index 0000000..80d5667 --- /dev/null +++ b/docs/NetworkManager.adoc @@ -0,0 +1,1213 @@ += PyroVision Network Manager Documentation +Daniel Kampert +v1.0, 2026-01-14 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The Network Manager is the central networking component for the PyroVision firmware. It manages WiFi connectivity (both Station and Access Point modes), HTTP/WebSocket servers, VISA/SCPI server, WiFi provisioning, and network events. The Network Manager provides a unified API for all network operations with automatic reconnection, retry logic, and comprehensive state management. + +=== Key Features + +* *WiFi Management*: Station (STA) and Access Point (AP) modes +* *Automatic Reconnection*: Configurable retry logic with intelligent backoff +* *HTTP/WebSocket Server*: Real-time thermal imaging data streaming +* *VISA/SCPI Server*: Standard instrumentation interface (port 5025) +* *WiFi Provisioning*: BLE and SoftAP provisioning support +* *Event-Driven Architecture*: Comprehensive event system for state changes +* *Network Monitoring*: RSSI, IP info, connection statistics +* *Credentials Management*: Secure storage in NVS +* *State Machine*: Well-defined connection states + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Manager/Network/ +├── networkManager.h # Public API +├── networkManager.cpp # Implementation +├── networkTypes.h # Type definitions and events +├── Server/ # HTTP/WebSocket server +│ ├── server.h +│ └── server.cpp +├── VISA/ # VISA/SCPI server +│ ├── visa.h +│ └── visa.cpp +├── SNTP/ # SNTP time sync (used by Time Manager) +│ ├── sntp.h +│ └── sntp.cpp +└── Provisioning/ # WiFi provisioning + ├── provisioning.h + └── provisioning.cpp +---- + +=== Network State Machine + +The Network Manager uses a state machine to track connection status: + +[source] +---- +┌──────────────┐ +│ IDLE │ ← Initial state, WiFi not started +└──────┬───────┘ + │ NetworkManager_StartSTA() + ↓ +┌──────────────┐ +│ CONNECTING │ ← Attempting to connect to AP +└──┬───────────┘ + │ + ├─→ [Success] → CONNECTED + │ + ├─→ [Retry] → CONNECTING (up to MaxRetries) + │ + └─→ [Max retries] → ERROR + +┌──────────────┐ +│ CONNECTED │ ← Connected, has IP address +└──┬───────────┘ + │ + ├─→ [Disconnect] → DISCONNECTED + │ + └─→ [Lost IP] → CONNECTING (auto-retry) + +┌──────────────┐ +│ DISCONNECTED │ ← WiFi disconnected (network lost, etc.) +└──────────────┘ + +┌──────────────┐ +│ AP_STARTED │ ← Access Point mode active +└──────────────┘ + +┌──────────────┐ +│ PROVISIONING │ ← Provisioning mode (BLE or SoftAP) +└──────────────┘ + +┌──────────────┐ +│ ERROR │ ← Max retries exceeded, manual intervention needed +└──────────────┘ +---- + +--- + +== Data Structures + +=== Network State Enum + +[source,cpp] +---- +typedef enum { + NETWORK_STATE_IDLE = 0, // WiFi not started + NETWORK_STATE_CONNECTING, // Attempting connection + NETWORK_STATE_CONNECTED, // Connected with IP + NETWORK_STATE_DISCONNECTED, // Disconnected from AP + NETWORK_STATE_PROVISIONING, // Provisioning mode active + NETWORK_STATE_AP_STARTED, // Access Point started + NETWORK_STATE_ERROR, // Error state (max retries) +} Network_State_t; +---- + +=== WiFi Configuration Structures + +==== WiFi Credentials + +[source,cpp] +---- +typedef struct { + char SSID[33]; // WiFi SSID (max 32 chars + null) + char Password[65]; // WiFi password (max 64 chars + null) +} Network_WiFi_Credentials_t; +---- + +==== Station Mode Configuration + +[source,cpp] +---- +typedef struct { + Network_WiFi_Credentials_t Credentials; // SSID and password + uint8_t MaxRetries; // Max connection attempts + uint16_t RetryInterval; // Delay between retries (ms) +} Network_WiFi_STA_Config_t; +---- + +=== Server Configuration + +[source,cpp] +---- +typedef struct { + uint16_t HTTP_Port; // HTTP server port (default 80) + uint8_t MaxClients; // Max simultaneous clients + uint16_t WSPingIntervalSec; // WebSocket ping interval (seconds) + bool EnableCORS; // Enable CORS headers + const char *API_Key; // Optional API key for authentication +} Server_Config_t; +---- + +=== Event System + +==== Event Base + +[source,cpp] +---- +ESP_EVENT_DECLARE_BASE(NETWORK_EVENTS); +---- + +==== Event Types + +[cols="2,3,2"] +|=== +|Event |Description |Data + +|`NETWORK_EVENT_WIFI_CONNECTED` +|WiFi connected to AP +|None + +|`NETWORK_EVENT_WIFI_DISCONNECTED` +|WiFi disconnected from AP +|`wifi_event_sta_disconnected_t` + +|`NETWORK_EVENT_WIFI_GOT_IP` +|IP address obtained via DHCP +|`Network_IP_Info_t` + +|`NETWORK_EVENT_CREDENTIALS_UPDATED` +|WiFi credentials changed +|`Network_WiFi_Credentials_t` + +|`NETWORK_EVENT_AP_STARTED` +|Access Point started +|None + +|`NETWORK_EVENT_AP_STOPPED` +|Access Point stopped +|None + +|`NETWORK_EVENT_AP_STA_CONNECTED` +|Station connected to our AP +|`Network_Event_STA_Info_t` + +|`NETWORK_EVENT_AP_STA_DISCONNECTED` +|Station disconnected from our AP +|`Network_Event_STA_Info_t` + +|`NETWORK_EVENT_PROV_STARTED` +|Provisioning started +|None + +|`NETWORK_EVENT_PROV_STOPPED` +|Provisioning stopped +|None + +|`NETWORK_EVENT_PROV_CRED_RECV` +|Provisioning credentials received +|None + +|`NETWORK_EVENT_PROV_SUCCESS` +|Provisioning successful +|None + +|`NETWORK_EVENT_PROV_FAILED` +|Provisioning failed +|None + +|`NETWORK_EVENT_SERVER_STARTED` +|HTTP/WebSocket server started +|None + +|`NETWORK_EVENT_SERVER_STOPPED` +|HTTP/WebSocket server stopped +|None +|=== + +==== Event Data Structures + +[source,cpp] +---- +/** @brief IP info event data. */ +typedef struct { + uint32_t IP; // IP address + uint32_t Netmask; // Subnet mask + uint32_t Gateway; // Gateway address +} Network_IP_Info_t; + +/** @brief Station info event data. */ +typedef struct { + uint8_t MAC[6]; // MAC address +} Network_Event_STA_Info_t; +---- + +--- + +== API Reference + +=== Initialization and Lifecycle + +==== `NetworkManager_Init()` + +[source,cpp] +---- +esp_err_t NetworkManager_Init(Network_WiFi_STA_Config_t *p_Config); +---- + +*Description*: Initializes the Network Manager with WiFi configuration. + +*Process*: + +1. Initializes TCP/IP stack (`esp_netif_init()`) +2. Creates FreeRTOS event group for synchronization +3. Creates WiFi station and AP network interfaces +4. Initializes WiFi with default configuration +5. Registers WiFi and IP event handlers +6. Sets WiFi storage mode to RAM + +*Parameters*: + +* `p_Config`: Pointer to WiFi station configuration (credentials, retries, interval) + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if `p_Config` is NULL +* `ESP_ERR_NO_MEM` if event group creation fails +* `ESP_FAIL` if netif or WiFi initialization fails + +*Example*: + +[source,cpp] +---- +Network_WiFi_STA_Config_t wifi_config = { + .Credentials = { + .SSID = "MyWiFi", + .Password = "MyPassword123", + }, + .MaxRetries = 5, + .RetryInterval = 5000, // 5 seconds +}; + +if (NetworkManager_Init(&wifi_config) == ESP_OK) { + ESP_LOGI(TAG, "Network Manager initialized"); +} else { + ESP_LOGE(TAG, "Failed to initialize Network Manager"); +} +---- + +==== `NetworkManager_Deinit()` + +[source,cpp] +---- +void NetworkManager_Deinit(void); +---- + +*Description*: Deinitializes the Network Manager and releases all resources. + +*Process*: + +1. Stops WiFi and SNTP +2. Deinitializes WiFi driver +3. Destroys network interfaces (STA and AP) +4. Deletes event group +5. Resets internal state + +*Example*: + +[source,cpp] +---- +void shutdown_network(void) +{ + ESP_LOGI(TAG, "Shutting down network..."); + NetworkManager_Deinit(); +} +---- + +--- + +=== WiFi Connection Management + +==== `NetworkManager_StartSTA()` + +[source,cpp] +---- +esp_err_t NetworkManager_StartSTA(void); +---- + +*Description*: Starts WiFi in station mode and connects to configured AP. + +*Process*: + +1. Resets retry counter +2. Clears event group bits +3. Configures WiFi with stored credentials +4. Sets authentication mode (WPA2-PSK minimum) +5. Enables Protected Management Frames (PMF) +6. Starts WiFi and initiates connection + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if not initialized + +*Authentication*: + +* Minimum: WPA2-PSK +* PMF capable: Yes +* PMF required: No (for compatibility) + +*Example*: + +[source,cpp] +---- +// Start WiFi connection +if (NetworkManager_StartSTA() == ESP_OK) { + ESP_LOGI(TAG, "WiFi STA started, connecting..."); + + // Wait for connection or failure + while (NetworkManager_GetState() == NETWORK_STATE_CONNECTING) { + vTaskDelay(pdMS_TO_TICKS(100)); + } + + if (NetworkManager_isConnected()) { + ESP_LOGI(TAG, "Connected successfully!"); + } else { + ESP_LOGE(TAG, "Connection failed"); + } +} +---- + +==== `NetworkManager_Stop()` + +[source,cpp] +---- +esp_err_t NetworkManager_Stop(void); +---- + +*Description*: Stops WiFi and SNTP, returns to IDLE state. + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if not initialized + +*Example*: + +[source,cpp] +---- +// Temporarily disable WiFi to save power +NetworkManager_Stop(); +ESP_LOGI(TAG, "WiFi stopped"); + +// Later, restart connection +NetworkManager_StartSTA(); +---- + +==== `NetworkManager_ConnectWiFi()` + +[source,cpp] +---- +esp_err_t NetworkManager_ConnectWiFi(const char *p_SSID, const char *p_Password); +---- + +*Description*: Connects to WiFi with new credentials (updates configuration). + +*Parameters*: + +* `p_SSID`: New SSID (NULL to keep current) +* `p_Password`: New password (NULL to keep current) + +*Process*: + +1. Updates credentials if provided +2. Stops current WiFi connection +3. Restarts with new credentials +4. Waits up to 30 seconds for connection + +*Return Value*: + +* `ESP_OK` if connected successfully +* `ESP_ERR_INVALID_STATE` if not initialized +* `ESP_FAIL` if connection failed +* `ESP_ERR_TIMEOUT` if connection timed out (30 seconds) + +*Example*: + +[source,cpp] +---- +// Connect to new WiFi network +esp_err_t ret = NetworkManager_ConnectWiFi("NewNetwork", "NewPassword123"); + +if (ret == ESP_OK) { + ESP_LOGI(TAG, "Connected to new network!"); +} else if (ret == ESP_ERR_TIMEOUT) { + ESP_LOGW(TAG, "Connection timeout - check credentials and signal strength"); +} else { + ESP_LOGE(TAG, "Connection failed: %d", ret); +} +---- + +==== `NetworkManager_DisconnectWiFi()` + +[source,cpp] +---- +esp_err_t NetworkManager_DisconnectWiFi(void); +---- + +*Description*: Disconnects from current WiFi network. + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if not initialized + +*Example*: + +[source,cpp] +---- +NetworkManager_DisconnectWiFi(); +ESP_LOGI(TAG, "Disconnected from WiFi"); +---- + +--- + +=== Status and Information + +==== `NetworkManager_isConnected()` + +[source,cpp] +---- +bool NetworkManager_isConnected(void); +---- + +*Description*: Checks if WiFi is connected and has IP address. + +*Return Value*: + +* `true` if state is `NETWORK_STATE_CONNECTED` +* `false` otherwise + +*Example*: + +[source,cpp] +---- +if (NetworkManager_isConnected()) { + // Safe to start servers, sync time, etc. + start_http_server(); +} else { + ESP_LOGW(TAG, "Not connected to WiFi"); +} +---- + +==== `NetworkManager_GetState()` + +[source,cpp] +---- +Network_State_t NetworkManager_GetState(void); +---- + +*Description*: Gets the current network connection state. + +*Return Value*: Current `Network_State_t` value + +*Example*: + +[source,cpp] +---- +Network_State_t state = NetworkManager_GetState(); + +switch (state) { + case NETWORK_STATE_IDLE: + ESP_LOGI(TAG, "WiFi not started"); + break; + case NETWORK_STATE_CONNECTING: + ESP_LOGI(TAG, "Connecting..."); + break; + case NETWORK_STATE_CONNECTED: + ESP_LOGI(TAG, "Connected!"); + break; + case NETWORK_STATE_ERROR: + ESP_LOGE(TAG, "Error state - max retries exceeded"); + break; + default: + break; +} +---- + +==== `NetworkManager_GetIP()` + +[source,cpp] +---- +esp_err_t NetworkManager_GetIP(esp_netif_ip_info_t *p_IP); +---- + +*Description*: Gets current IP, netmask, and gateway information. + +*Parameters*: + +* `p_IP`: Pointer to store IP information + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if `p_IP` is NULL + +*Example*: + +[source,cpp] +---- +esp_netif_ip_info_t ip_info; + +if (NetworkManager_GetIP(&ip_info) == ESP_OK) { + ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ip_info.ip)); + ESP_LOGI(TAG, "Netmask: " IPSTR, IP2STR(&ip_info.netmask)); + ESP_LOGI(TAG, "Gateway: " IPSTR, IP2STR(&ip_info.gw)); +} +---- + +==== `NetworkManager_GetRSSI()` + +[source,cpp] +---- +int8_t NetworkManager_GetRSSI(void); +---- + +*Description*: Gets WiFi signal strength (RSSI) in dBm. + +*Return Value*: + +* RSSI in dBm (typically -30 to -90) +* `0` if not connected + +*RSSI Interpretation*: + +* -30 dBm: Excellent signal +* -50 dBm: Very good signal +* -60 dBm: Good signal +* -70 dBm: Fair signal +* -80 dBm: Weak signal +* -90 dBm: Very weak signal + +*Example*: + +[source,cpp] +---- +int8_t rssi = NetworkManager_GetRSSI(); + +if (rssi != 0) { + const char *quality; + if (rssi >= -50) quality = "Excellent"; + else if (rssi >= -60) quality = "Very Good"; + else if (rssi >= -70) quality = "Good"; + else if (rssi >= -80) quality = "Fair"; + else quality = "Weak"; + + ESP_LOGI(TAG, "Signal: %d dBm (%s)", rssi, quality); +} +---- + +==== `NetworkManager_GetMAC()` + +[source,cpp] +---- +esp_err_t NetworkManager_GetMAC(uint8_t *p_MAC); +---- + +*Description*: Gets the MAC address of the WiFi station interface. + +*Parameters*: + +* `p_MAC`: Buffer to store MAC address (6 bytes) + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if `p_MAC` is NULL + +*Example*: + +[source,cpp] +---- +uint8_t mac[6]; + +if (NetworkManager_GetMAC(mac) == ESP_OK) { + ESP_LOGI(TAG, "MAC: %02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} +---- + +--- + +=== Credentials Management + +==== `NetworkManager_SetCredentials()` + +[source,cpp] +---- +esp_err_t NetworkManager_SetCredentials(Network_WiFi_Credentials_t *p_Credentials); +---- + +*Description*: Updates WiFi credentials without reconnecting. + +*Parameters*: + +* `p_Credentials`: Pointer to new credentials + +*Process*: + +1. Updates internal credentials +2. Posts `NETWORK_EVENT_CREDENTIALS_UPDATED` event +3. Does NOT reconnect (call `NetworkManager_ConnectWiFi()` to reconnect) + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if `p_Credentials` is NULL + +*Example*: + +[source,cpp] +---- +Network_WiFi_Credentials_t creds = { + .SSID = "NewNetwork", + .Password = "NewPass123", +}; + +// Update credentials (saved in RAM) +NetworkManager_SetCredentials(&creds); + +// Save to NVS via Settings Manager +App_Settings_WiFi_t wifi_settings; +SettingsManager_GetWiFi(&wifi_settings); +memcpy(&wifi_settings.Credentials, &creds, sizeof(creds)); +SettingsManager_UpdateWiFi(&wifi_settings); +SettingsManager_Save(); + +// Reconnect with new credentials +NetworkManager_ConnectWiFi(NULL, NULL); +---- + +--- + +=== Server Management + +==== `NetworkManager_StartServer()` + +[source,cpp] +---- +esp_err_t NetworkManager_StartServer(Server_Config_t *p_Config); +---- + +*Description*: Starts the HTTP/WebSocket server. + +*Parameters*: + +* `p_Config`: Pointer to server configuration + +*Return Value*: + +* `ESP_OK` on success +* Error code from server initialization + +*Example*: + +[source,cpp] +---- +Server_Config_t server_cfg = { + .HTTP_Port = 80, + .MaxClients = 4, + .WSPingIntervalSec = 30, + .EnableCORS = true, + .API_Key = NULL, // No API key +}; + +if (NetworkManager_isConnected()) { + NetworkManager_StartServer(&server_cfg); + ESP_LOGI(TAG, "HTTP/WebSocket server started on port 80"); +} +---- + +==== `NetworkManager_GetConnectedStations()` + +[source,cpp] +---- +uint8_t NetworkManager_GetConnectedStations(void); +---- + +*Description*: Gets the number of stations connected to our AP (AP mode only). + +*Return Value*: Number of connected stations (0 if not in AP mode) + +*Example*: + +[source,cpp] +---- +uint8_t num_stations = NetworkManager_GetConnectedStations(); +ESP_LOGI(TAG, "Connected stations: %d", num_stations); +---- + +--- + +== Usage + +=== Basic Connection Flow + +[source,cpp] +---- +#include "networkManager.h" + +void init_network(void) +{ + // Load WiFi settings from Settings Manager + App_Settings_WiFi_t wifi_settings; + SettingsManager_GetWiFi(&wifi_settings); + + // Prepare network configuration + Network_WiFi_STA_Config_t network_cfg = { + .Credentials = wifi_settings.Credentials, + .MaxRetries = 5, + .RetryInterval = 5000, + }; + + // Initialize Network Manager + ESP_ERROR_CHECK(NetworkManager_Init(&network_cfg)); + + // Start WiFi connection + ESP_ERROR_CHECK(NetworkManager_StartSTA()); + + ESP_LOGI(TAG, "WiFi connection initiated"); +} +---- + +--- + +=== Event Handling + +[source,cpp] +---- +static void network_event_handler(void* arg, esp_event_base_t base, + int32_t id, void* event_data) +{ + switch (id) { + case NETWORK_EVENT_WIFI_CONNECTED: + ESP_LOGI(TAG, "WiFi connected to AP"); + break; + + case NETWORK_EVENT_WIFI_DISCONNECTED: { + wifi_event_sta_disconnected_t *evt = (wifi_event_sta_disconnected_t*)event_data; + ESP_LOGW(TAG, "WiFi disconnected, reason: %d", evt->reason); + break; + } + + case NETWORK_EVENT_WIFI_GOT_IP: { + Network_IP_Info_t *ip_info = (Network_IP_Info_t*)event_data; + esp_ip4_addr_t ip = { .addr = ip_info->IP }; + ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&ip)); + + // Safe to start servers now + start_application_servers(); + + // Notify Time Manager + TimeManager_OnNetworkConnected(); + break; + } + + case NETWORK_EVENT_SERVER_STARTED: + ESP_LOGI(TAG, "HTTP/WebSocket server started"); + break; + + default: + break; + } +} + +void register_network_events(void) +{ + ESP_ERROR_CHECK(esp_event_handler_register(NETWORK_EVENTS, + ESP_EVENT_ANY_ID, + network_event_handler, + NULL)); +} +---- + +--- + +=== Connection Status Monitoring + +[source,cpp] +---- +void network_monitor_task(void *pvParameters) +{ + while (1) { + if (NetworkManager_isConnected()) { + // Get connection details + int8_t rssi = NetworkManager_GetRSSI(); + esp_netif_ip_info_t ip_info; + NetworkManager_GetIP(&ip_info); + + ESP_LOGI(TAG, "=== Network Status ==="); + ESP_LOGI(TAG, "State: CONNECTED"); + ESP_LOGI(TAG, "IP: " IPSTR, IP2STR(&ip_info.ip)); + ESP_LOGI(TAG, "RSSI: %d dBm", rssi); + + // Check signal quality + if (rssi < -80) { + ESP_LOGW(TAG, "Weak signal detected!"); + } + } else { + Network_State_t state = NetworkManager_GetState(); + ESP_LOGI(TAG, "Network state: %d (not connected)", state); + + if (state == NETWORK_STATE_ERROR) { + ESP_LOGE(TAG, "Network in error state - manual intervention needed"); + } + } + + vTaskDelay(pdMS_TO_TICKS(10000)); // Check every 10 seconds + } +} +---- + +--- + +=== Retry Logic Implementation + +The Network Manager implements intelligent retry logic: + +[source,cpp] +---- +/* + * Retry behavior: + * 1. On disconnect, check if retries remain + * 2. Wait RetryInterval milliseconds + * 3. Attempt reconnection + * 4. Repeat up to MaxRetries times + * 5. If max retries exceeded, enter ERROR state + */ + +// Example: Configure aggressive retries +Network_WiFi_STA_Config_t config = { + .Credentials = { .SSID = "MyNetwork", .Password = "Pass123" }, + .MaxRetries = 10, // Try 10 times + .RetryInterval = 3000, // 3 seconds between attempts +}; + +// Total timeout = 10 × 3s = 30 seconds of retry attempts +---- + +--- + +=== HTTP Server Integration + +[source,cpp] +---- +void start_web_interface(void) +{ + // Wait for network connection + while (!NetworkManager_isConnected()) { + ESP_LOGI(TAG, "Waiting for network connection..."); + vTaskDelay(pdMS_TO_TICKS(1000)); + } + + // Load server settings + App_Settings_HTTP_Server_t http_settings; + SettingsManager_GetHTTPServer(&http_settings); + + // Configure server + Server_Config_t server_cfg = { + .HTTP_Port = http_settings.Port, + .MaxClients = http_settings.MaxClients, + .WSPingIntervalSec = http_settings.WSPingIntervalSec, + .EnableCORS = true, + .API_Key = NULL, + }; + + // Start server + esp_err_t ret = NetworkManager_StartServer(&server_cfg); + if (ret == ESP_OK) { + ESP_LOGI(TAG, "Web interface available at http://" IPSTR, + IP2STR(¤t_ip)); + } else { + ESP_LOGE(TAG, "Failed to start server: %d", ret); + } +} +---- + +--- + +== Configuration + +=== WiFi Configuration + +==== Station Mode Settings + +Configure via Settings Manager or directly: + +[source,cpp] +---- +Network_WiFi_STA_Config_t wifi_config = { + .Credentials = { + .SSID = "YourNetwork", // Max 32 characters + .Password = "YourPassword", // Max 64 characters (WPA2) + }, + .MaxRetries = 5, // 0-255 retries + .RetryInterval = 5000, // Milliseconds between retries +}; +---- + +==== Server Settings + +[source,cpp] +---- +Server_Config_t server_config = { + .HTTP_Port = 80, // HTTP port (80 or 8080 typical) + .MaxClients = 4, // Max simultaneous clients + .WSPingIntervalSec = 30, // WebSocket keepalive (seconds) + .EnableCORS = true, // Allow cross-origin requests + .API_Key = "secret123", // Optional API key (or NULL) +}; +---- + +--- + +== WiFi Disconnect Reasons + +The Network Manager provides detailed disconnect reason logging: + +[cols="1,2,3"] +|=== +|Code |Reason |Description + +|1 +|Unspecified +|Generic disconnect + +|2 +|Auth expired +|Authentication timeout + +|4 +|Assoc expired +|Association timeout + +|6 +|Not authed +|Not authenticated yet + +|8 +|Assoc leave +|Device chose to disconnect + +|15 +|4-way handshake timeout +|WPA handshake failed + +|23 +|Beacon timeout +|Lost connection (AP disappeared) + +|201 +|No AP found +|SSID not found (check spelling, 2.4GHz) + +|202 +|Auth failed +|Wrong password + +|205 +|Connection failed +|Generic connection failure +|=== + +--- + +== Best Practices + +=== DO's + +* ✓ Initialize Network Manager after NVS and before starting tasks +* ✓ Register event handlers before starting WiFi +* ✓ Check `NetworkManager_isConnected()` before starting servers +* ✓ Handle disconnection gracefully with automatic retry +* ✓ Monitor RSSI for signal quality issues +* ✓ Use Settings Manager to persist WiFi credentials +* ✓ Implement timeout logic for critical network operations + +=== DON'Ts + +* ✗ Don't call `NetworkManager_StartSTA()` multiple times without stopping +* ✗ Don't start servers before network is connected +* ✗ Don't ignore disconnect events (handle gracefully) +* ✗ Don't hardcode credentials (use Settings Manager) +* ✗ Don't forget to call `NetworkManager_Deinit()` on shutdown +* ✗ Don't exceed ESP32 WiFi client limits (typically 4-8) + +--- + +== Troubleshooting + +=== Connection Fails Immediately + +*Symptom*: `NETWORK_EVENT_WIFI_DISCONNECTED` with reason 201 ("No AP found") + +*Possible Causes*: + +* SSID typo or incorrect case +* AP is on 5GHz band (ESP32 only supports 2.4GHz) +* AP is out of range +* AP is hidden (ESP32 can connect to hidden SSIDs but requires exact match) + +*Solution*: + +[source,cpp] +---- +ESP_LOGI(TAG, "Scanning for networks..."); +wifi_scan_config_t scan_config = { .ssid = NULL }; +ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, true)); + +uint16_t ap_count = 0; +esp_wifi_scan_get_ap_num(&ap_count); +wifi_ap_record_t *ap_list = malloc(sizeof(wifi_ap_record_t) * ap_count); +esp_wifi_scan_get_ap_records(&ap_count, ap_list); + +for (int i = 0; i < ap_count; i++) { + ESP_LOGI(TAG, "Found: %s (RSSI: %d, Channel: %d)", + ap_list[i].ssid, ap_list[i].rssi, ap_list[i].primary); +} +free(ap_list); +---- + +--- + +=== Authentication Failures + +*Symptom*: Disconnect reason 202 ("Auth failed") + +*Cause*: Incorrect password or incompatible encryption + +*Solution*: + +* Verify password is correct (case-sensitive) +* Ensure AP uses WPA2-PSK (WPA3 may require additional configuration) +* Check if AP requires additional settings (e.g., MAC filtering) + +--- + +=== Connection Drops Frequently + +*Symptom*: Repeated connect/disconnect cycles + +*Possible Causes*: + +* Weak signal (RSSI < -80 dBm) +* Interference from other 2.4GHz devices +* AP overload (too many clients) +* Power saving mode issues + +*Solution*: + +[source,cpp] +---- +// Disable WiFi power saving for stability +esp_wifi_set_ps(WIFI_PS_NONE); + +// Monitor RSSI +int8_t rssi = NetworkManager_GetRSSI(); +if (rssi < -75) { + ESP_LOGW(TAG, "Signal too weak: %d dBm", rssi); + // Consider reconnecting to different AP or warning user +} +---- + +--- + +=== Server Not Accessible + +*Symptom*: Cannot access HTTP server from browser + +*Possible Causes*: + +* Network not connected +* Firewall on client device +* Wrong IP address +* Server not started + +*Solution*: + +[source,cpp] +---- +if (!NetworkManager_isConnected()) { + ESP_LOGE(TAG, "Not connected!"); + return; +} + +esp_netif_ip_info_t ip_info; +NetworkManager_GetIP(&ip_info); +ESP_LOGI(TAG, "Server should be at: http://" IPSTR, IP2STR(&ip_info.ip)); + +// Test with curl or browser: +// curl http:/// +---- + +--- + +== Technical Details + +=== WiFi Mode + +Network Manager supports: + +* **Station (STA)**: Client mode, connects to existing AP +* **Access Point (AP)**: Creates own network (for provisioning) +* **APSTA**: Both modes simultaneously (not commonly used) + +Current implementation focuses on STA mode with AP support for provisioning. + +=== Security + +* **Minimum Authentication**: WPA2-PSK +* **PMF (Protected Management Frames)**: Capable (not required for compatibility) +* **Credentials Storage**: RAM only (use Settings Manager + NVS for persistence) + +=== Performance + +* **WiFi Standard**: 802.11 b/g/n (2.4GHz only) +* **Max Throughput**: ~20 Mbps (practical) +* **Concurrent Clients**: Configurable (typically 4-8) +* **WebSocket Frame Rate**: ~10-30 fps (depends on resolution and network) + +--- + +== Dependencies + +Network Manager depends on: + +* ESP-IDF WiFi Driver (`esp_wifi.h`) +* ESP-IDF TCP/IP Stack (`esp_netif.h`) +* ESP-IDF Event Loop (`esp_event.h`) +* FreeRTOS (`freertos/FreeRTOS.h`, `freertos/event_groups.h`) +* NVS (for credential storage via Settings Manager) + +Network Manager provides services to: + +* Time Manager (SNTP synchronization) +* HTTP/WebSocket Server (thermal image streaming) +* VISA Server (instrument control) +* Application tasks (network connectivity) + +--- + +== License + +Copyright (C) Daniel Kampert, 2026 + +This software is licensed under the GNU General Public License v3.0. +Website: www.kampis-elektroecke.de + +--- + +== Contact + +Please report bugs and suggestions to: DanielKampert@kampis-elektroecke.de diff --git a/docs/SettingsManager.adoc b/docs/SettingsManager.adoc new file mode 100644 index 0000000..f5f4f19 --- /dev/null +++ b/docs/SettingsManager.adoc @@ -0,0 +1,799 @@ += PyroVision Settings Manager Documentation +Daniel Kampert +v1.0, 2026-01-14 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The Settings Manager is a central component for persistent management of application settings in the PyroVision firmware. It provides thread-safe access to various settings categories and uses ESP32 NVS (Non-Volatile Storage) for permanent storage. + +=== Key Features + +* *Thread-safe Operations*: All accesses are protected by a mutex +* *Persistent Storage*: Settings are stored in NVS flash memory +* *Event-based Architecture*: Notification of changes via ESP Event System +* *Categorized Settings*: Modular structure for different subsystems +* *Factory Defaults*: Support for default settings from JSON or hardcoded +* *Versioning*: Support for future migrations + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Manager/Settings/ +├── settingsManager.h # Public API +├── settingsManager.cpp # Implementation +├── settingsTypes.h # Data types and Events +└── Private/ + ├── settingsLoader.h # Internal loader interface + ├── settingsJSONLoader.cpp # JSON Factory Defaults Loader + └── settingsDefaultLoader.cpp # Hardcoded Defaults +---- + +=== Internal State Management + +The manager maintains its state in the `SettingsManager_State_t` structure: + +[source,cpp] +---- +typedef struct { + bool isInitialized; // Initialization status + bool PendingChanges; // Unsaved changes + nvs_handle_t NVS_Handle; // NVS Handle + App_Settings_t Settings; // Current settings in RAM + SemaphoreHandle_t Mutex; // Thread safety +} SettingsManager_State_t; +---- + +=== NVS Storage Layout + +* *Namespace*: `"pyrovision"` +* *Blob Key*: `"settings"` - Contains the complete `App_Settings_t` structure +* *Version Key*: Reserved for future migrations +* *Config Loaded Flag*: `"config_loaded"` - Indicates whether JSON defaults have been loaded + +== Data Structures + +=== Settings Categories + +The settings are divided into the following categories: + +==== 1. Lepton Camera Settings (`App_Settings_Lepton_t`) + +[source,cpp] +---- +typedef struct { + App_Settings_ROI_t ROI[4]; // Camera ROIs + App_Settings_Emissivity_t EmissivityPresets[128]; // Emissivity presets + size_t EmissivityCount; // Number of presets +} App_Settings_Lepton_t; +---- + +* *ROIs*: Up to 4 Regions of Interest (Spotmeter, Scene, AGC, Video Focus) +* *Emissivity Presets*: Predefined material emissivities (e.g. Concrete: 0.92, Skin: 0.98) + +==== 2. WiFi Settings (`App_Settings_WiFi_t`) + +[source,cpp] +---- +typedef struct { + char SSID[33]; // WiFi SSID (max 32 characters + \0) + char Password[65]; // WiFi password (max 64 characters + \0) + bool AutoConnect; // Automatic connection + uint8_t MaxRetries; // Maximum connection attempts + uint16_t RetryInterval; // Wait time between attempts (ms) +} App_Settings_WiFi_t; +---- + +==== 3. Provisioning Settings (`App_Settings_Provisioning_t`) + +[source,cpp] +---- +typedef struct { + char DeviceName[32]; // Device name for provisioning + char PoP[32]; // Proof of Possession + uint32_t Timeout; // Provisioning timeout (seconds) +} App_Settings_Provisioning_t; +---- + +==== 4. Display Settings (`App_Settings_Display_t`) + +[source,cpp] +---- +typedef struct { + uint8_t Brightness; // Brightness (0-100%) + uint16_t ScreenTimeout; // Screen timeout (seconds, 0=off) +} App_Settings_Display_t; +---- + +==== 5. HTTP Server Settings (`App_Settings_HTTP_Server_t`) + +[source,cpp] +---- +typedef struct { + uint16_t Port; // HTTP Server Port + uint16_t WSPingIntervalSec; // WebSocket ping interval (seconds) + uint8_t MaxClients; // Max. simultaneous clients +} App_Settings_HTTP_Server_t; +---- + +==== 6. VISA Server Settings (`App_Settings_VISA_Server_t`) + +[source,cpp] +---- +typedef struct { + uint16_t Port; // VISA Server Port (default: 5025) +} App_Settings_VISA_Server_t; +---- + +==== 7. System Settings (`App_Settings_System_t`) + +[source,cpp] +---- +typedef struct { + char DeviceName[32]; // Device name + bool SDCard_AutoMount; // Automatic SD card mounting + bool Bluetooth_Enabled; // Bluetooth enabled + char Timezone[32]; // Timezone string (POSIX format) + uint8_t Reserved[100]; // Reserved for future extensions +} App_Settings_System_t; +---- + +=== Event System + +==== Event Base + +[source,cpp] +---- +ESP_EVENT_DECLARE_BASE(SETTINGS_EVENTS); +---- + +==== Event IDs + +[cols="2,3,2"] +|=== +|Event |Description |Data + +|`SETTINGS_EVENT_LOADED` +|Settings loaded from NVS +|`App_Settings_t` + +|`SETTINGS_EVENT_SAVED` +|Settings saved to NVS +|NULL + +|`SETTINGS_EVENT_LEPTON_CHANGED` +|Lepton settings changed +|`App_Settings_Lepton_t` + +|`SETTINGS_EVENT_WIFI_CHANGED` +|WiFi settings changed +|`App_Settings_WiFi_t` + +|`SETTINGS_EVENT_PROVISIONING_CHANGED` +|Provisioning settings changed +|`App_Settings_Provisioning_t` + +|`SETTINGS_EVENT_DISPLAY_CHANGED` +|Display settings changed +|`App_Settings_Display_t` + +|`SETTINGS_EVENT_HTTP_SERVER_CHANGED` +|HTTP server settings changed +|`App_Settings_HTTP_Server_t` + +|`SETTINGS_EVENT_VISA_SERVER_CHANGED` +|VISA server settings changed +|`App_Settings_VISA_Server_t` + +|`SETTINGS_EVENT_SYSTEM_CHANGED` +|System settings changed +|`App_Settings_System_t` + +|`SETTINGS_EVENT_REQUEST_GET` +|Request to retrieve current settings +|NULL + +|`SETTINGS_EVENT_REQUEST_SAVE` +|Request to save settings +|NULL + +|`SETTINGS_EVENT_REQUEST_RESET` +|Request to reset to factory defaults +|NULL +|=== + +== API Reference + +=== Initialization and Lifecycle + +==== `SettingsManager_Init()` + +[source,cpp] +---- +esp_err_t SettingsManager_Init(void); +---- + +*Description*: Initializes the Settings Manager and loads all settings from NVS. + +*Process*: + +1. Creates a mutex for thread safety +2. Opens the NVS namespace `"pyrovision"` +3. Attempts to load settings from NVS +4. If no settings exist: + * Loads JSON factory defaults from `data/default_settings.json` + * If JSON not available: Uses hardcoded defaults + * Saves the defaults to NVS +5. Posts `SETTINGS_EVENT_LOADED` event + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_NO_MEM` if mutex could not be created +* Other `ESP_ERR_*` on NVS errors + +*Example*: + +[source,cpp] +---- +if (SettingsManager_Init() == ESP_OK) { + ESP_LOGI(TAG, "Settings Manager successfully initialized"); +} +---- + +==== `SettingsManager_Deinit()` + +[source,cpp] +---- +esp_err_t SettingsManager_Deinit(void); +---- + +*Description*: Deinitializes the Settings Manager and releases resources. + +*Process*: + +1. Closes the NVS handle +2. Deletes the mutex +3. Resets initialization status + +*Return Value*: `ESP_OK` + +=== Loading and Saving Settings + +==== `SettingsManager_Load()` + +[source,cpp] +---- +esp_err_t SettingsManager_Load(App_Settings_t *p_Settings); +---- + +*Description*: Loads all settings from NVS into RAM and the provided structure. *Warning*: Overwrites unsaved RAM changes! + +*Parameters*: + +* `p_Settings`: Pointer to settings structure to be populated + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if manager is not initialized +* `ESP_ERR_INVALID_ARG` if `p_Settings` is NULL +* `ESP_ERR_NVS_NOT_FOUND` if no settings exist in NVS +* `ESP_ERR_INVALID_SIZE` on size mismatch (e.g., after firmware update) + +==== `SettingsManager_Save()` + +[source,cpp] +---- +esp_err_t SettingsManager_Save(void); +---- + +*Description*: Saves all RAM settings persistently to NVS. + +*Process*: + +1. Writes complete `App_Settings_t` structure as blob to NVS +2. Commits the changes +3. Posts `SETTINGS_EVENT_SAVED` event + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if manager is not initialized +* Other `ESP_ERR_*` on NVS errors + +*Important*: Changes via `Update*()` functions are only made in RAM. `Save()` must be called explicitly! + +=== Get/Update Functions + +For each settings category, there exists a pair of `Get` and `Update` functions: + +==== Pattern: Get Function + +[source,cpp] +---- +esp_err_t SettingsManager_Get(App_Settings__t* p_Settings); +---- + +*Description*: Reads the current settings from RAM (thread-safe). + +*Parameters*: Pointer to the structure to be populated + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` on NULL pointer + +*Example*: + +[source,cpp] +---- +App_Settings_WiFi_t wifi_settings; +if (SettingsManager_GetWiFi(&wifi_settings) == ESP_OK) { + ESP_LOGI(TAG, "WiFi SSID: %s", wifi_settings.SSID); +} +---- + +==== Pattern: Update Function + +[source,cpp] +---- +esp_err_t SettingsManager_Update(App_Settings__t* p_Settings); +---- + +*Description*: Updates settings in RAM (not persistent!) and posts a change event. + +*Parameters*: Pointer to the new settings structure + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if manager is not initialized +* `ESP_ERR_INVALID_ARG` on NULL pointer + +*Process*: + +1. Copies new values to RAM structure (thread-safe) +2. Posts corresponding `SETTINGS_EVENT_*_CHANGED` event with the new data + +*Example*: + +[source,cpp] +---- +App_Settings_Display_t display_settings; +SettingsManager_GetDisplay(&display_settings); + +display_settings.Brightness = 90; +display_settings.ScreenTimeout = 120; + +SettingsManager_UpdateDisplay(&display_settings); +SettingsManager_Save(); // Make persistent! +---- + +==== Available Get/Update Pairs + +* `SettingsManager_GetLepton()` / `SettingsManager_UpdateLepton()` +* `SettingsManager_GetWiFi()` / `SettingsManager_UpdateWiFi()` +* `SettingsManager_GetProvisioning()` / `SettingsManager_UpdateProvisioning()` +* `SettingsManager_GetDisplay()` / `SettingsManager_UpdateDisplay()` +* `SettingsManager_GetHTTPServer()` / `SettingsManager_UpdateHTTPServer()` +* `SettingsManager_GetVISAServer()` / `SettingsManager_UpdateVISAServer()` +* `SettingsManager_GetSystem()` / `SettingsManager_UpdateSystem()` + +=== Factory Reset + +==== `SettingsManager_ResetToDefaults()` + +[source,cpp] +---- +esp_err_t SettingsManager_ResetToDefaults(void); +---- + +*Description*: Resets all settings to factory defaults and restarts the device. + +*Process*: + +1. Deletes the `"settings"` key from NVS +2. Resets `"config_loaded"` flag (allows reloading JSON defaults) +3. Executes `esp_restart()` + +*Return Value*: + +* `ESP_OK` on success (never reached due to restart) +* `ESP_ERR_INVALID_STATE` if manager is not initialized +* Other `ESP_ERR_*` on NVS errors + +*Warning*: This function does not return as a restart is performed! + +== Usage + +=== Basic Workflow + +==== 1. Initialization at Startup + +[source,cpp] +---- +#include "settingsManager.h" + +void app_main(void) +{ + // Initialize Settings Manager + ESP_ERROR_CHECK(SettingsManager_Init()); + + // Further initializations... +} +---- + +==== 2. Reading Settings + +[source,cpp] +---- +App_Settings_System_t system_settings; + +if (SettingsManager_GetSystem(&system_settings) == ESP_OK) { + ESP_LOGI(TAG, "Device Name: %s", system_settings.DeviceName); + ESP_LOGI(TAG, "Timezone: %s", system_settings.Timezone); +} +---- + +==== 3. Changing Settings + +[source,cpp] +---- +App_Settings_Display_t display; + +// Read current settings +SettingsManager_GetDisplay(&display); + +// Change values +display.Brightness = 75; +display.ScreenTimeout = 300; + +// Update in RAM (triggers event) +SettingsManager_UpdateDisplay(&display); + +// IMPORTANT: Save persistently! +SettingsManager_Save(); +---- + +=== Event Handling + +==== Registering Event Handlers + +[source,cpp] +---- +#include +#include "settingsTypes.h" + +static void settings_event_handler(void* handler_args, esp_event_base_t base, + int32_t id, void* event_data) +{ + switch (id) { + case SETTINGS_EVENT_LOADED: + ESP_LOGI(TAG, "Settings have been loaded"); + break; + + case SETTINGS_EVENT_SAVED: + ESP_LOGI(TAG, "Settings have been saved"); + break; + + case SETTINGS_EVENT_WIFI_CHANGED: + App_Settings_WiFi_t* wifi = (App_Settings_WiFi_t*)event_data; + ESP_LOGI(TAG, "WiFi settings changed: SSID=%s", wifi->SSID); + // Reconfigure WiFi... + break; + + case SETTINGS_EVENT_DISPLAY_CHANGED: + App_Settings_Display_t* display = (App_Settings_Display_t*)event_data; + ESP_LOGI(TAG, "Display Brightness: %d%%", display->Brightness); + // Adjust display brightness... + break; + + // More events... + } +} + +void init_event_handlers(void) +{ + esp_event_handler_register(SETTINGS_EVENTS, + ESP_EVENT_ANY_ID, + settings_event_handler, + NULL); +} +---- + +=== Advanced Patterns + +==== Atomic Settings Update with Rollback + +[source,cpp] +---- +esp_err_t update_wifi_with_rollback(const char* ssid, const char* password) +{ + App_Settings_WiFi_t old_settings; + App_Settings_WiFi_t new_settings; + + // Backup old settings + SettingsManager_GetWiFi(&old_settings); + + // Prepare new settings + new_settings = old_settings; + strncpy(new_settings.SSID, ssid, sizeof(new_settings.SSID) - 1); + strncpy(new_settings.Password, password, sizeof(new_settings.Password) - 1); + + // Update + SettingsManager_UpdateWiFi(&new_settings); + SettingsManager_Save(); + + // Test WiFi connection... + if (wifi_connect_test() != ESP_OK) { + // On error: Rollback + SettingsManager_UpdateWiFi(&old_settings); + SettingsManager_Save(); + return ESP_FAIL; + } + + return ESP_OK; +} +---- + +==== Batch Updates + +[source,cpp] +---- +void configure_device_initial(void) +{ + App_Settings_System_t system; + App_Settings_Display_t display; + App_Settings_WiFi_t wifi; + + // Change multiple settings + SettingsManager_GetSystem(&system); + strncpy(system.DeviceName, "PyroVision-001", sizeof(system.DeviceName)); + system.SDCard_AutoMount = true; + SettingsManager_UpdateSystem(&system); + + SettingsManager_GetDisplay(&display); + display.Brightness = 80; + display.ScreenTimeout = 60; + SettingsManager_UpdateDisplay(&display); + + SettingsManager_GetWiFi(&wifi); + wifi.AutoConnect = true; + wifi.MaxRetries = 5; + SettingsManager_UpdateWiFi(&wifi); + + // Save ONCE for all changes + SettingsManager_Save(); +} +---- + +== Factory Defaults System + +=== Hierarchy of Default Sources + +1. *JSON Config* (`data/default_settings.json`) + * Loaded on first boot + * Flag `"config_loaded"` prevents reloading + * Flexible and easy to customize without recompilation + +2. *Hardcoded Defaults* (in `settingsDefaultLoader.cpp`) + * Fallback if JSON is not available + * Guaranteed base configuration + * Defined in code + +=== JSON Format + +[source,json] +---- +{ + "lepton": { + "emissivity": [ + { + "name": "Concrete", + "value": 0.92 + }, + { + "name": "Human Skin", + "value": 0.98 + } + ], + "roi": { + "spotmeter": { + "x": 60, + "y": 60, + "width": 40, + "height": 40 + } + } + }, + "wifi": { + "ssid": "", + "password": "", + "maxRetries": 5, + "retryInterval": 2000, + "autoConnect": true + }, + "display": { + "brightness": 80, + "timeout": 60 + } +} +---- + +=== Customizing Defaults + +==== Option 1: Modify JSON + +1. Edit `data/default_settings.json` +2. Flash firmware +3. Perform factory reset or manually reset `config_loaded` flag + +==== Option 2: Change Hardcoded Defaults + +Functions in `settingsDefaultLoader.cpp`: + +* `SettingsManager_InitDefaultLepton()` +* `SettingsManager_InitDefaultWiFi()` +* `SettingsManager_InitDefaultDisplay()` +* etc. + +== Best Practices + +=== DO's + +* ✓ Always call `SettingsManager_Save()` after updates if persistence is desired +* ✓ Register event handlers for dynamic response to setting changes +* ✓ Use Get/Update functions for category-specific access +* ✓ Configure factory defaults in JSON for easy customization +* ✓ Perform error handling on all API calls + +=== DON'Ts + +* ✗ Do not directly access internal `_State` structure +* ✗ Do not access settings without mutex (API already uses mutex) +* ✗ Do not forget to save after updates +* ✗ Do not use `ResetToDefaults()` in production code without user confirmation +* ✗ Do not save too frequently (consider flash wear) + +=== Performance Tips + +* *Batch Updates*: Make multiple changes, then save once +* *Event-based*: Use events instead of polling +* *Category-specific*: Only load/update relevant settings category + +== Troubleshooting + +=== Common Problems + +==== Settings are not saved + +*Symptom*: Changes are lost after restart + +*Cause*: `SettingsManager_Save()` was not called + +*Solution*: +[source,cpp] +---- +SettingsManager_UpdateWiFi(&wifi); +SettingsManager_Save(); // <-- Don't forget! +---- + +==== ESP_ERR_INVALID_SIZE on loading + +*Symptom*: Settings cannot be loaded after firmware update + +*Cause*: Structure size has changed + +*Solution*: Perform factory reset or implement migration + +==== Defaults are not loaded + +*Symptom*: JSON defaults are ignored + +*Cause*: `config_loaded` flag is set + +*Solution*: +[source,cpp] +---- +// Manually reset flag +nvs_handle_t handle; +nvs_open("pyrovision", NVS_READWRITE, &handle); +nvs_set_u8(handle, "config_loaded", 0); +nvs_commit(handle); +nvs_close(handle); +esp_restart(); +---- + +==== Events are not received + +*Symptom*: Event handler is not called + +*Cause*: Handler not registered or wrong event base + +*Solution*: +[source,cpp] +---- +esp_event_loop_create_default(); // Initialize event loop +esp_event_handler_register(SETTINGS_EVENTS, // Correct base! + SETTINGS_EVENT_WIFI_CHANGED, + handler, + NULL); +---- + +== Extensions + +=== Adding a New Settings Category + +1. *Define structure in `settingsTypes.h`*: +[source,cpp] +---- +typedef struct { + uint16_t NewParameter; + char NewString[32]; +} App_Settings_NewCategory_t; +---- + +2. *Insert into `App_Settings_t`*: +[source,cpp] +---- +typedef struct { + // ... existing categories + App_Settings_NewCategory_t NewCategory; +} App_Settings_t; +---- + +3. *Add event ID* in `settingsTypes.h`: +[source,cpp] +---- +enum { + // ... existing events + SETTINGS_EVENT_NEWCATEGORY_CHANGED, +}; +---- + +4. *Implement Get/Update functions* in `settingsManager.cpp`: +[source,cpp] +---- +esp_err_t SettingsManager_GetNewCategory(App_Settings_NewCategory_t* p_Settings) +{ + if (p_Settings == NULL) { + return ESP_ERR_INVALID_ARG; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_State.Settings.NewCategory, sizeof(App_Settings_NewCategory_t)); + xSemaphoreGive(_State.Mutex); + + return ESP_OK; +} + +esp_err_t SettingsManager_UpdateNewCategory(App_Settings_NewCategory_t* p_Settings) +{ + return SettingsManager_Update(p_Settings, + &_State.Settings.NewCategory, + sizeof(App_Settings_NewCategory_t), + SETTINGS_EVENT_NEWCATEGORY_CHANGED); +} +---- + +5. *Add default initialization* + +6. *Extend JSON schema* (optional) + +== License + +Copyright (C) Daniel Kampert, 2026 + +This software is licensed under the GNU General Public License v3.0. +Website: www.kampis-elektroecke.de + +== Contact + +Please report bugs and suggestions to: DanielKampert@kampis-elektroecke.de diff --git a/docs/TimeManager.adoc b/docs/TimeManager.adoc new file mode 100644 index 0000000..0310234 --- /dev/null +++ b/docs/TimeManager.adoc @@ -0,0 +1,998 @@ += PyroVision Time Manager Documentation +Daniel Kampert +v1.0, 2026-01-14 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The Time Manager is a unified time management component for the PyroVision firmware that provides reliable timekeeping through multiple time sources. It automatically manages time synchronization via SNTP (network time) and RTC (Real-Time Clock) backup, ensuring accurate timestamps even without network connectivity. + +=== Key Features + +* *Dual Time Sources*: Automatic switching between SNTP (network) and RTC (hardware backup) +* *Automatic Synchronization*: Periodic SNTP sync with configurable intervals +* *RTC Backup*: Automatic backup of synchronized time to hardware RTC +* *Network Awareness*: Seamless handling of network connect/disconnect events +* *Event-based Architecture*: Notification of time synchronization and source changes +* *Timezone Support*: Configurable timezone with POSIX format +* *Failover Management*: Graceful fallback to RTC when network unavailable +* *Status Monitoring*: Comprehensive status information for debugging + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Manager/Time/ +├── timeManager.h # Public API +├── timeManager.cpp # Implementation +└── time_types.h # Event types and definitions +---- + +=== Time Source Hierarchy + +The Time Manager uses a prioritized hierarchy of time sources: + +1. *SNTP (Network Time Protocol)* + * Highest priority when network is available + * Provides internet-synchronized time (accurate to milliseconds) + * Automatically syncs every hour + * Requires WiFi/network connection + +2. *RTC (Real-Time Clock)* + * Hardware backup time source + * Used when network is unavailable + * Maintains time during power cycles (with battery) + * Updated periodically from SNTP (every 5 minutes) + +3. *System Time* + * Fallback when neither SNTP nor RTC available + * Will drift over time without external synchronization + * Loses accuracy during deep sleep or reset + +=== Internal State Management + +The manager maintains its state in the `TimeManager_State_t` structure: + +[source,cpp] +---- +typedef struct { + bool isInitialized; // Initialization status + bool hasRTC; // RTC hardware available + bool hasNetwork; // Network connected + bool timeSynchronized; // Time has been synchronized + i2c_master_dev_handle_t RTC_Handle; // RTC device handle + TimeManager_Source_t activeSource; // Current active time source + time_t lastSNTP_Sync; // Last SNTP sync timestamp + time_t lastRTC_Sync; // Last RTC read timestamp + time_t lastRTC_Backup; // Last RTC backup timestamp + uint32_t sntpSyncCount; // SNTP sync counter + uint32_t rtcSyncCount; // RTC read counter + esp_timer_handle_t syncTimer; // Periodic sync timer +} TimeManager_State_t; +---- + +=== Synchronization Strategy + +==== SNTP Synchronization + +* *Interval*: Every 3600 seconds (1 hour) +* *Server*: pool.ntp.org (configurable) +* *Mode*: Polling mode +* *Callback*: Notifies on successful sync +* *Auto-restart*: Restarts on network reconnection + +==== RTC Backup + +* *Interval*: Every 300 seconds (5 minutes) +* *Condition*: Only when time is synchronized from SNTP +* *Purpose*: Preserve accurate time during network outages +* *Validation*: Checks year >= 2025 before accepting RTC time + +--- + +== Data Structures + +=== Time Source Enum + +[source,cpp] +---- +typedef enum { + TIME_SOURCE_NONE = 0, // No time source available + TIME_SOURCE_RTC, // Time from RTC + TIME_SOURCE_SNTP, // Time from SNTP + TIME_SOURCE_SYSTEM, // Time from system (not synchronized) +} TimeManager_Source_t; +---- + +=== Time Synchronization Status + +[source,cpp] +---- +typedef struct { + TimeManager_Source_t ActiveSource; // Currently active time source + bool SNTP_Available; // SNTP available (network connected) + bool RTC_Available; // RTC available + time_t LastSync_SNTP; // Timestamp of last SNTP sync + time_t LastSync_RTC; // Timestamp of last RTC sync + uint32_t SNTP_SyncCount; // Number of successful SNTP syncs + uint32_t RTC_SyncCount; // Number of RTC reads +} TimeManager_Status_t; +---- + +=== Event System + +==== Event Base + +[source,cpp] +---- +ESP_EVENT_DECLARE_BASE(TIME_EVENTS); +---- + +==== Event IDs + +[cols="2,3,2"] +|=== +|Event |Description |Data + +|`TIME_EVENT_SYNCHRONIZED` +|Time synchronized from SNTP +|`struct tm` + +|`TIME_EVENT_SOURCE_CHANGED` +|Time source changed (SNTP/RTC/System) +|`TimeManager_Source_t` +|=== + +--- + +== API Reference + +=== Initialization and Lifecycle + +==== `TimeManager_Init()` + +[source,cpp] +---- +esp_err_t TimeManager_Init(void *p_RTC_Handle); +---- + +*Description*: Initializes the Time Manager and sets up time sources. + +*Process*: + +1. Validates and stores RTC handle (if provided) +2. Attempts to load time from RTC (if available) +3. Validates RTC time (year >= 2025) +4. Sets system time from RTC if valid +5. Sets default timezone (UTC) +6. Creates periodic synchronization timer +7. Starts timer with 60-second period + +*Parameters*: + +* `p_RTC_Handle`: Pointer to RTC device handle (NULL if RTC not available) + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_*` on timer creation/start failure + +*Example*: + +[source,cpp] +---- +i2c_master_dev_handle_t rtc_handle; +// ... initialize RTC ... + +if (TimeManager_Init(&rtc_handle) == ESP_OK) { + ESP_LOGI(TAG, "Time Manager initialized successfully"); +} +---- + +==== `TimeManager_Deinit()` + +[source,cpp] +---- +esp_err_t TimeManager_Deinit(void); +---- + +*Description*: Deinitializes the Time Manager and releases resources. + +*Process*: + +1. Stops periodic sync timer +2. Deletes timer +3. Stops SNTP if enabled +4. Resets initialization status + +*Return Value*: `ESP_OK` + +--- + +=== Network Event Handlers + +==== `TimeManager_OnNetworkConnected()` + +[source,cpp] +---- +esp_err_t TimeManager_OnNetworkConnected(void); +---- + +*Description*: Called when network connection is established. Starts SNTP synchronization. + +*Process*: + +1. Sets network available flag +2. Initializes SNTP if first connection +3. Restarts SNTP if already initialized (triggers immediate sync) +4. Configures SNTP server (pool.ntp.org) +5. Sets sync notification callback + +*Return Value*: `ESP_OK` + +*Example*: + +[source,cpp] +---- +static void wifi_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_id == WIFI_EVENT_STA_CONNECTED) { + TimeManager_OnNetworkConnected(); + } +} +---- + +==== `TimeManager_OnNetworkDisconnected()` + +[source,cpp] +---- +esp_err_t TimeManager_OnNetworkDisconnected(void); +---- + +*Description*: Called when network connection is lost. Switches to RTC as time source. + +*Process*: + +1. Clears network available flag +2. Switches active source to RTC (if available) +3. Posts `TIME_EVENT_SOURCE_CHANGED` event if source changed +4. Falls back to system time if no RTC + +*Return Value*: `ESP_OK` + +--- + +=== Time Retrieval + +==== `TimeManager_GetTime()` + +[source,cpp] +---- +esp_err_t TimeManager_GetTime(struct tm *p_Time, TimeManager_Source_t *p_Source); +---- + +*Description*: Gets the current time from the best available source. + +*Parameters*: + +* `p_Time`: Pointer to store the time structure +* `p_Source`: Optional pointer to store the time source (can be NULL) + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if `p_Time` is NULL + +*Example*: + +[source,cpp] +---- +struct tm timeinfo; +TimeManager_Source_t source; + +if (TimeManager_GetTime(&timeinfo, &source) == ESP_OK) { + ESP_LOGI(TAG, "Current time: %04d-%02d-%02d %02d:%02d:%02d (Source: %d)", + timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, source); +} +---- + +==== `TimeManager_GetTimestamp()` + +[source,cpp] +---- +esp_err_t TimeManager_GetTimestamp(time_t *p_Time, TimeManager_Source_t *p_Source); +---- + +*Description*: Gets the current time as UNIX timestamp (seconds since epoch). + +*Parameters*: + +* `p_Time`: Pointer to store the timestamp +* `p_Source`: Optional pointer to store the time source (can be NULL) + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if `p_Time` is NULL + +*Example*: + +[source,cpp] +---- +time_t timestamp; + +if (TimeManager_GetTimestamp(×tamp, NULL) == ESP_OK) { + ESP_LOGI(TAG, "Current timestamp: %ld", timestamp); +} +---- + +==== `TimeManager_GetTimeString()` + +[source,cpp] +---- +esp_err_t TimeManager_GetTimeString(char *p_Buffer, size_t Size, const char *Format); +---- + +*Description*: Formats the current time as a string using strftime format. + +*Parameters*: + +* `p_Buffer`: Buffer to store the formatted time +* `Size`: Buffer size +* `Format`: Time format string (strftime format) + +*Common Format Specifiers*: + +* `%Y` - Year (4 digits) +* `%m` - Month (01-12) +* `%d` - Day of month (01-31) +* `%H` - Hour (00-23) +* `%M` - Minute (00-59) +* `%S` - Second (00-59) +* `%A` - Weekday name (e.g., "Monday") +* `%B` - Month name (e.g., "January") + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if parameters are NULL or Size is 0 +* `ESP_ERR_NO_MEM` if buffer is too small + +*Example*: + +[source,cpp] +---- +char time_str[64]; + +// ISO 8601 format +TimeManager_GetTimeString(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S"); +ESP_LOGI(TAG, "Time: %s", time_str); + +// Human-readable format +TimeManager_GetTimeString(time_str, sizeof(time_str), "%A, %B %d, %Y at %I:%M %p"); +ESP_LOGI(TAG, "Time: %s", time_str); +---- + +--- + +=== Status and Control + +==== `TimeManager_GetStatus()` + +[source,cpp] +---- +esp_err_t TimeManager_GetStatus(TimeManager_Status_t *p_Status); +---- + +*Description*: Gets comprehensive status information about time synchronization. + +*Parameters*: + +* `p_Status`: Pointer to store the status structure + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if `p_Status` is NULL + +*Example*: + +[source,cpp] +---- +TimeManager_Status_t status; + +if (TimeManager_GetStatus(&status) == ESP_OK) { + ESP_LOGI(TAG, "Active source: %d", status.ActiveSource); + ESP_LOGI(TAG, "SNTP available: %s", status.SNTP_Available ? "yes" : "no"); + ESP_LOGI(TAG, "RTC available: %s", status.RTC_Available ? "yes" : "no"); + ESP_LOGI(TAG, "SNTP syncs: %lu", status.SNTP_SyncCount); + ESP_LOGI(TAG, "Last SNTP sync: %ld", status.LastSync_SNTP); +} +---- + +==== `TimeManager_ForceSync()` + +[source,cpp] +---- +esp_err_t TimeManager_ForceSync(void); +---- + +*Description*: Forces immediate SNTP synchronization (if network available). + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_STATE` if network is not connected + +*Example*: + +[source,cpp] +---- +if (TimeManager_ForceSync() == ESP_OK) { + ESP_LOGI(TAG, "Forced SNTP sync initiated"); +} +---- + +==== `TimeManager_IsTimeSynchronized()` + +[source,cpp] +---- +bool TimeManager_IsTimeSynchronized(void); +---- + +*Description*: Checks if time has been synchronized from SNTP or RTC. + +*Return Value*: `true` if time is synchronized and reliable, `false` otherwise + +*Example*: + +[source,cpp] +---- +if (TimeManager_IsTimeSynchronized()) { + // Safe to use timestamps for logging, etc. + save_data_with_timestamp(); +} else { + ESP_LOGW(TAG, "Time not synchronized, timestamps may be inaccurate"); +} +---- + +--- + +=== Timezone Configuration + +==== `TimeManager_SetTimezone()` + +[source,cpp] +---- +esp_err_t TimeManager_SetTimezone(const char *p_Timezone); +---- + +*Description*: Sets the timezone for time display. + +*Parameters*: + +* `p_Timezone`: Timezone string in POSIX format + +*POSIX Timezone Format*: + +[source] +---- +std offset [dst [offset] [,start[/time],end[/time]]] + +std - Standard timezone abbreviation (e.g., CET, EST) +offset - Hours offset from UTC (e.g., -1, +5) +dst - Daylight saving time abbreviation (e.g., CEST, EDT) +start - DST start rule (e.g., M3.5.0 = last Sunday in March) +end - DST end rule (e.g., M10.5.0 = last Sunday in October) +---- + +*Common Timezone Examples*: + +[cols="2,3,2"] +|=== +|Timezone |String |Description + +|UTC +|`UTC-0` +|Coordinated Universal Time + +|CET/CEST +|`CET-1CEST,M3.5.0,M10.5.0/3` +|Central European Time + +|EST/EDT +|`EST5EDT,M3.2.0,M11.1.0` +|US Eastern Time + +|PST/PDT +|`PST8PDT,M3.2.0,M11.1.0` +|US Pacific Time + +|JST +|`JST-9` +|Japan Standard Time (no DST) + +|AEST/AEDT +|`AEST-10AEDT,M10.1.0,M4.1.0/3` +|Australian Eastern Time +|=== + +*Return Value*: + +* `ESP_OK` on success +* `ESP_ERR_INVALID_ARG` if `p_Timezone` is NULL + +*Example*: + +[source,cpp] +---- +// Set Central European Time +TimeManager_SetTimezone("CET-1CEST,M3.5.0,M10.5.0/3"); + +// Now all time functions return local time +char time_str[64]; +TimeManager_GetTimeString(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S %Z"); +ESP_LOGI(TAG, "Local time: %s", time_str); +---- + +--- + +== Usage + +=== Basic Workflow + +==== 1. Initialization at Startup + +[source,cpp] +---- +#include "timeManager.h" + +void app_main(void) +{ + i2c_master_dev_handle_t rtc_handle; + + // Initialize I2C and RTC first + DevicesManager_GetRTCHandle(&rtc_handle); + + // Initialize Time Manager + ESP_ERROR_CHECK(TimeManager_Init(&rtc_handle)); + + // Set desired timezone + App_Settings_System_t system_settings; + SettingsManager_GetSystem(&system_settings); + TimeManager_SetTimezone(system_settings.Timezone); + + // Further initializations... +} +---- + +==== 2. Network Event Integration + +[source,cpp] +---- +static void network_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + switch (event_id) { + case NETWORK_EVENT_WIFI_CONNECTED: + TimeManager_OnNetworkConnected(); + break; + + case NETWORK_EVENT_WIFI_DISCONNECTED: + TimeManager_OnNetworkDisconnected(); + break; + } +} + +void init_network(void) +{ + esp_event_handler_register(NETWORK_EVENTS, + ESP_EVENT_ANY_ID, + network_event_handler, + NULL); +} +---- + +==== 3. Using Time in Application + +[source,cpp] +---- +// Get current time +struct tm timeinfo; +if (TimeManager_GetTime(&timeinfo, NULL) == ESP_OK) { + char filename[64]; + snprintf(filename, sizeof(filename), + "capture_%04d%02d%02d_%02d%02d%02d.jpg", + timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); + save_image(filename); +} + +// Check if time is reliable +if (TimeManager_IsTimeSynchronized()) { + // Safe to use for logging + log_event_with_timestamp(); +} else { + ESP_LOGW(TAG, "Time not synchronized, waiting..."); +} +---- + +--- + +=== Event Handling + +==== Registering Event Handlers + +[source,cpp] +---- +#include +#include "time_types.h" + +static void time_event_handler(void* handler_args, esp_event_base_t base, + int32_t id, void* event_data) +{ + switch (id) { + case TIME_EVENT_SYNCHRONIZED: { + struct tm *timeinfo = (struct tm*)event_data; + ESP_LOGI(TAG, "Time synchronized: %04d-%02d-%02d %02d:%02d:%02d", + timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, + timeinfo->tm_mday, timeinfo->tm_hour, + timeinfo->tm_min, timeinfo->tm_sec); + + // Update RTC display + update_clock_display(); + break; + } + + case TIME_EVENT_SOURCE_CHANGED: { + TimeManager_Source_t *source = (TimeManager_Source_t*)event_data; + const char *source_name = (*source == TIME_SOURCE_SNTP) ? "SNTP" : + (*source == TIME_SOURCE_RTC) ? "RTC" : "System"; + ESP_LOGI(TAG, "Time source changed to: %s", source_name); + break; + } + } +} + +void init_time_events(void) +{ + esp_event_handler_register(TIME_EVENTS, + ESP_EVENT_ANY_ID, + time_event_handler, + NULL); +} +---- + +--- + +=== Advanced Patterns + +==== Status Monitoring Task + +[source,cpp] +---- +void time_status_task(void *pvParameters) +{ + TimeManager_Status_t status; + char time_str[64]; + + while (1) { + if (TimeManager_GetStatus(&status) == ESP_OK) { + TimeManager_GetTimeString(time_str, sizeof(time_str), + "%Y-%m-%d %H:%M:%S"); + + ESP_LOGI(TAG, "=== Time Manager Status ==="); + ESP_LOGI(TAG, "Current time: %s", time_str); + ESP_LOGI(TAG, "Active source: %s", + status.ActiveSource == TIME_SOURCE_SNTP ? "SNTP" : + status.ActiveSource == TIME_SOURCE_RTC ? "RTC" : "System"); + ESP_LOGI(TAG, "SNTP syncs: %lu (last: %ld sec ago)", + status.SNTP_SyncCount, + status.LastSync_SNTP > 0 ? time(NULL) - status.LastSync_SNTP : 0); + ESP_LOGI(TAG, "RTC reads: %lu", status.RTC_SyncCount); + } + + vTaskDelay(pdMS_TO_TICKS(30000)); // Every 30 seconds + } +} +---- + +==== Timezone Selection UI + +[source,cpp] +---- +typedef struct { + const char *name; + const char *posix_tz; +} Timezone_Entry_t; + +const Timezone_Entry_t timezones[] = { + {"UTC", "UTC-0"}, + {"London (UK)", "GMT0BST,M3.5.0/1,M10.5.0"}, + {"Berlin (Germany)", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"New York (US)", "EST5EDT,M3.2.0,M11.1.0"}, + {"Los Angeles (US)", "PST8PDT,M3.2.0,M11.1.0"}, + {"Tokyo (Japan)", "JST-9"}, + {"Sydney (Australia)", "AEST-10AEDT,M10.1.0,M4.1.0/3"}, +}; + +void set_timezone_by_index(size_t index) +{ + if (index < sizeof(timezones) / sizeof(timezones[0])) { + ESP_LOGI(TAG, "Setting timezone to: %s", timezones[index].name); + TimeManager_SetTimezone(timezones[index].posix_tz); + + // Save to settings + App_Settings_System_t system; + SettingsManager_GetSystem(&system); + strncpy(system.Timezone, timezones[index].posix_tz, sizeof(system.Timezone) - 1); + SettingsManager_UpdateSystem(&system); + SettingsManager_Save(); + } +} +---- + +==== Periodic Time Display + +[source,cpp] +---- +void display_time_task(void *pvParameters) +{ + char time_str[64]; + TimeManager_Source_t source; + + while (1) { + struct tm timeinfo; + if (TimeManager_GetTime(&timeinfo, &source) == ESP_OK) { + // Format time + strftime(time_str, sizeof(time_str), "%H:%M:%S", &timeinfo); + + // Update display with source indicator + const char *source_icon = (source == TIME_SOURCE_SNTP) ? "🌐" : + (source == TIME_SOURCE_RTC) ? "⏰" : "⚠️"; + + display_text(time_str, source_icon); + } + + vTaskDelay(pdMS_TO_TICKS(1000)); // Update every second + } +} +---- + +--- + +== Configuration + +=== Compile-Time Constants + +The following constants can be adjusted in `timeManager.cpp`: + +[cols="2,1,3"] +|=== +|Constant |Default |Description + +|`TIME_MANAGER_SYNC_INTERVAL_SEC` +|3600 +|SNTP sync interval (1 hour) + +|`TIME_MANAGER_RTC_BACKUP_INTERVAL_SEC` +|300 +|RTC backup interval (5 minutes) + +|`TIME_MANAGER_VALID_YEAR_MIN` +|2025 +|Minimum valid year for RTC validation +|=== + +=== SNTP Server Configuration + +By default, the Time Manager uses `pool.ntp.org`. To use a custom NTP server: + +[source,cpp] +---- +// In timeManager.cpp, modify: +esp_sntp_setservername(0, "time.google.com"); // Google NTP +// or +esp_sntp_setservername(0, "time.nist.gov"); // NIST NTP +// or +esp_sntp_setservername(0, "192.168.1.1"); // Local NTP server +---- + +--- + +== Best Practices + +=== DO's + +* ✓ Always initialize Time Manager after Device Manager (requires RTC handle) +* ✓ Call `TimeManager_OnNetworkConnected()` when WiFi connects +* ✓ Call `TimeManager_OnNetworkDisconnected()` when WiFi disconnects +* ✓ Check `TimeManager_IsTimeSynchronized()` before using time for critical operations +* ✓ Set timezone according to user settings +* ✓ Register event handlers to monitor time sync status +* ✓ Use RTC with battery backup for best reliability + +=== DON'Ts + +* ✗ Don't assume time is accurate immediately after boot +* ✗ Don't use system time for security-critical operations without sync check +* ✗ Don't manually set system time (use Time Manager functions) +* ✗ Don't forget to handle network events +* ✗ Don't rely on time accuracy without RTC during extended offline periods + +=== Performance Tips + +* *Battery Backup*: Use RTC with battery for uninterrupted timekeeping +* *Fast Boot*: RTC provides immediate valid time on startup +* *Network Sync*: SNTP provides high accuracy when online +* *Periodic Backup*: RTC backup ensures time survives network outages + +--- + +== Troubleshooting + +=== Common Problems + +==== Time not synchronized after boot + +*Symptom*: `TimeManager_IsTimeSynchronized()` returns `false` + +*Possible Causes*: +* Network not connected yet +* RTC not available or has invalid time +* System just booted and SNTP hasn't synced yet + +*Solution*: +[source,cpp] +---- +// Wait for time sync or proceed with degraded functionality +int retries = 0; +while (!TimeManager_IsTimeSynchronized() && retries < 30) { + ESP_LOGI(TAG, "Waiting for time sync... (%d/30)", retries + 1); + vTaskDelay(pdMS_TO_TICKS(1000)); + retries++; +} + +if (TimeManager_IsTimeSynchronized()) { + ESP_LOGI(TAG, "Time synchronized!"); +} else { + ESP_LOGW(TAG, "Proceeding without time sync"); +} +---- + +==== SNTP sync fails + +*Symptom*: Time source stays on RTC/System, SNTP_SyncCount doesn't increase + +*Possible Causes*: +* Network connection issues +* Firewall blocking NTP traffic (port 123 UDP) +* DNS resolution failure for pool.ntp.org +* Incorrect NTP server address + +*Solution*: +[source,cpp] +---- +// Check network connectivity +ESP_LOGI(TAG, "Testing network..."); +// Try force sync +TimeManager_ForceSync(); + +// Check status +TimeManager_Status_t status; +TimeManager_GetStatus(&status); +ESP_LOGI(TAG, "Network available: %s", status.SNTP_Available ? "yes" : "no"); +ESP_LOGI(TAG, "SNTP syncs: %lu", status.SNTP_SyncCount); +---- + +==== RTC time invalid after battery replacement + +*Symptom*: RTC year shows < 2025, time not loaded from RTC + +*Cause*: RTC was reset or battery was dead + +*Solution*: +[source,cpp] +---- +// RTC will be automatically updated once SNTP syncs +// Wait for network and SNTP sync, or manually set RTC: +struct tm manual_time = { + .tm_year = 2026 - 1900, // Years since 1900 + .tm_mon = 0, // January (0-11) + .tm_mday = 14, // 14th + .tm_hour = 12, + .tm_min = 0, + .tm_sec = 0, +}; +RTC_SetTime(&manual_time); +---- + +==== Timezone not working correctly + +*Symptom*: Displayed time is wrong by several hours + +*Cause*: Incorrect timezone string or DST rules + +*Solution*: +[source,cpp] +---- +// Verify timezone string format +const char *tz = "CET-1CEST,M3.5.0,M10.5.0/3"; // Correct format +TimeManager_SetTimezone(tz); + +// Test with known date/time +struct tm test_time; +TimeManager_GetTime(&test_time, NULL); +char time_str[64]; +strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S %Z", &test_time); +ESP_LOGI(TAG, "Current time: %s", time_str); +---- + +==== Time drifts during long offline periods + +*Symptom*: Time becomes increasingly inaccurate without network + +*Cause*: System clock drift, no RTC, or RTC crystal inaccuracy + +*Solution*: + +* Install RTC module with accurate crystal oscillator +* Use RTC with temperature compensation (DS3231) +* Ensure RTC has backup battery +* Implement periodic RTC calibration when online + +--- + +== Technical Details + +=== SNTP Operation + +The Time Manager uses ESP-IDF's built-in SNTP client: + +* *Protocol*: SNTPv4 (Simple Network Time Protocol) +* *Transport*: UDP port 123 +* *Mode*: Client polling mode +* *Callback*: Async notification on successful sync +* *Retry*: Automatic retry on failure + +=== RTC Integration + +Compatible with I2C RTC modules: + +* DS1307, DS3231, PCF8523, etc. +* Requires I2C master device handle +* Uses standard `struct tm` format +* Validates year before accepting RTC time + +=== Timezone Implementation + +Uses POSIX TZ environment variable: + +* Configured via `setenv("TZ", ...)` and `tzset()` +* Supports DST (Daylight Saving Time) transitions +* Automatic DST adjustment based on rules +* Affects all time functions (`localtime()`, `strftime()`, etc.) + +--- + +== License + +Copyright (C) Daniel Kampert, 2026 + +This software is licensed under the GNU General Public License v3.0. +Website: www.kampis-elektroecke.de + +--- + +== Contact + +Please report bugs and suggestions to: DanielKampert@kampis-elektroecke.de diff --git a/main/Application/Manager/Devices/devicesManager.h b/main/Application/Manager/Devices/devicesManager.h index 1a74ced..cf94893 100644 --- a/main/Application/Manager/Devices/devicesManager.h +++ b/main/Application/Manager/Devices/devicesManager.h @@ -58,6 +58,4 @@ esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage); */ esp_err_t DevicesManager_GetRTCHandle(i2c_master_dev_handle_t *p_Handle); -// TODO: Function to get charge status? - #endif /* DEVICESMANAGER_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Network/Provisioning/provisioning.cpp b/main/Application/Manager/Network/Provisioning/provisioning.cpp index 6ec5064..a3a488e 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.cpp +++ b/main/Application/Manager/Network/Provisioning/provisioning.cpp @@ -169,18 +169,20 @@ static esp_err_t on_Custom_Data_Prov_Handler(uint32_t session_id, const uint8_t return ESP_OK; } -esp_err_t Provisioning_Init(Network_WiFi_STA_Config_t *p_Config) +esp_err_t Provisioning_Init(Network_Provisioning_Config_t *p_Config) { if (_Provisioning_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); return ESP_OK; + } else if (p_Config == NULL) { + return ESP_ERR_INVALID_ARG; } ESP_LOGD(TAG, "Initializing Provisioning Manager"); - strncpy(_Provisioning_State.device_name, p_Config->ProvConfig.DeviceName, + strncpy(_Provisioning_State.device_name, p_Config->Name, sizeof(_Provisioning_State.device_name) - 1); - strncpy(_Provisioning_State.pop, p_Config->ProvConfig.PoP, sizeof(_Provisioning_State.pop) - 1); - _Provisioning_State.timeout_sec = p_Config->ProvConfig.Timeout; + strncpy(_Provisioning_State.pop, p_Config->PoP, sizeof(_Provisioning_State.pop) - 1); + _Provisioning_State.timeout_sec = p_Config->Timeout; ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &on_Prov_Event, NULL)); @@ -250,13 +252,7 @@ esp_err_t Provisioning_Start(void) return Error; } -#ifdef CONFIG_NETWORK_PROV_SECURITY_VERSION - int security = CONFIG_NETWORK_PROV_SECURITY_VERSION; -#else - int security = 1; -#endif - - if ((security == 1) && (strlen(_Provisioning_State.pop) > 0)) { + if (strlen(_Provisioning_State.pop) > 0) { pop = _Provisioning_State.pop; } @@ -272,7 +268,7 @@ esp_err_t Provisioning_Start(void) /* Register custom endpoint */ wifi_prov_mgr_endpoint_create("custom-data"); - Error = wifi_prov_mgr_start_provisioning((wifi_prov_security_t)security, + Error = wifi_prov_mgr_start_provisioning(WIFI_PROV_SECURITY_1, pop, service_name, NULL); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to start provisioning: %d!", Error); diff --git a/main/Application/Manager/Network/Provisioning/provisioning.h b/main/Application/Manager/Network/Provisioning/provisioning.h index 2366fc4..1b91f63 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.h +++ b/main/Application/Manager/Network/Provisioning/provisioning.h @@ -27,13 +27,13 @@ #include #include -#include "../network_types.h" +#include "../networkTypes.h" /** @brief Initialize provisioning manager. - * @param p_Config Network configuration + * @param p_Config Network provisioning configuration * @return ESP_OK on success */ -esp_err_t Provisioning_Init(Network_WiFi_STA_Config_t *p_Config); +esp_err_t Provisioning_Init(Network_Provisioning_Config_t *p_Config); /** @brief Deinitialize provisioning manager. */ diff --git a/main/Application/Manager/Network/Server/http_server.cpp b/main/Application/Manager/Network/Server/http_server.cpp index 7501dde..d3a399c 100644 --- a/main/Application/Manager/Network/Server/http_server.cpp +++ b/main/Application/Manager/Network/Server/http_server.cpp @@ -33,8 +33,8 @@ #include #include "http_server.h" -#include "image_encoder.h" -#include "../network_types.h" +#include "imageEncoder.h" +#include "../networkTypes.h" #define HTTP_SERVER_API_BASE_PATH "/api/v1" #define HTTP_SERVER_API_KEY_HEADER "X-API-Key" @@ -256,7 +256,7 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) } /* Encode image */ - Error = Image_Encoder_Encode(_HTTPServer_State.ThermalFrame, format, palette, &encoded); + Error = ImageEncoder_Encode(_HTTPServer_State.ThermalFrame, format, palette, &encoded); xSemaphoreGive(_HTTPServer_State.ThermalFrame->mutex); @@ -285,7 +285,7 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) Error = httpd_resp_send(p_Request, (const char *)encoded.data, encoded.size); /* Free encoded image */ - Image_Encoder_Free(&encoded); + ImageEncoder_Free(&encoded); return Error; } diff --git a/main/Application/Manager/Network/Server/http_server.h b/main/Application/Manager/Network/Server/http_server.h index 57c324f..77fa722 100644 --- a/main/Application/Manager/Network/Server/http_server.h +++ b/main/Application/Manager/Network/Server/http_server.h @@ -27,7 +27,7 @@ #include #include -#include "../network_types.h" +#include "../networkTypes.h" /** @brief Initialize the HTTP server. * @param p_Config Pointer to server configuration. diff --git a/main/Application/Manager/Network/Server/image_encoder.cpp b/main/Application/Manager/Network/Server/imageEncoder.cpp similarity index 89% rename from main/Application/Manager/Network/Server/image_encoder.cpp rename to main/Application/Manager/Network/Server/imageEncoder.cpp index 30e01f4..9441c6e 100644 --- a/main/Application/Manager/Network/Server/image_encoder.cpp +++ b/main/Application/Manager/Network/Server/imageEncoder.cpp @@ -27,16 +27,16 @@ #include -#include "image_encoder.h" +#include "imageEncoder.h" #include "lepton.h" typedef struct { bool isInitialized; uint8_t JpegQuality; -} Image_Encoder_State_t; +} ImageEncoder_State_t; -static Image_Encoder_State_t _Encoder_State; +static ImageEncoder_State_t _Encoder_State; static const char *TAG = "image_encoder"; @@ -44,7 +44,7 @@ static const char *TAG = "image_encoder"; * @param palette Palette type. * @return Pointer to palette array. */ -static const uint8_t (*Image_Encoder_GetPalette(Server_Palette_t palette))[3] { +static const uint8_t (*ImageEncoder_GetPalette(Server_Palette_t palette))[3] { switch (palette) { case PALETTE_IRON: @@ -63,7 +63,7 @@ static const uint8_t (*Image_Encoder_GetPalette(Server_Palette_t palette))[3] { * @param p_Output Output RGB buffer (width * height * 3 bytes) * @return ESP_OK on success */ -static esp_err_t Image_Encoder_ApplyPalette(const Network_Thermal_Frame_t *p_Frame, +static esp_err_t ImageEncoder_ApplyPalette(const Network_Thermal_Frame_t *p_Frame, Server_Palette_t palette, uint8_t *p_Output) { @@ -84,7 +84,7 @@ static esp_err_t Image_Encoder_ApplyPalette(const Network_Thermal_Frame_t *p_Fra * @param p_Encoded Output encoded image * @return ESP_OK on success */ -static esp_err_t Image_Encoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, uint16_t height, +static esp_err_t ImageEncoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, uint16_t height, uint8_t quality, Network_Encoded_Image_t *p_Encoded) { jpeg_enc_config_t enc_config = { @@ -133,7 +133,7 @@ static esp_err_t Image_Encoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, return ESP_OK; } -esp_err_t Image_Encoder_Init(uint8_t Quality) +esp_err_t ImageEncoder_Init(uint8_t Quality) { if (_Encoder_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); @@ -156,7 +156,7 @@ esp_err_t Image_Encoder_Init(uint8_t Quality) return ESP_OK; } -void Image_Encoder_Deinit(void) +void ImageEncoder_Deinit(void) { if (_Encoder_State.isInitialized == false) { return; @@ -167,7 +167,7 @@ void Image_Encoder_Deinit(void) ESP_LOGI(TAG, "Image encoder deinitialized"); } -esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, +esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, Network_ImageFormat_t Format, Server_Palette_t Palette, Network_Encoded_Image_t *p_Encoded) @@ -188,7 +188,7 @@ esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, return ESP_ERR_NO_MEM; } - Error = Image_Encoder_ApplyPalette(p_Frame, Palette, rgb_buffer); + Error = ImageEncoder_ApplyPalette(p_Frame, Palette, rgb_buffer); if (Error != ESP_OK) { heap_caps_free(rgb_buffer); return Error; @@ -196,7 +196,7 @@ esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, switch (Format) { case NETWORK_IMAGE_FORMAT_JPEG: { - Error = Image_Encoder_EncodeJPEG(rgb_buffer, p_Frame->width, p_Frame->height, + Error = ImageEncoder_EncodeJPEG(rgb_buffer, p_Frame->width, p_Frame->height, _Encoder_State.JpegQuality, p_Encoded); break; } @@ -223,7 +223,7 @@ esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, return Error; } -void Image_Encoder_Free(Network_Encoded_Image_t *p_Encoded) +void ImageEncoder_Free(Network_Encoded_Image_t *p_Encoded) { if (p_Encoded == NULL) { return; @@ -237,7 +237,7 @@ void Image_Encoder_Free(Network_Encoded_Image_t *p_Encoded) p_Encoded->size = 0; } -void Image_Encoder_SetQuality(uint8_t Quality) +void ImageEncoder_SetQuality(uint8_t Quality) { _Encoder_State.JpegQuality = Quality; if (_Encoder_State.JpegQuality < 1) { diff --git a/main/Application/Manager/Network/Server/image_encoder.h b/main/Application/Manager/Network/Server/imageEncoder.h similarity index 78% rename from main/Application/Manager/Network/Server/image_encoder.h rename to main/Application/Manager/Network/Server/imageEncoder.h index 8f837da..6377fbb 100644 --- a/main/Application/Manager/Network/Server/image_encoder.h +++ b/main/Application/Manager/Network/Server/imageEncoder.h @@ -26,17 +26,17 @@ #include -#include "../network_types.h" +#include "../networkTypes.h" /** @brief Initialize the image encoder. * @param Quality JPEG quality (1-100) * @return ESP_OK on success */ -esp_err_t Image_Encoder_Init(uint8_t Quality); +esp_err_t ImageEncoder_Init(uint8_t Quality); /** @brief Deinitialize the image encoder. */ -void Image_Encoder_Deinit(void); +void ImageEncoder_Deinit(void); /** @brief Encode a thermal frame to the specified format. * @param p_Frame Pointer to thermal frame data @@ -45,19 +45,19 @@ void Image_Encoder_Deinit(void); * @param p_Encoded Pointer to store encoded image data * @return ESP_OK on success */ -esp_err_t Image_Encoder_Encode(const Network_Thermal_Frame_t *p_Frame, - Network_ImageFormat_t Format, - Server_Palette_t Palette, - Network_Encoded_Image_t *p_Encoded); +esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, + Network_ImageFormat_t Format, + Server_Palette_t Palette, + Network_Encoded_Image_t *p_Encoded); /** @brief Free encoded image data. * @param p_Encoded Pointer to encoded image structure */ -void Image_Encoder_Free(Network_Encoded_Image_t *p_Encoded); +void ImageEncoder_Free(Network_Encoded_Image_t *p_Encoded); /** @brief Set JPEG encoding quality. * @param Quality Quality value (1-100) */ -void Image_Encoder_SetQuality(uint8_t Quality); +void ImageEncoder_SetQuality(uint8_t Quality); #endif /* IMAGE_ENCODER_H_ */ diff --git a/main/Application/Manager/Network/Server/server.h b/main/Application/Manager/Network/Server/server.h index 90baba7..66a5629 100644 --- a/main/Application/Manager/Network/Server/server.h +++ b/main/Application/Manager/Network/Server/server.h @@ -26,7 +26,7 @@ #include "http_server.h" #include "websocket_handler.h" -#include "image_encoder.h" +#include "imageEncoder.h" /** @brief Initialize the complete server (HTTP + WebSocket + Image Encoder). * @param p_Config Pointer to server configuration @@ -36,21 +36,22 @@ static inline esp_err_t Server_Init(const Server_Config_t *p_Config) { esp_err_t Error; - Error = Image_Encoder_Init(80); /* Default JPEG quality */ + /* Default JPEG quality */ + Error = ImageEncoder_Init(80); if (Error != ESP_OK) { return Error; } Error = HTTP_Server_Init(p_Config); if (Error != ESP_OK) { - Image_Encoder_Deinit(); + ImageEncoder_Deinit(); return Error; } Error = WebSocket_Handler_Init(p_Config); if (Error != ESP_OK) { HTTP_Server_Deinit(); - Image_Encoder_Deinit(); + ImageEncoder_Deinit(); return Error; } @@ -63,7 +64,7 @@ static inline void Server_Deinit(void) { WebSocket_Handler_Deinit(); HTTP_Server_Deinit(); - Image_Encoder_Deinit(); + ImageEncoder_Deinit(); } /** @brief Start the server (HTTP server and register WebSocket handler). diff --git a/main/Application/Manager/Network/Server/websocket_handler.cpp b/main/Application/Manager/Network/Server/websocket_handler.cpp index 2194b2f..fc60dfa 100644 --- a/main/Application/Manager/Network/Server/websocket_handler.cpp +++ b/main/Application/Manager/Network/Server/websocket_handler.cpp @@ -28,7 +28,7 @@ #include #include "websocket_handler.h" -#include "image_encoder.h" +#include "imageEncoder.h" /** @brief WebSocket client state. */ @@ -590,7 +590,7 @@ static void WS_BroadcastTask(void *p_Param) /* Encode frame ONCE for all clients (assume JPEG format for simplicity) */ if (xSemaphoreTake(_WSHandler_State.ThermalFrame->mutex, 50 / portTICK_PERIOD_MS) == pdTRUE) { - esp_err_t err = Image_Encoder_Encode(_WSHandler_State.ThermalFrame, + esp_err_t err = ImageEncoder_Encode(_WSHandler_State.ThermalFrame, NETWORK_IMAGE_FORMAT_JPEG, PALETTE_IRON, &Encoded); xSemaphoreGive(_WSHandler_State.ThermalFrame->mutex); @@ -641,7 +641,7 @@ static void WS_BroadcastTask(void *p_Param) xSemaphoreGive(_WSHandler_State.ClientsMutex); /* Free encoded frame after sending to all clients */ - Image_Encoder_Free(&Encoded); + ImageEncoder_Free(&Encoded); } /* Small yield to prevent task starvation */ diff --git a/main/Application/Manager/Network/Server/websocket_handler.h b/main/Application/Manager/Network/Server/websocket_handler.h index 96330d5..957ce8c 100644 --- a/main/Application/Manager/Network/Server/websocket_handler.h +++ b/main/Application/Manager/Network/Server/websocket_handler.h @@ -27,7 +27,7 @@ #include #include -#include "../network_types.h" +#include "../networkTypes.h" /** @brief Maximum number of WebSocket clients. */ diff --git a/main/Application/Manager/Network/VISA/CMakeLists.txt b/main/Application/Manager/Network/VISA/CMakeLists.txt deleted file mode 100644 index e871406..0000000 --- a/main/Application/Manager/Network/VISA/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register( - SRCS "visa_server.cpp" "visa_commands.cpp" - INCLUDE_DIRS "." - REQUIRES lwip freertos esp_timer -) diff --git a/main/Application/Manager/Network/VISA/visa_commands.cpp b/main/Application/Manager/Network/VISA/Private/visaCommands.cpp similarity index 94% rename from main/Application/Manager/Network/VISA/visa_commands.cpp rename to main/Application/Manager/Network/VISA/Private/visaCommands.cpp index 35dab89..217b109 100644 --- a/main/Application/Manager/Network/VISA/visa_commands.cpp +++ b/main/Application/Manager/Network/VISA/Private/visaCommands.cpp @@ -1,23 +1,24 @@ /* - * visa_commands.cpp + * visaCommands.cpp * - * Copyright (C) 2026 - * This file is part of PyroVision. + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: VISA commands implementation. * - * PyroVision is free software: you can redistribute it and/or modify + * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * PyroVision is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with PyroVision. If not, see . + * along with this program. If not, see . * - * File info: VISA/SCPI command handler implementation. + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ #include @@ -28,7 +29,7 @@ #include #include -#include "visa_commands.h" +#include "visaCommands.h" #include "sdkconfig.h" @@ -121,7 +122,7 @@ static int VISA_CMD_RST(char *Response, size_t MaxLen) */ static int VISA_CMD_CLS(char *Response, size_t MaxLen) { - VISA_Commands_ClearErrors(); + VISACommands_ClearErrors(); _operation_complete = true; return 0; /* No response */ } @@ -162,7 +163,7 @@ static int VISA_CMD_TST(char *Response, size_t MaxLen) */ static int VISA_CMD_SYST_ERR(char *Response, size_t MaxLen) { - int error = VISA_Commands_GetError(); + int error = VISACommands_GetError(); if (error == SCPI_ERROR_NO_ERROR) { return snprintf(Response, MaxLen, "0,\"No error\"\n"); @@ -372,24 +373,24 @@ static int VISA_CMD_DISP_LED_BRIG(char **Tokens, int Count, char *Response, size return 0; /* Success */ } -esp_err_t VISA_Commands_Init(void) +esp_err_t VISACommands_Init(void) { - VISA_Commands_ClearErrors(); + VISACommands_ClearErrors(); _operation_complete = true; ESP_LOGI(TAG, "VISA command handler initialized"); return ESP_OK; } -esp_err_t VISA_Commands_Deinit(void) +esp_err_t VISACommands_Deinit(void) { - VISA_Commands_ClearErrors(); + VISACommands_ClearErrors(); ESP_LOGI(TAG, "VISA command handler deinitialized"); return ESP_OK; } -int VISA_Commands_Execute(const char *Command, char *Response, size_t MaxLen) +int VISACommands_Execute(const char *Command, char *Response, size_t MaxLen) { if ((Command == NULL) || (Response == NULL)) { return SCPI_ERROR_COMMAND_ERROR; @@ -486,7 +487,7 @@ int VISA_Commands_Execute(const char *Command, char *Response, size_t MaxLen) return SCPI_ERROR_UNDEFINED_HEADER; } -int VISA_Commands_GetError(void) +int VISACommands_GetError(void) { if (_error_count > 0) { int error = _error_queue[0]; @@ -503,7 +504,7 @@ int VISA_Commands_GetError(void) return SCPI_ERROR_NO_ERROR; } -void VISA_Commands_ClearErrors(void) +void VISACommands_ClearErrors(void) { _error_count = 0; memset(_error_queue, 0, sizeof(_error_queue)); diff --git a/main/Application/Manager/Network/VISA/visa_commands.h b/main/Application/Manager/Network/VISA/Private/visaCommands.h similarity index 79% rename from main/Application/Manager/Network/VISA/visa_commands.h rename to main/Application/Manager/Network/VISA/Private/visaCommands.h index 91b14de..16d45bc 100644 --- a/main/Application/Manager/Network/VISA/visa_commands.h +++ b/main/Application/Manager/Network/VISA/Private/visaCommands.h @@ -1,23 +1,24 @@ /* - * visa_commands.h + * visaCommands.h * - * Copyright (C) 2026 - * This file is part of PyroVision. + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: VISA commands implementation. * - * PyroVision is free software: you can redistribute it and/or modify + * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * PyroVision is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with PyroVision. If not, see . + * along with this program. If not, see . * - * File info: VISA/SCPI command handler for PyroVision thermal camera. + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ #ifndef VISA_COMMANDS_H_ @@ -49,12 +50,12 @@ /** @brief Initialize command handler * @return ESP_OK on success, error code otherwise */ -esp_err_t VISA_Commands_Init(void); +esp_err_t VISACommands_Init(void); /** @brief Deinitialize command handler * @return ESP_OK on success, error code otherwise */ -esp_err_t VISA_Commands_Deinit(void); +esp_err_t VISACommands_Deinit(void); /** @brief Execute VISA/SCPI command * @param Command Command string @@ -62,15 +63,15 @@ esp_err_t VISA_Commands_Deinit(void); * @param MaxLen Maximum response length * @return Response length or error code */ -int VISA_Commands_Execute(const char *Command, char *Response, size_t MaxLen); +int VISACommands_Execute(const char *Command, char *Response, size_t MaxLen); /** @brief Get last error from error queue * @return Error code */ -int VISA_Commands_GetError(void); +int VISACommands_GetError(void); /** @brief Clear error queue */ -void VISA_Commands_ClearErrors(void); +void VISACommands_ClearErrors(void); #endif /* VISA_COMMANDS_H_ */ diff --git a/main/Application/Manager/Network/VISA/README.md b/main/Application/Manager/Network/VISA/README.md deleted file mode 100644 index 5fcbfb8..0000000 --- a/main/Application/Manager/Network/VISA/README.md +++ /dev/null @@ -1,554 +0,0 @@ -# PyroVision VISA Interface - -## Overview - -The VISA (Virtual Instrument Software Architecture) interface provides standardized instrument control for the PyroVision thermal camera over TCP/IP. This implementation follows SCPI (Standard Commands for Programmable Instruments) conventions and IEEE 488.2 standards, enabling integration with test automation systems like LabVIEW, MATLAB, or Python-VISA. - -## Features - -- **TCP/IP Communication**: Standard VISA/SCPI port 5025 -- **IEEE 488.2 Compliance**: Mandatory common commands implemented -- **SCPI Command Structure**: Hierarchical command tree with queries -- **Binary Data Transfer**: IEEE 488.2 definite length arbitrary block format -- **Error Management**: SCPI error queue with standard error codes -- **Thermal Camera Control**: Device-specific commands for imaging -- **Multiple Clients**: Support for up to 4 concurrent connections - -## Network Configuration - -- **Default Port**: 5025 (configurable in `visa_server.h`) -- **Protocol**: TCP/IP -- **Encoding**: ASCII text for commands, binary for image data -- **Termination**: Commands terminated with newline (`\n`) -- **Timeout**: 5000 ms (configurable) - -## Command Reference - -### IEEE 488.2 Common Commands - -All commands are case-insensitive. Long form and short form are both supported (e.g., `SYSTem` or `SYST`). - -#### `*IDN?` - Identification Query - -Returns device identification string. - -**Response Format**: `Manufacturer,Model,SerialNumber,FirmwareVersion` - -**Example**: - -```sh -*IDN? -PyroVision,ThermalCam-ESP32,0000001,1.0.0 -``` - -#### `*RST` - Reset - -Resets the device to default state. - -**Example**: - -```sh -*RST -``` - -#### `*CLS` - Clear Status - -Clears the status data structures and error queue. - -**Example**: - -```sh -*CLS -``` - -#### `*OPC?` - Operation Complete Query - -Returns 1 when all pending operations are complete. - -**Response**: `1` or `0` - -**Example**: - -```sh -*OPC? -1 -``` - -#### `*TST?` - Self-Test Query - -Performs device self-test. Returns 0 for pass, non-zero for failure. - -**Example**: - -```sh -*TST? -0 -``` - -### SCPI System Commands - -#### `SYSTem:ERRor?` - Error Query - -Returns the oldest error from the error queue. - -**Response Format**: `ErrorCode,"ErrorMessage"` - -**Example**: - -```sh -SYST:ERR? -0,"No error" -``` - -#### `SYSTem:VERSion?` - SCPI Version Query - -Returns the SCPI version supported. - -**Response**: `1999.0` (SCPI-99) - -**Example**: - -```sh -SYST:VERS? -1999.0 -``` - -### Sensor Commands - -#### `SENSe:TEMPerature?` - Temperature Query - -Returns the thermal sensor temperature in Celsius. - -**Response**: Floating point temperature value - -**Example**: - -```sh -SENS:TEMP? -25.50 -``` - -#### `SENSe:IMAGE:CAPTure` - Capture Image - -Triggers image capture. Operation completes asynchronously. - -**Example**: - -```sh -SENS:IMG:CAPT -``` - -#### `SENSe:IMAGE:DATA?` - Image Data Query - -Returns the captured image in binary format using IEEE 488.2 definite length arbitrary block format. - -**Response Format**: `#` where: - -- `n` = number of digits in length -- `length` = byte count of data -- `data` = binary image data - -**Example**: - -```sh -SENS:IMG:DATA? -#41024 -``` - -(Header `#41024` means 4 digits, 1024 bytes of data follows) - -#### `SENSe:IMAGE:FORMat {JPEG|PNG|RAW}` - Set Image Format - -Sets the format for captured images. - -**Parameters**: - -- `JPEG`: JPEG compressed format -- `PNG`: PNG compressed format -- `RAW`: Raw thermal data (16-bit) - -**Example**: - -```sh -SENS:IMG:FORM JPEG -``` - -#### `SENSe:IMAGE:PALette {IRON|GRAY|RAINBOW}` - Set Color Palette - -Sets the color palette for thermal image visualization. - -**Parameters**: - -- `IRON`: Ironbow palette (thermal imaging standard) -- `GRAY`: Grayscale palette -- `RAINBOW`: Rainbow palette - -**Example**: - -```sh -SENS:IMG:PAL IRON -``` - -### Display Commands - -#### `DISPlay:LED:STATe {ON|OFF|BLINK}` - LED Control - -Controls the status LED. - -**Parameters**: - -- `ON`: LED continuously on -- `OFF`: LED off -- `BLINK`: LED blinking - -**Example**: - -```sh -DISP:LED:STAT ON -``` - -#### `DISPlay:LED:BRIGhtness <0-255>` - LED Brightness - -Sets the LED brightness level. - -**Parameters**: Integer value 0-255 (0=off, 255=maximum) - -**Example**: - -```sh -DISP:LED:BRIG 128 -``` - -## Error Codes - -Standard SCPI error codes are used: - -| Code | Description | -|------|-------------| -| 0 | No error | -| -100 | Command error | -| -101 | Invalid character | -| -102 | Syntax error | -| -103 | Invalid separator | -| -104 | Data type error | -| -108 | Parameter not allowed | -| -109 | Missing parameter | -| -110 | Command header error | -| -113 | Undefined header | -| -200 | Execution error | -| -222 | Data out of range | -| -240 | Hardware error | -| -241 | Hardware missing | -| -300 | System error | -| -350 | Out of memory | -| -400 | Query error | - -## Usage Examples - -### Python with PyVISA - -```python -import pyvisa - -rm = pyvisa.ResourceManager() -# Connect to PyroVision camera -camera = rm.open_resource('TCPIP::192.168.4.1::5025::SOCKET') -camera.read_termination = '\n' -camera.write_termination = '\n' - -# Identify device -idn = camera.query('*IDN?') -print(f"Connected to: {idn}") - -# Set image format -camera.write('SENS:IMG:FORM JPEG') - -# Set color palette -camera.write('SENS:IMG:PAL IRON') - -# Capture image -camera.write('SENS:IMG:CAPT') - -# Wait for operation complete -while camera.query('*OPC?') != '1': - time.sleep(0.1) - -# Get image data (binary) -camera.write('SENS:IMG:DATA?') -image_data = camera.read_raw() - -# Parse IEEE 488.2 block format -# Skip header (#) -header_start = image_data.find(b'#') -n = int(chr(image_data[header_start + 1])) -length = int(image_data[header_start + 2:header_start + 2 + n]) -data = image_data[header_start + 2 + n:header_start + 2 + n + length] - -# Save image -with open('thermal_image.jpg', 'wb') as f: - f.write(data) - -# Check for errors -error = camera.query('SYST:ERR?') -print(f"Error status: {error}") - -camera.close() -``` - -### Python with Sockets - -```python -import socket -import time - -# Connect to camera -sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -sock.connect(('192.168.4.1', 5025)) -sock.settimeout(5.0) - -def send_command(sock, command): - sock.sendall((command + '\n').encode()) - -def read_response(sock): - data = b'' - while True: - chunk = sock.recv(1024) - data += chunk - if b'\n' in chunk: - break - return data.decode().strip() - -# Identify device -send_command(sock, '*IDN?') -response = read_response(sock) -print(f"Device: {response}") - -# Get temperature -send_command(sock, 'SENS:TEMP?') -temp = read_response(sock) -print(f"Temperature: {temp}°C") - -# Control LED -send_command(sock, 'DISP:LED:STAT BLINK') -send_command(sock, 'DISP:LED:BRIG 200') - -sock.close() -``` - -### MATLAB - -```matlab -% Connect to camera -t = tcpclient('192.168.4.1', 5025); -configureTerminator(t, 'LF'); - -% Identify device -writeline(t, '*IDN?'); -idn = readline(t); -disp(['Connected to: ', idn]); - -% Get temperature -writeline(t, 'SENS:TEMP?'); -temp = str2double(readline(t)); -fprintf('Temperature: %.2f°C\n', temp); - -% Capture image -writeline(t, 'SENS:IMG:CAPT'); - -% Wait for completion -writeline(t, '*OPC?'); -while str2double(readline(t)) ~= 1 - pause(0.1); -end - -% Get image data -writeline(t, 'SENS:IMG:DATA?'); -data = read(t); - -% Parse IEEE 488.2 block format -header_idx = find(data == uint8('#'), 1); -n = data(header_idx + 1) - uint8('0'); -length = str2double(char(data(header_idx + 2:header_idx + 1 + n))); -img_data = data(header_idx + 2 + n:header_idx + 1 + n + length); - -% Save image -fid = fopen('thermal_image.jpg', 'wb'); -fwrite(fid, img_data, 'uint8'); -fclose(fid); - -clear t; -``` - -### LabVIEW - -1. Use **VISA TCP/IP Resource** with format: `TCPIP::192.168.4.1::5025::SOCKET` -2. Use **VISA Write** to send commands -3. Use **VISA Read** to receive responses -4. Set termination character to `\n` (0x0A) -5. For binary data, use **VISA Read** in binary mode - -## Integration with Firmware - -To integrate the VISA server with your application: - -### 1. Include Headers - -```cpp -#include "Manager/Network/VISA/visa_server.h" -``` - -### 2. Initialize Server - -```cpp -// During application initialization -esp_err_t err = VISA_Server_Init(); -if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize VISA server"); -} -``` - -### 3. Start Server - -```cpp -// After network is connected -err = VISA_Server_Start(); -if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to start VISA server"); -} -``` - -### 4. Stop Server (if needed) - -```cpp -// Before shutdown or network disconnect -VISA_Server_Stop(); -``` - -### 5. Deinitialize - -```cpp -// During application cleanup -VISA_Server_Deinit(); -``` - -### CMake Integration - -Add to your main component's `CMakeLists.txt`: - -```cmake -idf_component_register( - SRCS "main.cpp" ... - INCLUDE_DIRS "." ... - REQUIRES ... visa_interface -) -``` - -## Customization - -### Adding New Commands - -1. Define command handler in `visa_commands.cpp`: - -```cpp -static int VISA_CMD_MY_COMMAND(char *Response, size_t MaxLen) -{ - // Implement command logic - return snprintf(Response, MaxLen, "Result\n"); -} -``` - -2. Add command to parser in `VISA_Commands_Execute()`: - -```cpp -else if (strcasecmp(tokens[0], "MYCommand") == 0) { - return VISA_CMD_MY_COMMAND(Response, MaxLen); -} -``` - -### Modifying Port - -Edit `VISA_SERVER_PORT` in `visa_server.h`: - -```cpp -#define VISA_SERVER_PORT 5555 // Custom port -``` - -### Adjusting Timeouts - -Edit `VISA_SOCKET_TIMEOUT_MS` in `visa_server.h`: - -```cpp -#define VISA_SOCKET_TIMEOUT_MS 10000 // 10 seconds -``` - -## Troubleshooting - -### Cannot Connect - -- Verify network connectivity: `ping 192.168.4.1` -- Check firewall settings -- Confirm server is running: Check logs for "VISA server listening" -- Verify correct port (default: 5025) - -### Commands Not Responding - -- Ensure commands are terminated with newline `\n` -- Check command syntax (case-insensitive) -- Query error queue: `SYST:ERR?` -- Enable debug logs in `visa_server.cpp` and `visa_commands.cpp` - -### Binary Data Issues - -- Verify IEEE 488.2 block format parsing -- Check data length matches header -- Use binary read mode, not text mode -- Ensure sufficient buffer size - -### Performance Optimization - -- Reduce `VISA_SOCKET_TIMEOUT_MS` for faster response -- Increase task stack size if needed -- Use binary format for large data transfers -- Consider caching frequently requested data - -## Protocol Specification - -### Command Format - -```sh -
[][\n] -``` - -- Header: Hierarchical command path separated by colons -- Parameter: Optional command argument -- Terminator: Newline character (0x0A) - -### Query Format - -```sh -
?[\n] -``` - -- Query: Header followed by question mark - -### Response Format - -```sh -[\n] -``` - -- Text responses terminated with newline -- Binary data uses IEEE 488.2 block format - -### IEEE 488.2 Block Format - -```sh -# -``` - -- `#`: Start marker -- `n`: Single digit, number of digits in length -- `length`: ASCII decimal length value -- `data`: Binary data bytes - -**Example**: `#41024<1024 bytes>` means 4 digits, 1024 bytes follow diff --git a/main/Application/Manager/Network/VISA/visa_server.cpp b/main/Application/Manager/Network/VISA/visaServer.cpp similarity index 91% rename from main/Application/Manager/Network/VISA/visa_server.cpp rename to main/Application/Manager/Network/VISA/visaServer.cpp index 057f2af..05d0c78 100644 --- a/main/Application/Manager/Network/VISA/visa_server.cpp +++ b/main/Application/Manager/Network/VISA/visaServer.cpp @@ -1,23 +1,24 @@ /* - * visa_server.cpp + * visaServer.cpp * - * Copyright (C) 2026 - * This file is part of PyroVision. + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: VISA server implementation. * - * PyroVision is free software: you can redistribute it and/or modify + * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * PyroVision is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with PyroVision. If not, see . + * along with this program. If not, see . * - * File info: VISA (Virtual Instrument Software Architecture) TCP server implementation. + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ #include @@ -31,8 +32,8 @@ #include #include -#include "visa_server.h" -#include "visa_commands.h" +#include "visaServer.h" +#include "Private/visaCommands.h" static const char *TAG = "VISA-Server"; @@ -55,6 +56,8 @@ static VISA_Server_State_t _VISA_Server_State = {0}; */ static int VISA_ProcessCommand(const char *Command, char *Response, size_t MaxLen) { + char cmd_buffer[VISA_MAX_COMMAND_LENGTH]; + if ((Command == NULL) || (Response == NULL)) { return VISA_ERR_INVALID_ARG; } @@ -62,7 +65,6 @@ static int VISA_ProcessCommand(const char *Command, char *Response, size_t MaxLe ESP_LOGD(TAG, "Processing command: %s", Command); /* Remove trailing newline/carriage return */ - char cmd_buffer[VISA_MAX_COMMAND_LENGTH]; strncpy(cmd_buffer, Command, sizeof(cmd_buffer) - 1); cmd_buffer[sizeof(cmd_buffer) - 1] = '\0'; @@ -72,7 +74,7 @@ static int VISA_ProcessCommand(const char *Command, char *Response, size_t MaxLe } /* Process command */ - return VISA_Commands_Execute(cmd_buffer, Response, MaxLen); + return VISACommands_Execute(cmd_buffer, Response, MaxLen); } /** @brief Handle client connection @@ -102,10 +104,13 @@ static void VISA_HandleClient(int ClientSocket) /* Timeout, continue */ continue; } - ESP_LOGE(TAG, "recv failed: errno %d", errno); + + ESP_LOGE(TAG, "recv failed: errno %d!", errno); + break; } else if (len == 0) { ESP_LOGI(TAG, "Client disconnected"); + break; } @@ -209,7 +214,7 @@ static void VISA_ServerTask(void *p_Args) vTaskDelete(NULL); } -esp_err_t VISA_Server_Init(void) +esp_err_t VISAServer_Init(void) { esp_err_t Error; @@ -227,7 +232,7 @@ esp_err_t VISA_Server_Init(void) } /* Initialize command handler */ - Error = VISA_Commands_Init(); + Error = VISACommands_Init(); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize command handler: 0x%x!", Error); vSemaphoreDelete(_VISA_Server_State.Mutex); @@ -242,15 +247,15 @@ esp_err_t VISA_Server_Init(void) return ESP_OK; } -esp_err_t VISA_Server_Deinit(void) +esp_err_t VISAServer_Deinit(void) { if (_VISA_Server_State.isInitialized == false) { return ESP_OK; } - VISA_Server_Stop(); + VISAServer_Stop(); - VISA_Commands_Deinit(); + VISACommands_Deinit(); if (_VISA_Server_State.Mutex != NULL) { vSemaphoreDelete(_VISA_Server_State.Mutex); @@ -264,12 +269,12 @@ esp_err_t VISA_Server_Deinit(void) return ESP_OK; } -bool VISA_Server_IsRunning(void) +bool VISAServer_isRunning(void) { return _VISA_Server_State.isRunning; } -esp_err_t VISA_Server_Start(void) +esp_err_t VISAServer_Start(void) { if (_VISA_Server_State.isInitialized == false) { ESP_LOGE(TAG, "Not initialized!"); @@ -309,7 +314,7 @@ esp_err_t VISA_Server_Start(void) return ESP_OK; } -esp_err_t VISA_Server_Stop(void) +esp_err_t VISAServer_Stop(void) { if (_VISA_Server_State.isRunning == false) { return ESP_OK; diff --git a/main/Application/Manager/Network/VISA/visa_server.h b/main/Application/Manager/Network/VISA/visaServer.h similarity index 73% rename from main/Application/Manager/Network/VISA/visa_server.h rename to main/Application/Manager/Network/VISA/visaServer.h index b13df07..0ec0808 100644 --- a/main/Application/Manager/Network/VISA/visa_server.h +++ b/main/Application/Manager/Network/VISA/visaServer.h @@ -1,23 +1,24 @@ /* - * visa_server.h + * visaServer.h * - * Copyright (C) 2026 - * This file is part of PyroVision. + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: VISA server implementation. * - * PyroVision is free software: you can redistribute it and/or modify + * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * PyroVision is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with PyroVision. If not, see . + * along with this program. If not, see . * - * File info: VISA (Virtual Instrument Software Architecture) TCP server for PyroVision thermal camera. + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ #ifndef VISA_SERVER_H_ @@ -46,29 +47,29 @@ typedef enum { VISA_ERR_NOT_INITIALIZED = -7, /**< Server not initialized */ } VISA_Error_t; -/** @brief Initialize VISA server +/** @brief Initialize VISA server. * @return VISA_OK on success, error code otherwise */ -esp_err_t VISA_Server_Init(void); +esp_err_t VISAServer_Init(void); -/** @brief Deinitialize VISA server +/** @brief Deinitialize VISA server. * @return VISA_OK on success, error code otherwise */ -esp_err_t VISA_Server_Deinit(void); +esp_err_t VISAServer_Deinit(void); /** @brief Check if VISA server is running * @return true if running, false otherwise */ -bool VISA_Server_IsRunning(void); +bool VISAServer_isRunning(void); -/** @brief Start VISA server +/** @brief Start VISA server. * @return VISA_OK on success, error code otherwise */ -esp_err_t VISA_Server_Start(void); +esp_err_t VISAServer_Start(void); -/** @brief Stop VISA server +/** @brief Stop VISA server. * @return VISA_OK on success, error code otherwise */ -esp_err_t VISA_Server_Stop(void); +esp_err_t VISAServer_Stop(void); #endif /* VISA_SERVER_H_ */ diff --git a/main/Application/Manager/Network/networkManager.cpp b/main/Application/Manager/Network/networkManager.cpp index daf9cbd..5c4cb6e 100644 --- a/main/Application/Manager/Network/networkManager.cpp +++ b/main/Application/Manager/Network/networkManager.cpp @@ -34,7 +34,7 @@ #include -#include "network_types.h" +#include "networkTypes.h" #include "Server/server.h" #include "Provisioning/provisioning.h" diff --git a/main/Application/Manager/Network/networkManager.h b/main/Application/Manager/Network/networkManager.h index 67c30cf..742a5bc 100644 --- a/main/Application/Manager/Network/networkManager.h +++ b/main/Application/Manager/Network/networkManager.h @@ -28,7 +28,7 @@ #include #include -#include "network_types.h" +#include "networkTypes.h" #include "SNTP/sntp.h" #include "Server/server.h" #include "Provisioning/provisioning.h" diff --git a/main/Application/Manager/Network/network_types.h b/main/Application/Manager/Network/networkTypes.h similarity index 98% rename from main/Application/Manager/Network/network_types.h rename to main/Application/Manager/Network/networkTypes.h index d1e7620..18e5d7c 100644 --- a/main/Application/Manager/Network/network_types.h +++ b/main/Application/Manager/Network/networkTypes.h @@ -192,7 +192,7 @@ typedef struct { */ typedef struct { - char DeviceName[32]; + char Name[32]; char PoP[32]; uint32_t Timeout; } Network_Provisioning_Config_t; @@ -203,7 +203,6 @@ typedef struct { Network_WiFi_Credentials_t Credentials; uint8_t MaxRetries; uint16_t RetryInterval; - Network_Provisioning_Config_t ProvConfig; } Network_WiFi_STA_Config_t; /** @brief Server configuration. diff --git a/main/Application/Manager/SD/sdManager.cpp b/main/Application/Manager/SD/sdManager.cpp index ef368b9..38f125d 100644 --- a/main/Application/Manager/SD/sdManager.cpp +++ b/main/Application/Manager/SD/sdManager.cpp @@ -39,7 +39,6 @@ #include #include "sdManager.h" -#include "Application/bitmap.h" #include "Application/application.h" #include "Application/Manager/Devices/SPI/spi.h" @@ -251,86 +250,11 @@ esp_err_t SDManager_Deinit(void) return ESP_OK; } -bool SDManager_IsCardPresent(void) +bool SDManager_isCardPresent(void) { return _SD_Manager_State.CardPresent; } -esp_err_t SDManager_SaveBitmap(const char *p_Path, uint16_t Width, uint16_t Height, const uint8_t *p_Buffer, - uint32_t Length) -{ - esp_err_t Error; - Bitmap_BMP_Header_t Header; - Bitmap_DIB_Header_t InfoHeader; - - if (_SD_Manager_State.CardPresent == false) { - return ESP_ERR_INVALID_STATE; - } - - if ((p_Path == NULL) || (p_Buffer == NULL)) { - return ESP_ERR_INVALID_ARG; - } - - /* Prepare bitmap headers */ - memset(&Header, 0, sizeof(Header)); - memset(&InfoHeader, 0, sizeof(InfoHeader)); - - Header.bType = BITMAP_MAGIC; - Header.bReserved = 0; - Header.bfSize = sizeof(Header) + sizeof(InfoHeader) + Length; - Header.bfOffBits = sizeof(Header) + sizeof(InfoHeader); - - InfoHeader.biSize = sizeof(InfoHeader); - InfoHeader.biWidth = Width; - InfoHeader.biHeight = Height; - InfoHeader.biPlanes = 1; - InfoHeader.biBitCount = 24; - InfoHeader.biCompression = BITMAP_COMP_RGB; - InfoHeader.biSizeImage = Length; - InfoHeader.biXPelsPerMeter = 0; - InfoHeader.biYPelsPerMeter = 0; - InfoHeader.biClrUsed = 0; - InfoHeader.biClrImportant = 0; - - ESP_LOGI(TAG, "Saving bitmap to %s", p_Path); - - /* Open file for writing */ - FILE *f = fopen(p_Path, "wb"); - if (f == NULL) { - ESP_LOGE(TAG, "Failed to open file for writing: %s!", p_Path); - return ESP_FAIL; - } - - /* Write bitmap file header */ - if (fwrite(&Header, sizeof(uint8_t), sizeof(Header), f) != sizeof(Header)) { - ESP_LOGE(TAG, "Failed to write file header: %s!", p_Path); - Error = ESP_FAIL; - goto SDManager_SaveBitmap_Exit; - } - - /* Write DIB header */ - if (fwrite(&InfoHeader, sizeof(uint8_t), sizeof(InfoHeader), f) != sizeof(InfoHeader)) { - ESP_LOGE(TAG, "Failed to write DIB header: %s!", p_Path); - Error = ESP_FAIL; - goto SDManager_SaveBitmap_Exit; - } - - /* Write image data */ - if (fwrite(p_Buffer, sizeof(uint8_t), Length, f) != Length) { - ESP_LOGE(TAG, "Failed to write image data: %s!", p_Path); - Error = ESP_FAIL; - goto SDManager_SaveBitmap_Exit; - } - - ESP_LOGI(TAG, "Bitmap saved successfully"); - Error = ESP_OK; - -SDManager_SaveBitmap_Exit: - fclose(f); - - return Error; -} - /** @brief Background task for mounting SD card (prevents GUI blocking). * @param arg Unused */ diff --git a/main/Application/Manager/SD/sdManager.h b/main/Application/Manager/SD/sdManager.h index 490b95d..4746f1b 100644 --- a/main/Application/Manager/SD/sdManager.h +++ b/main/Application/Manager/SD/sdManager.h @@ -57,18 +57,7 @@ esp_err_t SDManager_Deinit(void); /** @brief Check if SD card is currently present and mounted. * @return true if card is present and mounted, false otherwise */ -bool SDManager_IsCardPresent(void); - -/** @brief Save a bitmap image to the SD card. - * @param p_Path Path to save the bitmap file (relative to mount point) - * @param Width Image width in pixels - * @param Height Image height in pixels - * @param p_Buffer Pointer to RGB888 image buffer - * @param Length Buffer length in bytes - * @return ESP_OK on success - */ -esp_err_t SDManager_SaveBitmap(const char *p_Path, uint16_t Width, uint16_t Height, const uint8_t *p_Buffer, - uint32_t Length); +bool SDManager_isCardPresent(void); /** @brief Mount the SD card. * @return ESP_OK on success diff --git a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp new file mode 100644 index 0000000..f7e45cf --- /dev/null +++ b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp @@ -0,0 +1,159 @@ +/* + * settingsDefaultLoader.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Default settings loader implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include + +#include +#include + +#include + +#include "settingsLoader.h" +#include "../settingsManager.h" + +static const char *TAG = "settings_default_loader"; + +void SettingsManager_InitDefaultLeptonROIs(App_Settings_t *p_Settings) +{ + /* Spotmeter defaults */ + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].Type = ROI_TYPE_SPOTMETER; + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].x = 60; + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].y = 40; + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].w = 40; + p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].h = 40; + + /* Scene statistics defaults */ + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].Type = ROI_TYPE_SCENE; + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].x = 0; + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].y = 0; + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].w = 160; + p_Settings->Lepton.ROI[ROI_TYPE_SCENE].h = 120; + + /* AGC defaults */ + p_Settings->Lepton.ROI[ROI_TYPE_AGC].Type = ROI_TYPE_AGC; + p_Settings->Lepton.ROI[ROI_TYPE_AGC].x = 0; + p_Settings->Lepton.ROI[ROI_TYPE_AGC].y = 0; + p_Settings->Lepton.ROI[ROI_TYPE_AGC].w = 160; + p_Settings->Lepton.ROI[ROI_TYPE_AGC].h = 120; + + /* Video focus defaults */ + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].Type = ROI_TYPE_VIDEO_FOCUS; + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].x = 1; + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].y = 1; + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].w = 157; + p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].h = 157; +} + +void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settings) +{ + /* No emissiviy values available */ + p_Settings->Lepton.EmissivityCount = 1; + p_Settings->Lepton.EmissivityPresets[0].Value = 100.0f; + strncpy(p_Settings->Lepton.EmissivityPresets[0].Description, "Unknown", sizeof(p_Settings->Lepton.EmissivityPresets[0].Description)); +} + +void SettingsManager_InitDefaults(App_Settings_t *p_Settings) +{ + memset(p_Settings, 0, sizeof(App_Settings_t)); + + SettingsManager_InitDefaultDisplay(p_Settings); + SettingsManager_InitDefaultProvisioning(p_Settings); + SettingsManager_InitDefaultWiFi(p_Settings); + SettingsManager_InitDefaultSystem(p_Settings); + SettingsManager_InitDefaultLepton(p_Settings); + SettingsManager_InitDefaultHTTPServer(p_Settings); + SettingsManager_InitDefaultVISAServer(p_Settings); +} + +void SettingsManager_InitDefaultDisplay(App_Settings_t *p_Settings) +{ + ESP_LOGW(TAG, "Loading default Display settings"); + + p_Settings->Display.Brightness = 80; + p_Settings->Display.Timeout = 0; +} + +void SettingsManager_InitDefaultProvisioning(App_Settings_t *p_Settings) +{ + ESP_LOGW(TAG, "Loading default Provisioning settings"); + + p_Settings->Provisioning.Timeout = 300; + strncpy(p_Settings->Provisioning.Name, "PyroVision-Provision", sizeof(p_Settings->Provisioning.Name)); + strncpy(p_Settings->Provisioning.PoP, "pyrovision", sizeof(p_Settings->Provisioning.PoP)); +} + +void SettingsManager_InitDefaultWiFi(App_Settings_t *p_Settings) +{ + ESP_LOGW(TAG, "Loading default WiFi settings"); + + p_Settings->WiFi.AutoConnect = true; + p_Settings->WiFi.MaxRetries = 5; + p_Settings->WiFi.RetryInterval = 2000; + strncpy(p_Settings->WiFi.SSID, "", sizeof(p_Settings->WiFi.SSID)); + strncpy(p_Settings->WiFi.Password, "", sizeof(p_Settings->WiFi.Password)); +} + +void SettingsManager_InitDefaultSystem(App_Settings_t *p_Settings) +{ + uint8_t Mac[6]; + + ESP_LOGW(TAG, "Loading default System settings"); + + if (esp_efuse_mac_get_default(Mac) == ESP_OK) { + snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision-%02X%02X%02X%02X%02X%02X", + Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]); + } else { + snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision"); + ESP_LOGW(TAG, "Failed to get MAC address, using default name"); + } + + p_Settings->System.SDCard_AutoMount = true; + p_Settings->System.Bluetooth_Enabled = false; + strncpy(p_Settings->System.Timezone, "CET-1CEST,M3.5.0,M10.5.0/3", sizeof(p_Settings->System.Timezone)); +} + +void SettingsManager_InitDefaultLepton(App_Settings_t *p_Settings) +{ + ESP_LOGW(TAG, "Loading default Lepton settings"); + + SettingsManager_InitDefaultLeptonROIs(p_Settings); + SettingsManager_InitDefaultLeptonEmissivityPresets(p_Settings); +} + +void SettingsManager_InitDefaultHTTPServer(App_Settings_t *p_Settings) +{ + ESP_LOGW(TAG, "Loading default HTTP Server settings"); + + p_Settings->HTTPServer.Port = 80; + p_Settings->HTTPServer.WSPingIntervalSec = 30; + p_Settings->HTTPServer.MaxClients = 4; +} + +void SettingsManager_InitDefaultVISAServer(App_Settings_t *p_Settings) +{ + ESP_LOGW(TAG, "Loading default VISA Server settings"); + + p_Settings->VISAServer.Port = 5025; +} \ No newline at end of file diff --git a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp new file mode 100644 index 0000000..f2abe5b --- /dev/null +++ b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp @@ -0,0 +1,405 @@ +/* + * settingsJSONLoader.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: JSON settings loader for factory defaults. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include + +#include +#include +#include + +#include "settingsLoader.h" +#include "../settingsManager.h" + +static const char *TAG = "settings_json_loader"; + +/** @brief + * @param p_State + * @param p_JSON + */ +static void SettingsManager_LoadLepton(SettingsManager_State_t *p_State, const cJSON *p_JSON) +{ + cJSON *lepton = NULL; + cJSON *emissivity_array = NULL; + cJSON *roi_array = NULL; + + lepton = cJSON_GetObjectItem(p_JSON, "lepton"); + if (lepton != NULL) { + emissivity_array = cJSON_GetObjectItem(lepton, "emissivity"); + if (cJSON_IsArray(emissivity_array)) { + p_State->Settings.Lepton.EmissivityCount = cJSON_GetArraySize(emissivity_array); + + ESP_LOGD(TAG, "Found %d emissivity presets in JSON", p_State->Settings.Lepton.EmissivityCount); + + for (uint32_t i = 0; i < p_State->Settings.Lepton.EmissivityCount; i++) { + cJSON *preset = cJSON_GetArrayItem(emissivity_array, i); + cJSON *name = cJSON_GetObjectItem(preset, "name"); + cJSON *value = cJSON_GetObjectItem(preset, "value"); + + if (cJSON_IsString(name) && cJSON_IsNumber(value)) { + p_State->Settings.Lepton.EmissivityPresets[i].Value = (float)(value->valuedouble); + + /* Cap the emissivity value between 0 and 100 */ + if (p_State->Settings.Lepton.EmissivityPresets[i].Value < 0.0f) { + p_State->Settings.Lepton.EmissivityPresets[i].Value = 0.0f; + } else if (p_State->Settings.Lepton.EmissivityPresets[i].Value > 100.0f) { + p_State->Settings.Lepton.EmissivityPresets[i].Value = 100.0f; + } + + memset(p_State->Settings.Lepton.EmissivityPresets[i].Description, 0, + sizeof(p_State->Settings.Lepton.EmissivityPresets[i].Description)); + strncpy(p_State->Settings.Lepton.EmissivityPresets[i].Description, name->valuestring, + sizeof(p_State->Settings.Lepton.EmissivityPresets[i].Description)); + + ESP_LOGD(TAG, " Preset %d: %s = %.2f", i, name->valuestring, value->valuedouble); + } + } + } else { + SettingsManager_InitDefaultLeptonEmissivityPresets(&p_State->Settings); + } + + roi_array = cJSON_GetObjectItem(lepton, "roi"); + if (cJSON_IsArray(roi_array)) { + } else { + SettingsManager_InitDefaultLeptonROIs(&p_State->Settings); + } + } else { + SettingsManager_InitDefaultLepton(&p_State->Settings); + } +} + +/** @brief + * @param p_State + * @param p_JSON + */ +static void SettingsManager_LoadDisplay(SettingsManager_State_t *p_State, const cJSON *p_JSON) +{ + cJSON *display = NULL; + + display = cJSON_GetObjectItem(p_JSON, "display"); + if (display != NULL) { + cJSON *brightness = cJSON_GetObjectItem(display, "brightness"); + if (cJSON_IsNumber(brightness)) { + p_State->Settings.Display.Brightness = (uint8_t)(brightness->valueint); + } + + cJSON *timeout = cJSON_GetObjectItem(display, "timeout"); + if (cJSON_IsNumber(timeout)) { + p_State->Settings.Display.Timeout = (uint16_t)(timeout->valueint); + } + } else { + SettingsManager_InitDefaultDisplay(&p_State->Settings); + } +} + +/** @brief + * @param p_State + * @param p_JSON + */ +static void SettingsManager_LoadWiFi(SettingsManager_State_t *p_State, const cJSON *p_JSON) +{ + cJSON *wifi = NULL; + + wifi = cJSON_GetObjectItem(p_JSON, "wifi"); + if (wifi != NULL) { + cJSON *maxRetries = cJSON_GetObjectItem(wifi, "maxRetries"); + if (cJSON_IsNumber(maxRetries)) { + p_State->Settings.WiFi.MaxRetries = (uint8_t)(maxRetries->valueint); + } + + cJSON *retryInterval = cJSON_GetObjectItem(wifi, "retryInterval"); + if (cJSON_IsNumber(retryInterval)) { + p_State->Settings.WiFi.RetryInterval = (uint32_t)(retryInterval->valueint); + } + + cJSON *autoConnect = cJSON_GetObjectItem(wifi, "autoConnect"); + if (cJSON_IsBool(autoConnect)) { + p_State->Settings.WiFi.AutoConnect = cJSON_IsTrue(autoConnect); + } + + cJSON *ssid = cJSON_GetObjectItem(wifi, "ssid"); + if (cJSON_IsString(ssid)) { + strncpy(p_State->Settings.WiFi.SSID, ssid->valuestring, sizeof(p_State->Settings.WiFi.SSID)); + } + + cJSON *password = cJSON_GetObjectItem(wifi, "password"); + if (cJSON_IsString(password)) { + strncpy(p_State->Settings.WiFi.Password, password->valuestring, sizeof(p_State->Settings.WiFi.Password)); + } + } else { + SettingsManager_InitDefaultWiFi(&p_State->Settings); + } +} + +/** @brief + * @param p_State + * @param p_JSON + */ +static void SettingsManager_LoadProvisioning(SettingsManager_State_t *p_State, const cJSON *p_JSON) +{ + cJSON *provisioning = NULL; + + provisioning = cJSON_GetObjectItem(p_JSON, "provisioning"); + if (provisioning != NULL) { + cJSON *name = cJSON_GetObjectItem(provisioning, "name"); + if (cJSON_IsString(name)) { + strncpy(p_State->Settings.Provisioning.Name, name->valuestring, sizeof(p_State->Settings.Provisioning.Name)); + } + + cJSON *pop = cJSON_GetObjectItem(provisioning, "pop"); + if (cJSON_IsString(pop)) { + strncpy(p_State->Settings.Provisioning.PoP, pop->valuestring, sizeof(p_State->Settings.Provisioning.PoP)); + } + + cJSON *timeout = cJSON_GetObjectItem(provisioning, "timeout"); + if (cJSON_IsNumber(timeout)) { + p_State->Settings.Provisioning.Timeout = (uint32_t)(timeout->valueint); + } + } else { + SettingsManager_InitDefaultProvisioning(&p_State->Settings); + } +} + +/** @brief + * @param p_State + * @param p_JSON + */ +static void SettingsManager_LoadSystem(SettingsManager_State_t *p_State, const cJSON *p_JSON) +{ + cJSON *system = NULL; + + system = cJSON_GetObjectItem(p_JSON, "system"); + if (system != NULL) { + cJSON *timezone = cJSON_GetObjectItem(system, "timezone"); + if (cJSON_IsString(timezone)) { + strncpy(p_State->Settings.System.Timezone, timezone->valuestring, sizeof(p_State->Settings.System.Timezone)); + } + } else { + SettingsManager_InitDefaultSystem(&p_State->Settings); + } +} + +/** @brief + * @param p_State + * @param p_JSON + */ +static void SettingsManager_LoadHTTPServer(SettingsManager_State_t *p_State, const cJSON *p_JSON) +{ + cJSON *http_server = NULL; + + http_server = cJSON_GetObjectItem(p_JSON, "http-server"); + if (http_server != NULL) { + cJSON *port = cJSON_GetObjectItem(http_server, "port"); + if (cJSON_IsNumber(port)) { + p_State->Settings.HTTPServer.Port = (uint16_t)(port->valueint); + } + + cJSON *wsPingIntervalSec = cJSON_GetObjectItem(http_server, "wsPingIntervalSec"); + if (cJSON_IsNumber(wsPingIntervalSec)) { + p_State->Settings.HTTPServer.WSPingIntervalSec = (uint16_t)(wsPingIntervalSec->valueint); + } + + cJSON *maxClients = cJSON_GetObjectItem(http_server, "maxClients"); + if (cJSON_IsNumber(maxClients)) { + p_State->Settings.HTTPServer.MaxClients = (uint8_t)(maxClients->valueint); + } + } else { + SettingsManager_InitDefaultHTTPServer(&p_State->Settings); + } +} + +/** @brief + * @param p_State + * @param p_JSON + */ +static void SettingsManager_LoadVISAServer(SettingsManager_State_t *p_State, const cJSON *p_JSON) +{ + cJSON *visa_server = NULL; + + visa_server = cJSON_GetObjectItem(p_JSON, "visa-server"); + if (visa_server != NULL) { + cJSON *port = cJSON_GetObjectItem(visa_server, "port"); + if (cJSON_IsNumber(port)) { + p_State->Settings.VISAServer.Port = (uint16_t)(port->valueint); + } + } else { + SettingsManager_InitDefaultVISAServer(&p_State->Settings); + } +} + +esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State) +{ + uint8_t ConfigLoaded = 0; + esp_err_t Error; + cJSON *json = NULL; + size_t Total = 0; + size_t Used = 0; + size_t BytesRead = 0; + FILE* SettingsFile = NULL; + char *SettingsBuffer = NULL; + long FileSize; + esp_vfs_littlefs_conf_t LittleFS_Config = { + .base_path = "/littlefs", + .partition_label = "storage", + .format_if_mount_failed = true, + .read_only = true, + .dont_mount = false + }; + + Error = nvs_get_u8(p_State->NVS_Handle, "config_loaded", &ConfigLoaded); + if ((Error == ESP_OK) && (ConfigLoaded == true)) { + ESP_LOGD(TAG, "Default config already loaded, skipping"); + //return ESP_OK; + } + + ESP_LOGD(TAG, "Initializing LittleFS"); + + Error = esp_vfs_littlefs_register(&LittleFS_Config); + if (Error != ESP_OK) { + if (Error == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount or format filesystem!"); + } else if (Error == ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to find LittleFS partition!"); + } else { + ESP_LOGE(TAG, "Failed to initialize LittleFS: %d!", Error); + } + + return ESP_FAIL; + } + + Error = esp_littlefs_info(LittleFS_Config.partition_label, &Total, &Used); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to get LittleFS partition information: %d!", Error); + } else { + ESP_LOGD(TAG, "Partition size: total: %zu, used: %zu", Total, Used); + } + + ESP_LOGD(TAG, "Opening settings file..."); + SettingsFile = fopen("/littlefs/default_settings.json", "r"); + if (SettingsFile == NULL) { + ESP_LOGE(TAG, "Failed to open file for reading!"); + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + return ESP_FAIL; + } + + /* Get file size */ + fseek(SettingsFile, 0, SEEK_END); + FileSize = ftell(SettingsFile); + fseek(SettingsFile, 0, SEEK_SET); + + if (FileSize <= 0) { + ESP_LOGE(TAG, "Invalid file size: %ld!", FileSize); + fclose(SettingsFile); + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + return ESP_FAIL; + } + + ESP_LOGD(TAG, "File size: %ld bytes", FileSize); + + /* Allocate buffer for file content */ + SettingsBuffer = (char*)heap_caps_malloc(FileSize + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (SettingsBuffer == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory for file buffer!"); + fclose(SettingsFile); + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + return ESP_ERR_NO_MEM; + } + + /* Read file content */ + BytesRead = fread(SettingsBuffer, 1, FileSize, SettingsFile); + fclose(SettingsFile); + SettingsFile = NULL; + + if (BytesRead != FileSize) { + ESP_LOGE(TAG, "Failed to read file (read %zu of %ld bytes)", BytesRead, FileSize); + heap_caps_free(SettingsBuffer); + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + return ESP_FAIL; + } + + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + ESP_LOGD(TAG, "File read successfully, parsing JSON..."); + + /* Parse JSON */ + json = cJSON_Parse(SettingsBuffer); + heap_caps_free(SettingsBuffer); + SettingsBuffer = NULL; + + if (json == NULL) { + const char *error_ptr = cJSON_GetErrorPtr(); + if (error_ptr != NULL) { + ESP_LOGE(TAG, "JSON Parse Error: %s!", error_ptr); + } else { + ESP_LOGE(TAG, "JSON Parse Error: Unknown!"); + } + + return ESP_FAIL; + } + + ESP_LOGD(TAG, "JSON parsed successfully"); + + /* Extract display settings */ + SettingsManager_LoadDisplay(p_State, json); + + /* Extract provisioning settings */ + SettingsManager_LoadProvisioning(p_State, json); + + /* Extract WiFi settings */ + SettingsManager_LoadWiFi(p_State, json); + + /* Extract system settings */ + SettingsManager_LoadSystem(p_State, json); + + /* Extract Lepton settings */ + SettingsManager_LoadLepton(p_State, json); + + /* Extract HTTP Server settings */ + SettingsManager_LoadHTTPServer(p_State, json); + + /* Extract VISA Server settings */ + SettingsManager_LoadVISAServer(p_State, json); + + cJSON_Delete(json); + + /* Mark config as loaded */ + Error = nvs_set_u8(p_State->NVS_Handle, "config_loaded", true); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set config_loaded flag: %d!", Error); + return Error; + } + + Error = nvs_commit(p_State->NVS_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit config_loaded flag: %d!", Error); + return Error; + } + + ESP_LOGD(TAG, "Default config loaded and marked as valid"); + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/Settings/Private/settingsLoader.h b/main/Application/Manager/Settings/Private/settingsLoader.h new file mode 100644 index 0000000..b4e080a --- /dev/null +++ b/main/Application/Manager/Settings/Private/settingsLoader.h @@ -0,0 +1,104 @@ +/* + * settingsLoader.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: JSON settings loader for factory defaults. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef SETTINGS_LOADER_H_ +#define SETTINGS_LOADER_H_ + +#include + +#include +#include + +#include +#include + +#include + +#include "../settingsTypes.h" + +/** @brief Settings Manager state. + */ +typedef struct { + bool isInitialized; + nvs_handle_t NVS_Handle; + App_Settings_t Settings; + SemaphoreHandle_t Mutex; +} SettingsManager_State_t; + +/** @brief Initialize the settings presets from the NVS by using a config JSON file. + * @param p_State Pointer to the Settings Manager state structure + * @return ESP_OK on success, ESP_ERR_* on failure + */ +esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State); + +/** @brief Initialize Lepton ROIs with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultLeptonROIs(App_Settings_t *p_Settings); + +/** @brief Initialize Lepton emissivity presets with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settings); + +/** @brief Initialize settings with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaults(App_Settings_t *p_Settings); + +/** @brief Initialize Display settings with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultDisplay(App_Settings_t *p_Settings); + +/** @brief Initialize Provisioning settings with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultProvisioning(App_Settings_t *p_Settings); + +/** @brief Initialize WiFi settings with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultWiFi(App_Settings_t *p_Settings); + +/** @brief Initialize System settings with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultSystem(App_Settings_t *p_Settings); + +/** @brief Initialize Lepton settings with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultLepton(App_Settings_t *p_Settings); + +/** @brief Initialize HTTP server settings with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultHTTPServer(App_Settings_t *p_Settings); + +/** @brief Initialize VISA server settings with factory defaults. + * @param p_Settings Pointer to settings structure + */ +void SettingsManager_InitDefaultVISAServer(App_Settings_t *p_Settings); + +#endif /* SETTINGS_LOADER_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index 350aa91..1dd4163 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -35,269 +35,41 @@ #include #include "settingsManager.h" +#include "Private/settingsLoader.h" + +/** @brief Settings storage namespace in NVS. + */ +#define SETTINGS_NVS_NAMESPACE "pyrovision" static const char *TAG = "settings_manager"; ESP_EVENT_DEFINE_BASE(SETTINGS_EVENTS); -/** @brief Settings Manager state. - */ -typedef struct { - bool isInitialized; - bool PendingChanges; - nvs_handle_t NVS_Handle; - App_Settings_t Settings; - SemaphoreHandle_t Mutex; -} SettingsManager_State_t; - -static SettingsManager_State_t _State = { - .isInitialized = false, - .PendingChanges = false, - .NVS_Handle = 0, - .Settings = {0}, - .Mutex = NULL, -}; - -/** @brief Initialize settings with factory defaults. - */ -static void SettingsManager_InitDefaults(App_Settings_t *p_Settings) -{ - uint8_t Mac[6]; - - memset(p_Settings, 0, sizeof(App_Settings_t)); - - p_Settings->Version = SETTINGS_VERSION; - - /* Spotmeter defaults */ - p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].Type = ROI_TYPE_SPOTMETER; - p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].x = 60; - p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].y = 40; - p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].w = 40; - p_Settings->Lepton.ROI[ROI_TYPE_SPOTMETER].h = 40; - - /* Scene statistics defaults */ - p_Settings->Lepton.ROI[ROI_TYPE_SCENE].Type = ROI_TYPE_SCENE; - p_Settings->Lepton.ROI[ROI_TYPE_SCENE].x = 0; - p_Settings->Lepton.ROI[ROI_TYPE_SCENE].y = 0; - p_Settings->Lepton.ROI[ROI_TYPE_SCENE].w = 160; - p_Settings->Lepton.ROI[ROI_TYPE_SCENE].h = 120; - - /* AGC defaults */ - p_Settings->Lepton.ROI[ROI_TYPE_AGC].Type = ROI_TYPE_AGC; - p_Settings->Lepton.ROI[ROI_TYPE_AGC].x = 0; - p_Settings->Lepton.ROI[ROI_TYPE_AGC].y = 0; - p_Settings->Lepton.ROI[ROI_TYPE_AGC].w = 160; - p_Settings->Lepton.ROI[ROI_TYPE_AGC].h = 120; - - /* Video focus defaults */ - p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].Type = ROI_TYPE_VIDEO_FOCUS; - p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].x = 1; - p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].y = 1; - p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].w = 157; - p_Settings->Lepton.ROI[ROI_TYPE_VIDEO_FOCUS].h = 157; - - p_Settings->Lepton.EnableSceneStatistics = true; - - /* No emissiviy values available */ - p_Settings->Lepton.EmissivityCount = 1; - p_Settings->Lepton.EmissivityPresets[0].Value = 100.0f; - strncpy(p_Settings->Lepton.EmissivityPresets[0].Description, "Unknown", sizeof(p_Settings->Lepton.EmissivityPresets[0].Description)); - - /* WiFi defaults */ - strncpy(p_Settings->WiFi.SSID, "", sizeof(p_Settings->WiFi.SSID)); - strncpy(p_Settings->WiFi.Password, "", sizeof(p_Settings->WiFi.Password)); - p_Settings->WiFi.AutoConnect = true; - - /* Display defaults */ - p_Settings->Display.Brightness = 80; - p_Settings->Display.ScreenTimeout = 0; - - /* System defaults */ - if (esp_efuse_mac_get_default(Mac) == ESP_OK) { - snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision-%02X%02X%02X%02X%02X%02X", - Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]); - } else { - snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision"); - ESP_LOGW(TAG, "Failed to get MAC address, using default name"); - } - - p_Settings->System.SDCard_AutoMount = true; - p_Settings->System.Bluetooth_Enabled = false; - strncpy(p_Settings->System.Timezone, "CET-1CEST,M3.5.0,M10.5.0/3", sizeof(p_Settings->System.Timezone)); -} +static SettingsManager_State_t _State; -/** @brief Initialize the settings presets from the NVS by using a config JSON file. +/** @brief Update a specific settings section in the Settings Manager RAM and emit the corresponding event. + * @param p_Src Pointer to source settings structure + * @param p_Dst Pointer to destination settings structure in RAM + * @param Size Size of the settings structure to copy + * @param EventID Event identifier to emit after update + * @return ESP_OK on success */ -static esp_err_t SettingsManager_LoadDefaultsFromJSON(void) +static esp_err_t SettingsManager_Update(void* p_Src, void* p_Dst, size_t Size, int EventID) { - uint8_t ConfigLoaded = 0; - esp_err_t Error; - cJSON *json = NULL; - cJSON *lepton = NULL; - cJSON *emissivity_array = NULL; - size_t Total = 0; - size_t Used = 0; - size_t BytesRead = 0; - FILE* SettingsFile = NULL; - char *SettingsBuffer = NULL; - long FileSize; - esp_vfs_littlefs_conf_t LittleFS_Config = { - .base_path = "/littlefs", - .partition_label = "storage", - .format_if_mount_failed = true, - .dont_mount = false - }; - - Error = nvs_get_u8(_State.NVS_Handle, "config_loaded", &ConfigLoaded); - if ((Error == ESP_OK) && (ConfigLoaded == true)) { - ESP_LOGI(TAG, "Default config already loaded, skipping"); - //return ESP_OK; - } - - ESP_LOGI(TAG, "Initializing LittleFS"); - - Error = esp_vfs_littlefs_register(&LittleFS_Config); - if (Error != ESP_OK) { - if (Error == ESP_FAIL) { - ESP_LOGE(TAG, "Failed to mount or format filesystem!"); - } else if (Error == ESP_ERR_NOT_FOUND) { - ESP_LOGE(TAG, "Failed to find LittleFS partition!"); - } else { - ESP_LOGE(TAG, "Failed to initialize LittleFS: %d!", Error); - } - - return ESP_FAIL; - } - - Error = esp_littlefs_info(LittleFS_Config.partition_label, &Total, &Used); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to get LittleFS partition information: %d!", Error); - } else { - ESP_LOGI(TAG, "Partition size: total: %zu, used: %zu", Total, Used); - } - - ESP_LOGI(TAG, "Opening settings file..."); - SettingsFile = fopen("/littlefs/default_settings.json", "r"); - if (SettingsFile == NULL) { - ESP_LOGE(TAG, "Failed to open file for reading!"); - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); - - return ESP_FAIL; - } - - /* Get file size */ - fseek(SettingsFile, 0, SEEK_END); - FileSize = ftell(SettingsFile); - fseek(SettingsFile, 0, SEEK_SET); - - if (FileSize <= 0) { - ESP_LOGE(TAG, "Invalid file size: %ld!", FileSize); - fclose(SettingsFile); - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); - - return ESP_FAIL; - } - - ESP_LOGI(TAG, "File size: %ld bytes", FileSize); - - /* Allocate buffer for file content */ - SettingsBuffer = (char*)heap_caps_malloc(FileSize + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (SettingsBuffer == NULL) { - ESP_LOGE(TAG, "Failed to allocate memory for file buffer!"); - fclose(SettingsFile); - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); - - return ESP_ERR_NO_MEM; - } - - /* Read file content */ - BytesRead = fread(SettingsBuffer, 1, FileSize, SettingsFile); - fclose(SettingsFile); - SettingsFile = NULL; - - if (BytesRead != FileSize) { - ESP_LOGE(TAG, "Failed to read file (read %zu of %ld bytes)", BytesRead, FileSize); - heap_caps_free(SettingsBuffer); - - return ESP_FAIL; - } - - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); - - ESP_LOGI(TAG, "File read successfully, parsing JSON..."); - - /* Parse JSON */ - json = cJSON_Parse(SettingsBuffer); - heap_caps_free(SettingsBuffer); - SettingsBuffer = NULL; - - if (json == NULL) { - const char *error_ptr = cJSON_GetErrorPtr(); - if (error_ptr != NULL) { - ESP_LOGE(TAG, "JSON Parse Error: %s", error_ptr); - } else { - ESP_LOGE(TAG, "JSON Parse Error: Unknown"); - } - - return ESP_FAIL; + if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if ((p_Src == NULL) || (p_Dst == NULL) || (Size == 0)) { + return ESP_ERR_INVALID_ARG; } - ESP_LOGI(TAG, "JSON parsed successfully"); - - /* Extract lepton settings */ - lepton = cJSON_GetObjectItem(json, "lepton"); - if (lepton != NULL) { - emissivity_array = cJSON_GetObjectItem(lepton, "emissivity"); - if (cJSON_IsArray(emissivity_array)) { - _State.Settings.Lepton.EmissivityCount = cJSON_GetArraySize(emissivity_array); - - ESP_LOGI(TAG, "Found %d emissivity presets in JSON", _State.Settings.Lepton.EmissivityCount); - - for (uint32_t i = 0; i < _State.Settings.Lepton.EmissivityCount; i++) { - cJSON *preset = cJSON_GetArrayItem(emissivity_array, i); - cJSON *name = cJSON_GetObjectItem(preset, "name"); - cJSON *value = cJSON_GetObjectItem(preset, "value"); - - if (cJSON_IsString(name) && cJSON_IsNumber(value)) { - _State.Settings.Lepton.EmissivityPresets[i].Value = (float)(value->valuedouble); - - /* Cap the emissivity value between 0 and 100 */ - if (_State.Settings.Lepton.EmissivityPresets[i].Value < 0.0f) { - _State.Settings.Lepton.EmissivityPresets[i].Value = 0.0f; - } else if (_State.Settings.Lepton.EmissivityPresets[i].Value > 100.0f) { - _State.Settings.Lepton.EmissivityPresets[i].Value = 100.0f; - } - - strncpy(_State.Settings.Lepton.EmissivityPresets[i].Description, name->valuestring, - sizeof(_State.Settings.Lepton.EmissivityPresets[i].Description)); - } else { - _State.Settings.Lepton.EmissivityPresets[i].Value = 100.0f; - strncpy(_State.Settings.Lepton.EmissivityPresets[i].Description, "Unknown", - sizeof(_State.Settings.Lepton.EmissivityPresets[i].Description)); - } - - ESP_LOGI(TAG, " Preset %d: %s = %.2f", i, name->valuestring, value->valuedouble); - } - } - } + xSemaphoreTake(_State.Mutex, portMAX_DELAY); - cJSON_Delete(json); + memcpy(p_Dst, p_Src, Size); - /* Mark config as loaded */ - Error = nvs_set_u8(_State.NVS_Handle, "config_loaded", true); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to set config_loaded flag: %d!", Error); - return Error; - } + xSemaphoreGive(_State.Mutex); - Error = nvs_commit(_State.NVS_Handle); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to commit config_loaded flag: %d!", Error); - return Error; - } + esp_event_post(SETTINGS_EVENTS, EventID, p_Dst, Size, portMAX_DELAY); - ESP_LOGI(TAG, "Default config loaded and marked as valid"); - return ESP_OK; } @@ -331,7 +103,6 @@ esp_err_t SettingsManager_Init(void) } _State.isInitialized = true; - _State.PendingChanges = false; /* Load the settings from the NVS */ Error = SettingsManager_Load(&_State.Settings); @@ -339,7 +110,7 @@ esp_err_t SettingsManager_Init(void) ESP_LOGI(TAG, "No settings found, using factory defaults"); /* Try to load default settings from JSON first (on first boot) */ - if (SettingsManager_LoadDefaultsFromJSON() != ESP_OK) { + if (SettingsManager_LoadDefaultsFromJSON(&_State) != ESP_OK) { ESP_LOGW(TAG, "Failed to load default settings from JSON, using built-in defaults"); /* Use built-in defaults */ @@ -347,13 +118,13 @@ esp_err_t SettingsManager_Init(void) } /* Save the default settings to NVS */ - SettingsManager_Save(&_State.Settings); + SettingsManager_Save(); /* Load the JSON presets into the settings structure */ SettingsManager_Load(&_State.Settings); } - ESP_LOGI(TAG, "Settings Manager initialized (version %lu)", _State.Settings.Version); + ESP_LOGI(TAG, "Settings Manager initialized"); esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_LOADED, &_State.Settings, sizeof(App_Settings_t), portMAX_DELAY); @@ -366,10 +137,6 @@ esp_err_t SettingsManager_Deinit(void) return ESP_OK; } - if (_State.PendingChanges) { - SettingsManager_Commit(); - } - nvs_close(_State.NVS_Handle); vSemaphoreDelete(_State.Mutex); @@ -396,6 +163,7 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) Error = nvs_get_blob(_State.NVS_Handle, "settings", NULL, &RequiredSize); if (Error == ESP_ERR_NVS_NOT_FOUND) { xSemaphoreGive(_State.Mutex); + return ESP_ERR_NVS_NOT_FOUND; } else if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to get settings size: %d!", Error); @@ -411,7 +179,7 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) return ESP_ERR_INVALID_SIZE; } - Error = nvs_get_blob(_State.NVS_Handle, "settings", p_Settings, &RequiredSize); + Error = nvs_get_blob(_State.NVS_Handle, "settings", &_State.Settings, &RequiredSize); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to read settings: %d!", Error); xSemaphoreGive(_State.Mutex); @@ -419,41 +187,26 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) return Error; } - /* Verify version */ - if (p_Settings->Version != SETTINGS_VERSION) { - ESP_LOGW(TAG, "Settings version mismatch (expected %d, got %lu), migration needed", - SETTINGS_VERSION, p_Settings->Version); - - /* TODO: Implement migration logic here */ - - ESP_LOGW(TAG, "Settings migration not implemented, using defaults"); - xSemaphoreGive(_State.Mutex); - - return ESP_FAIL; - } + memcpy(p_Settings, &_State.Settings, sizeof(App_Settings_t)); xSemaphoreGive(_State.Mutex); - ESP_LOGI(TAG, "Settings loaded from NVS"); + ESP_LOGD(TAG, "Settings loaded from NVS"); - // TODO: Remove me - return ESP_FAIL; return ESP_OK; } -esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings) +esp_err_t SettingsManager_Save(void) { esp_err_t Error; if (_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (p_Settings == NULL) { - return ESP_ERR_INVALID_ARG; } xSemaphoreTake(_State.Mutex, portMAX_DELAY); - Error = nvs_set_blob(_State.NVS_Handle, "settings", p_Settings, sizeof(App_Settings_t)); + Error = nvs_set_blob(_State.NVS_Handle, "settings", &_State.Settings, sizeof(App_Settings_t)); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to write settings: %d!", Error); xSemaphoreGive(_State.Mutex); @@ -467,8 +220,6 @@ esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings) return Error; } - _State.PendingChanges = false; - xSemaphoreGive(_State.Mutex); ESP_LOGI(TAG, "Settings saved to NVS"); @@ -478,113 +229,146 @@ esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings) return ESP_OK; } -esp_err_t SettingsManager_Get(App_Settings_t *p_Settings) +esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings) { - if (_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } else if (p_Settings == NULL) { + if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; + } else if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; } xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Settings, sizeof(App_Settings_t)); + memcpy(p_Settings, &_State.Settings.Lepton, sizeof(App_Settings_Lepton_t)); xSemaphoreGive(_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_SetLepton(const App_Settings_Lepton_t *p_Lepton) +esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings) { - if (_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } else if (p_Lepton == NULL) { + return SettingsManager_Update(p_Settings, &_State.Settings.Lepton, sizeof(App_Settings_Lepton_t), SETTINGS_EVENT_LEPTON_CHANGED); +} + +esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t* p_Settings) +{ + if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; + } else if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; } xSemaphoreTake(_State.Mutex, portMAX_DELAY); - - memcpy(&_State.Settings.Lepton, p_Lepton, sizeof(App_Settings_Lepton_t)); - _State.PendingChanges = true; - + memcpy(p_Settings, &_State.Settings.WiFi, sizeof(App_Settings_WiFi_t)); xSemaphoreGive(_State.Mutex); - ESP_LOGI(TAG, "Lepton settings updated"); - - esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_LEPTON_CHANGED, p_Lepton, - sizeof(App_Settings_Lepton_t), portMAX_DELAY); - return ESP_OK; } -esp_err_t SettingsManager_SetWiFi(const App_Settings_WiFi_t *p_WiFi) +esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t* p_Settings) { - if (_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } else if (p_WiFi == NULL) { + return SettingsManager_Update(p_Settings, &_State.Settings.WiFi, sizeof(App_Settings_WiFi_t), SETTINGS_EVENT_WIFI_CHANGED); +} + +esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t* p_Settings) +{ + if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; + } else if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; } xSemaphoreTake(_State.Mutex, portMAX_DELAY); - - memcpy(&_State.Settings.WiFi, p_WiFi, sizeof(App_Settings_WiFi_t)); - _State.PendingChanges = true; - + memcpy(p_Settings, &_State.Settings.Provisioning, sizeof(App_Settings_Provisioning_t)); xSemaphoreGive(_State.Mutex); - esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_WIFI_CHANGED, p_WiFi, - sizeof(App_Settings_WiFi_t), portMAX_DELAY); - return ESP_OK; } -esp_err_t SettingsManager_SetDisplay(const App_Settings_Display_t *p_Display) +esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t* p_Settings) { - if (_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } else if (p_Display == NULL) { + return SettingsManager_Update(p_Settings, &_State.Settings.Provisioning, sizeof(App_Settings_Provisioning_t), SETTINGS_EVENT_PROVISIONING_CHANGED); +} + +esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t* p_Settings) +{ + if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; + } else if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; } xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_State.Settings.Display, sizeof(App_Settings_Display_t)); + xSemaphoreGive(_State.Mutex); - memcpy(&_State.Settings.Display, p_Display, sizeof(App_Settings_Display_t)); - _State.PendingChanges = true; + return ESP_OK; +} - xSemaphoreGive(_State.Mutex); +esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t* p_Settings) +{ + return SettingsManager_Update(p_Settings, &_State.Settings.Display, sizeof(App_Settings_Display_t), SETTINGS_EVENT_DISPLAY_CHANGED); +} - ESP_LOGI(TAG, "Display settings updated (Brightness: %d%%, Timeout: %ds)", - p_Display->Brightness, p_Display->ScreenTimeout); +esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t* p_Settings) +{ + if ( p_Settings == NULL ) { + return ESP_ERR_INVALID_ARG; + } else if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } - esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_DISPLAY_CHANGED, p_Display, - sizeof(App_Settings_Display_t), portMAX_DELAY); + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_State.Settings.HTTPServer, sizeof(App_Settings_HTTP_Server_t)); + xSemaphoreGive(_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_SetSystem(const App_Settings_System_t *p_System) +esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t* p_Settings) { - if (_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } else if (p_System == NULL) { + return SettingsManager_Update(p_Settings, &_State.Settings.HTTPServer, sizeof(App_Settings_HTTP_Server_t), SETTINGS_EVENT_HTTP_SERVER_CHANGED); +} + +esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t* p_Settings) +{ + if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; + } else if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; } xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_State.Settings.VISAServer, sizeof(App_Settings_VISA_Server_t)); + xSemaphoreGive(_State.Mutex); - memcpy(&_State.Settings.System, p_System, sizeof(App_Settings_System_t)); - _State.PendingChanges = true; + return ESP_OK; +} - xSemaphoreGive(_State.Mutex); +esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t* p_Settings) +{ + return SettingsManager_Update(p_Settings, &_State.Settings.VISAServer, sizeof(App_Settings_VISA_Server_t), SETTINGS_EVENT_VISA_SERVER_CHANGED); +} - ESP_LOGI(TAG, "System settings updated (Device: %s, SD Auto: %d)", - p_System->DeviceName, p_System->SDCard_AutoMount); +esp_err_t SettingsManager_GetSystem(App_Settings_System_t* p_Settings) +{ + if ( p_Settings == NULL ) { + return ESP_ERR_INVALID_ARG; + } else if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } - esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_SYSTEM_CHANGED, p_System, - sizeof(App_Settings_System_t), portMAX_DELAY); + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_State.Settings.System, sizeof(App_Settings_System_t)); + xSemaphoreGive(_State.Mutex); return ESP_OK; } +esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t* p_Settings) +{ + return SettingsManager_Update(p_Settings, &_State.Settings.System, sizeof(App_Settings_System_t), SETTINGS_EVENT_SYSTEM_CHANGED); +} + esp_err_t SettingsManager_ResetToDefaults(void) { esp_err_t Error; @@ -615,6 +399,7 @@ esp_err_t SettingsManager_ResetToDefaults(void) Error = nvs_set_u8(_State.NVS_Handle, "config_loaded", false); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to set config_loaded flag: %d!", Error); + xSemaphoreGive(_State.Mutex); return Error; } @@ -627,19 +412,3 @@ esp_err_t SettingsManager_ResetToDefaults(void) return ESP_OK; } -esp_err_t SettingsManager_Commit(void) -{ - if (_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } else if (_State.PendingChanges == false) { - ESP_LOGD(TAG, "No pending changes to commit"); - return ESP_OK; - } - - return SettingsManager_Save(&_State.Settings); -} - -bool SettingsManager_HasPendingChanges(void) -{ - return _State.PendingChanges; -} diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h index 85638bc..fd2ed3d 100644 --- a/main/Application/Manager/Settings/settingsManager.h +++ b/main/Application/Manager/Settings/settingsManager.h @@ -27,18 +27,10 @@ #include #include -#include "settings_types.h" +#include "settingsTypes.h" -/** @brief Settings storage namespace in NVS. - */ -#define SETTINGS_NVS_NAMESPACE "pyrovision" - -/** @brief Current settings version for migration support. - */ -#define SETTINGS_VERSION 1 - -/** @brief Initialize the Settings Manager and load settings from NVS. - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Initialize the Settings Manager and load all settings from NVS into the Settings Manager RAM and into the provided structure. + * @return ESP_OK on success */ esp_err_t SettingsManager_Init(void); @@ -47,52 +39,100 @@ esp_err_t SettingsManager_Init(void); */ esp_err_t SettingsManager_Deinit(void); -/** @brief Load all settings from NVS. - * If settings don't exist, factory defaults are used. +/** @brief Load all settings from NVS into the Settings Manager RAM and into the provided structure. This function overwrites all unsaved settings in RAM. * @param p_Settings Pointer to settings structure to populate * @return ESP_OK on success, ESP_ERR_NVS_NOT_FOUND if no settings exist */ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings); -/** @brief Save all settings to NVS. - * @param p_Settings Pointer to settings structure to save - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Save all RAM settings to NVS. + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_Save(const App_Settings_t *p_Settings); +esp_err_t SettingsManager_Save(void); -/** @brief Get current settings (cached in RAM). - * @param p_Settings Pointer to settings structure to populate - * @return ESP_OK on success +/** @brief Get the Lepton settings from the Settings Manager RAM. + * @param p_Settings Pointer to System settings structure to populate + * @return ESP_OK on success, ESP_ERR_* on failure +*/ +esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings); + +/** @brief Update Lepton settings in the Settings Manager RAM. + * @param p_Settings Pointer to Lepton settings structure + * @return ESP_OK on success, ESP_ERR_* on failure + */ +esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings); + +/** @brief Get the WiFi settings from the Settings Manager RAM. + * @param p_Settings Pointer to WiFi settings structure to populate + * @return ESP_OK on success, ESP_ERR_* on failure +*/ +esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t* p_Settings); + +/** @brief Update WiFi settings in the Settings Manager RAM. + * @param p_Settings Pointer to WiFi settings structure + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_Get(App_Settings_t *p_Settings); +esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t* p_Settings); -/** @brief Update Lepton settings. - * Changes are cached and broadcasted via SETTINGS_EVENT_LEPTON_CHANGED. - * @param p_Lepton Pointer to Lepton settings - * @return ESP_OK on success +/** @brief Get the Provisioning settings from the Settings Manager RAM. + * @param p_Settings Pointer to Provisioning settings structure to populate + * @return ESP_OK on success, ESP_ERR_* on failure +*/ +esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t* p_Settings); + +/** @brief Update Provisioning settings in the Settings Manager RAM. + * @param p_Settings Pointer to Provisioning settings structure + * @return ESP_OK on success, ESP_ERR_* on failure + */ +esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t* p_Settings); + +/** @brief Get the Display settings from the Settings Manager RAM. + * @param p_Settings Pointer to Display settings structure to populate + * @return ESP_OK on success, ESP_ERR_* on failure +*/ +esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t* p_Settings); + +/** @brief Update Display settings in the Settings Manager RAM. + * @param p_Settings Pointer to Display settings structure + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_SetLepton(const App_Settings_Lepton_t *p_Lepton); +esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t* p_Settings); + +/** @brief Get the HTTP Server settings from the Settings Manager RAM. + * @param p_Settings Pointer to HTTP Server settings structure to populate + * @return ESP_OK on success, ESP_ERR_* on failure +*/ +esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t* p_Settings); -/** @brief Update WiFi settings. - * Changes are cached and broadcasted via SETTINGS_EVENT_WIFI_CHANGED. - * @param p_WiFi Pointer to WiFi settings - * @return ESP_OK on success +/** @brief Update HTTP Server settings in the Settings Manager RAM. + * @param p_Settings Pointer to HTTP Server settings structure + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_SetWiFi(const App_Settings_WiFi_t *p_WiFi); +esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t* p_Settings); + +/** @brief Get the VISA Server settings from the Settings Manager RAM. + * @param p_Settings Pointer to VISA Server settings structure to populate + * @return ESP_OK on success, ESP_ERR_* on failure +*/ +esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t* p_Settings); -/** @brief Update Display settings. - * Changes are cached and broadcasted via SETTINGS_EVENT_DISPLAY_CHANGED. - * @param p_Display Pointer to Display settings - * @return ESP_OK on success +/** @brief Update VISA Server settings in the Settings Manager RAM. + * @param p_Settings Pointer to VISA Server settings structure + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_SetDisplay(const App_Settings_Display_t *p_Display); +esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t* p_Settings); -/** @brief Update System settings. - * Changes are cached and broadcasted via SETTINGS_EVENT_SYSTEM_CHANGED. - * @param p_System Pointer to System settings - * @return ESP_OK on success +/** @brief Get the system settings from the Settings Manager RAM. + * @param p_Settings Pointer to System settings structure to populate + * @return ESP_OK on success, ESP_ERR_* on failure +*/ +esp_err_t SettingsManager_GetSystem(App_Settings_System_t* p_Settings); + +/** @brief Update System settings in the Settings Manager RAM. + * @param p_Settings Pointer to System settings structure + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_SetSystem(const App_Settings_System_t *p_System); +esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t* p_Settings); /** @brief Reset all settings to factory defaults. * Erases NVS partition and reloads defaults. @@ -100,15 +140,4 @@ esp_err_t SettingsManager_SetSystem(const App_Settings_System_t *p_System); */ esp_err_t SettingsManager_ResetToDefaults(void); -/** @brief Commit cached settings to NVS storage. - * Should be called periodically or on shutdown to persist changes. - * @return ESP_OK on success - */ -esp_err_t SettingsManager_Commit(void); - -/** @brief Check if settings have unsaved changes. - * @return true if changes are pending, false otherwise - */ -bool SettingsManager_HasPendingChanges(void); - #endif /* SETTINGS_MANAGER_H_ */ diff --git a/main/Application/Manager/Settings/settings_types.h b/main/Application/Manager/Settings/settingsTypes.h similarity index 79% rename from main/Application/Manager/Settings/settings_types.h rename to main/Application/Manager/Settings/settingsTypes.h index ce854cd..c125556 100644 --- a/main/Application/Manager/Settings/settings_types.h +++ b/main/Application/Manager/Settings/settingsTypes.h @@ -24,6 +24,10 @@ #ifndef SETTINGS_TYPES_H_ #define SETTINGS_TYPES_H_ +#include +#include +#include + #include /** @brief Settings Manager events base. @@ -39,8 +43,14 @@ enum { Data contains App_Settings_Lepton_t. */ SETTINGS_EVENT_WIFI_CHANGED, /**< WiFi settings changed. Data contains App_Settings_WiFi_t. */ + SETTINGS_EVENT_PROVISIONING_CHANGED, /**< Provisioning settings changed. + Data contains App_Settings_Provisioning_t. */ SETTINGS_EVENT_DISPLAY_CHANGED, /**< Display settings changed. Data contains App_Settings_Display_t. */ + SETTINGS_EVENT_HTTP_SERVER_CHANGED, /**< HTTP server settings changed. + Data contains App_Settings_HTTP_Server_t. */ + SETTINGS_EVENT_VISA_SERVER_CHANGED, /**< VISA server settings changed. + Data contains App_Settings_VISA_Server_t. */ SETTINGS_EVENT_SYSTEM_CHANGED, /**< System settings changed. Data contains App_Settings_System_t. */ SETTINGS_EVENT_REQUEST_GET, /**< Request to get current settings. */ @@ -78,8 +88,6 @@ typedef struct { */ typedef struct { App_Settings_ROI_t ROI[4]; /**< Camera ROIs. */ - uint8_t Emissivity; /**< Emissivity (0-100). */ - bool EnableSceneStatistics; /**< Enable scene statistics calculation. */ App_Settings_Emissivity_t EmissivityPresets[128]; /**< Array of emissivity presets. */ size_t EmissivityCount; /**< Number of emissivity presets. */ } __attribute__((packed)) App_Settings_Lepton_t; @@ -97,20 +105,32 @@ typedef struct { /** @brief Provisioning settings. */ typedef struct { - char DeviceName[32]; /**< Device name for provisioning. */ + char Name[32]; /**< Device name for provisioning. */ char PoP[32]; /**< Proof of Possession for provisioning. */ uint32_t Timeout; /**< Provisioning timeout in seconds. */ - uint8_t Reserved[100]; /**< Reserved for future use. */ } __attribute__((packed)) App_Settings_Provisioning_t; /** @brief Display settings. */ typedef struct { uint8_t Brightness; /**< Display brightness (0-100%). */ - uint16_t ScreenTimeout; /**< Screen timeout in seconds (0=never). */ - uint8_t Reserved[100]; /**< Reserved for future use. */ + uint16_t Timeout; /**< Screen timeout in seconds (0=never). */ } __attribute__((packed)) App_Settings_Display_t; +/** @brief HTTP server settings. + */ +typedef struct { + uint16_t Port; /**< HTTP server port. */ + uint16_t WSPingIntervalSec; /**< WebSocket ping interval in seconds. */ + uint8_t MaxClients; /**< Maximum number of simultaneous clients. */ +} __attribute__((packed)) App_Settings_HTTP_Server_t; + +/** @brief VISA server settings. + */ +typedef struct { + uint16_t Port; /**< VISA server port. */ +} __attribute__((packed)) App_Settings_VISA_Server_t; + /** @brief System settings. */ typedef struct { @@ -124,11 +144,12 @@ typedef struct { /** @brief Complete application settings structure. */ typedef struct { - uint32_t Version; /**< Settings version for migration. */ App_Settings_Lepton_t Lepton; /**< Lepton camera settings. */ App_Settings_WiFi_t WiFi; /**< WiFi settings. */ - App_Settings_Provisioning_t ProvConfig; /**< Provisioning settings. */ + App_Settings_Provisioning_t Provisioning; /**< Provisioning settings. */ App_Settings_Display_t Display; /**< Display settings. */ + App_Settings_HTTP_Server_t HTTPServer; /**< HTTP server settings. */ + App_Settings_VISA_Server_t VISAServer; /**< VISA server settings. */ App_Settings_System_t System; /**< System settings. */ } __attribute__((packed)) App_Settings_t; diff --git a/main/Application/Tasks/GUI/Private/guiHelper.h b/main/Application/Tasks/GUI/Private/guiHelper.h index d251f56..7d8548e 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.h +++ b/main/Application/Tasks/GUI/Private/guiHelper.h @@ -37,7 +37,7 @@ #include #include "Application/application.h" -#include "Application/Manager/Network/network_types.h" +#include "Application/Manager/Network/networkTypes.h" #define STOP_REQUEST BIT0 #define BATTERY_VOLTAGE_READY BIT1 diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp index 4f1f19c..ef86936 100644 --- a/main/Application/Tasks/GUI/guiTask.cpp +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -316,8 +316,7 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) { int32_t DisplayWidth; int32_t DisplayHeight; - App_Settings_ROI_t Lepton_ROI; - App_Settings_t App_Settings; + App_Settings_Lepton_t SettingsLepton; if ((ROI.x + ROI.w) > 160) { ROI.w = 160 - ROI.x; @@ -389,22 +388,26 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) } } - /* Save the new ROI to NVS */ - if (SettingsManager_Get(&App_Settings) == ESP_OK) { - if (App_Settings.Lepton.ROI[ROI.Type].x == ROI.x && - App_Settings.Lepton.ROI[ROI.Type].y == ROI.y && - App_Settings.Lepton.ROI[ROI.Type].w == ROI.w && - App_Settings.Lepton.ROI[ROI.Type].h == ROI.h) { - ESP_LOGW(TAG, "ROI unchanged, not updating NVS"); - return; - } + SettingsManager_GetLepton(&SettingsLepton); - memcpy(&App_Settings.Lepton.ROI[ROI.Type], &ROI, sizeof(App_Settings_ROI_t)); - SettingsManager_SetLepton(&App_Settings.Lepton); + /* Check if an update is required */ + if (SettingsLepton.ROI[ROI.Type].x == ROI.x && + SettingsLepton.ROI[ROI.Type].y == ROI.y && + SettingsLepton.ROI[ROI.Type].w == ROI.w && + SettingsLepton.ROI[ROI.Type].h == ROI.h) { + ESP_LOGW(TAG, "ROI unchanged, not updating NVS"); + return; } + /* Copy the new ROI in the existing settings structure */ + memcpy(&SettingsLepton.ROI[ROI.Type], &ROI, sizeof(App_Settings_ROI_t)); + + /* Save the new ROI to NVS */ + SettingsManager_UpdateLepton(&SettingsLepton); + SettingsManager_Save(); + /* The Lepton task needs the ROI with the Lepton coordinates */ - Lepton_ROI = { + SettingsLepton.ROI[ROI.Type] = { .Type = ROI.Type, .x = (uint16_t)ROI.x, .y = (uint16_t)ROI.y, @@ -412,7 +415,7 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) .h = (uint16_t)ROI.h }; - esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_ROI, &Lepton_ROI, sizeof(App_Settings_ROI_t), portMAX_DELAY); + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_ROI, &SettingsLepton.ROI[ROI.Type], sizeof(App_Settings_ROI_t), portMAX_DELAY); } /** @brief Create temperature gradient canvas for palette visualization. @@ -512,6 +515,7 @@ static void XPT2046_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Da void Task_GUI(void *p_Parameters) { App_Context_t *App_Context; + App_Settings_Lepton_t LeptonSettings; esp_task_wdt_add(NULL); @@ -546,11 +550,11 @@ void Task_GUI(void *p_Parameters) lv_timer_handler(); /* Set the initial ROI FIRST to give it a size */ - GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_SPOTMETER]); - GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_SPOTMETER]); - GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_SCENE]); - GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_AGC]); - GUI_Update_ROI(App_Context->Settings.Lepton.ROI[ROI_TYPE_VIDEO_FOCUS]); + SettingsManager_GetLepton(&LeptonSettings); + GUI_Update_ROI(LeptonSettings.ROI[ROI_TYPE_SPOTMETER]); + GUI_Update_ROI(LeptonSettings.ROI[ROI_TYPE_SCENE]); + GUI_Update_ROI(LeptonSettings.ROI[ROI_TYPE_AGC]); + GUI_Update_ROI(LeptonSettings.ROI[ROI_TYPE_VIDEO_FOCUS]); GUI_Update_Info(); diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp index 000281d..5516857 100644 --- a/main/Application/Tasks/Lepton/leptonTask.cpp +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -43,6 +43,7 @@ #define LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE BIT4 #define LEPTON_TASK_UPDATE_SPOTMETER BIT5 #define LEPTON_TASK_UPDATE_SCENE_STATISTICS BIT6 +#define LEPTON_TASK_UPDATE_EMISSIVITY BIT7 ESP_EVENT_DEFINE_BASE(LEPTON_EVENTS); @@ -54,7 +55,7 @@ typedef struct { EventGroupHandle_t EventGroup; uint8_t *RGB_Buffer[2]; uint8_t CurrentReadBuffer; - uint8_t InitializationRetries; + uint16_t Emissivity; SemaphoreHandle_t BufferMutex; QueueHandle_t RawFrameQueue; Lepton_FrameBuffer_t RawFrame; @@ -106,6 +107,13 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int break; } + case GUI_EVENT_REQUEST_EMISSIVITY: { + _LeptonTask_State.Emissivity = *(uint16_t *)p_Data; + + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); + + break; + } default: { ESP_LOGW(TAG, "Unhandled GUI event ID: %d", ID); break; @@ -154,7 +162,6 @@ static void Task_Lepton(void *p_Parameters) esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_READY, &DeviceInfo, sizeof(App_Lepton_Device_t), portMAX_DELAY); - /* Lepton_FluxLinearParams_t FluxParams; Lepton_GetFluxLinearParameters(&_LeptonTask_State.Lepton, &FluxParams); ESP_LOGI(TAG, "Flux Linear Parameters - Scene Emissivity: %u, TBkgK: %u, TauWindow: %u, TWindowK: %u, TauAtm: %u, TAtmK: %u, ReflWindow: %u, TReflK: %u", @@ -169,10 +176,6 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGD(TAG, "Start image capturing..."); - if (Lepton_SetEmissivity(&_LeptonTask_State.Lepton, (Lepton_Emissivity_t)App_Context->Settings.Lepton.Emissivity) != LEPTON_ERR_OK) { - ESP_LOGE(TAG, "Failed to set emissivity!"); - } -*/ if (Lepton_StartCapture(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrameQueue) != LEPTON_ERR_OK) { ESP_LOGE(TAG, "Can not start image capturing!"); esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); @@ -405,6 +408,17 @@ static void Task_Lepton(void *p_Parameters) } xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SCENE_STATISTICS); + } else if (EventBits & LEPTON_TASK_UPDATE_EMISSIVITY) { + Lepton_Error_t Error; + + Error = Lepton_SetEmissivity(&_LeptonTask_State.Lepton, static_cast(_LeptonTask_State.Emissivity)); + if (Error == LEPTON_ERR_OK) { + ESP_LOGD(TAG, "Updated emissivity to %u", _LeptonTask_State.Emissivity); + } else { + ESP_LOGE(TAG, "Failed to update emissivity to %u!", _LeptonTask_State.Emissivity); + } + + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); } } @@ -429,7 +443,6 @@ esp_err_t Lepton_Task_Init(void) ESP_LOGD(TAG, "Initializing Lepton Task"); _LeptonTask_State.CurrentReadBuffer = 0; - _LeptonTask_State.InitializationRetries = 0; Lepton_Error = LEPTON_ERR_OK; diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index 2e485a1..a777c26 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -57,6 +57,8 @@ typedef struct { Network_State_t State; const char *Timezone; App_Context_t *AppContext; + char SSID[33]; + char Password[65]; } Network_Task_State_t; static Network_Task_State_t _NetworkTask_State; @@ -77,12 +79,12 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, ESP_LOGD(TAG, "WiFi credentials updated"); - memcpy(&_NetworkTask_State.AppContext->Settings.WiFi.SSID, + memcpy(&_NetworkTask_State.SSID, Credentials->SSID, - sizeof(_NetworkTask_State.AppContext->Settings.WiFi.SSID)); - memcpy(&_NetworkTask_State.AppContext->Settings.WiFi.Password, + sizeof(_NetworkTask_State.SSID)); + memcpy(&_NetworkTask_State.Password, Credentials->Password, - sizeof(_NetworkTask_State.AppContext->Settings.WiFi.Password)); + sizeof(_NetworkTask_State.Password)); xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); @@ -159,13 +161,16 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, */ static void Task_Network(void *p_Parameters) { + App_Settings_WiFi_t WiFiSettings; + esp_task_wdt_add(NULL); ESP_LOGD(TAG, "Network task started on core %d", xPortGetCoreID()); - ESP_LOGI(TAG, "Autoconnect is %s", (_NetworkTask_State.AppContext->Settings.WiFi.AutoConnect) ? "enabled" : "disabled"); - /* - if(App_Context->Settings.WiFi.AutoConnect == false) { + SettingsManager_GetWiFi(&WiFiSettings); + + ESP_LOGI(TAG, "Autoconnect is %s", (WiFiSettings.AutoConnect) ? "enabled" : "disabled"); + if (WiFiSettings.AutoConnect == false) { do { EventBits_t EventBits; @@ -180,7 +185,7 @@ static void Task_Network(void *p_Parameters) vTaskDelay(100 / portTICK_PERIOD_MS); } while (true); - }*/ + } if ((Provisioning_isProvisioned() == false) && (strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0)) { @@ -265,15 +270,27 @@ static void Task_Network(void *p_Parameters) xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); } else if (EventBits & NETWORK_TASK_SNTP_TIMEZONE_SET) { + App_Settings_System_t SystemSettings; + + SettingsManager_GetSystem(&SystemSettings); - memcpy(&_NetworkTask_State.AppContext->Settings.System.Timezone, _NetworkTask_State.Timezone, - sizeof(_NetworkTask_State.AppContext->Settings.System.Timezone)); - SettingsManager_Save(&_NetworkTask_State.AppContext->Settings); - TimeManager_SetTimezone(_NetworkTask_State.AppContext->Settings.System.Timezone); + memcpy(&SystemSettings.Timezone, _NetworkTask_State.Timezone, sizeof(SystemSettings.Timezone)); + TimeManager_SetTimezone(SystemSettings.Timezone); + + SettingsManager_UpdateSystem(&SystemSettings); + SettingsManager_Save(); xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); } else if (EventBits & NETWORK_TASK_WIFI_CREDENTIALS_UPDATED) { - SettingsManager_Save(&_NetworkTask_State.AppContext->Settings); + App_Settings_WiFi_t WiFiSettings; + + SettingsManager_GetWiFi(&WiFiSettings); + + memcpy(WiFiSettings.SSID, _NetworkTask_State.SSID, sizeof(WiFiSettings.SSID)); + memcpy(WiFiSettings.Password, _NetworkTask_State.Password, sizeof(WiFiSettings.Password)); + + SettingsManager_UpdateWiFi(&WiFiSettings); + SettingsManager_Save(); xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); } @@ -295,6 +312,8 @@ static void Task_Network(void *p_Parameters) esp_err_t Network_Task_Init(App_Context_t *p_AppContext) { esp_err_t Error; + App_Settings_WiFi_t WiFiSettings; + App_Settings_Provisioning_t ProvisioningSettings; if (p_AppContext == NULL) { return ESP_ERR_INVALID_ARG; @@ -337,21 +356,23 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) } /* Copy the required WiFi settings from settings to network config */ - strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID, p_AppContext->Settings.WiFi.SSID, + SettingsManager_GetWiFi(&WiFiSettings); + strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID, WiFiSettings.SSID, sizeof(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) - 1); - strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.Password, p_AppContext->Settings.WiFi.Password, + strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.Password, WiFiSettings.Password, sizeof(_NetworkTask_State.AppContext->STA_Config.Credentials.Password) - 1); - _NetworkTask_State.AppContext->STA_Config.MaxRetries = p_AppContext->Settings.WiFi.MaxRetries; - _NetworkTask_State.AppContext->STA_Config.RetryInterval = p_AppContext->Settings.WiFi.RetryInterval; + _NetworkTask_State.AppContext->STA_Config.MaxRetries = WiFiSettings.MaxRetries; + _NetworkTask_State.AppContext->STA_Config.RetryInterval = WiFiSettings.RetryInterval; /* Copy the required Provisioning settings from settings to network config */ - strncpy(_NetworkTask_State.AppContext->STA_Config.ProvConfig.DeviceName, - p_AppContext->Settings.ProvConfig.DeviceName, - sizeof(_NetworkTask_State.AppContext->STA_Config.ProvConfig.DeviceName) - 1); - strncpy(_NetworkTask_State.AppContext->STA_Config.ProvConfig.PoP, - p_AppContext->Settings.ProvConfig.PoP, - sizeof(_NetworkTask_State.AppContext->STA_Config.ProvConfig.PoP) - 1); - _NetworkTask_State.AppContext->STA_Config.ProvConfig.Timeout = p_AppContext->Settings.ProvConfig.Timeout; + SettingsManager_GetProvisioning(&ProvisioningSettings); + strncpy(_NetworkTask_State.AppContext->Prov_Config.Name, + ProvisioningSettings.Name, + sizeof(_NetworkTask_State.AppContext->Prov_Config.Name) - 1); + strncpy(_NetworkTask_State.AppContext->Prov_Config.PoP, + ProvisioningSettings.PoP, + sizeof(_NetworkTask_State.AppContext->Prov_Config.PoP) - 1); + _NetworkTask_State.AppContext->Prov_Config.Timeout = ProvisioningSettings.Timeout; Error = NetworkManager_Init(&_NetworkTask_State.AppContext->STA_Config); if (Error != ESP_OK) { @@ -363,7 +384,7 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) return Error; } - Error = Provisioning_Init(&p_AppContext->STA_Config); + Error = Provisioning_Init(&_NetworkTask_State.AppContext->Prov_Config); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to init provisioning: %d!", Error); /* Continue anyway, provisioning is optional */ diff --git a/main/Application/Tasks/Network/networkTask.h b/main/Application/Tasks/Network/networkTask.h index 9b7184a..273c834 100644 --- a/main/Application/Tasks/Network/networkTask.h +++ b/main/Application/Tasks/Network/networkTask.h @@ -30,7 +30,7 @@ #include #include "Application/application.h" -#include "Application/Manager/Network/network_types.h" +#include "Application/Manager/Network/networkTypes.h" /** @brief Initialize the network task. * @param p_AppContext Pointer to the application context diff --git a/main/Application/application.h b/main/Application/application.h index 6fb5297..37b369a 100644 --- a/main/Application/application.h +++ b/main/Application/application.h @@ -68,7 +68,8 @@ enum { */ enum { GUI_EVENT_INIT_DONE, /**< GUI task initialization done. */ - GUI_EVENT_REQUEST_ROI, /**< Update the ROI rectangle on the GUI. */ + GUI_EVENT_REQUEST_ROI, /**< Update the ROI rectangle on the GUI. + Data is transmitted in a App_Settings_ROI_t structure. */ GUI_EVENT_REQUEST_FPA_AUX_TEMP, /**< Request update of the FPA and AUX temperature. */ GUI_EVENT_REQUEST_UPTIME, /**< Request update of the uptime. */ GUI_EVENT_UPDATE_INFO, /**< Update the information screen. */ @@ -76,6 +77,8 @@ enum { Data is transmitted in a App_GUI_Screenposition_t structure. */ GUI_EVENT_REQUEST_SPOTMETER, /**< Request update of spotmeter data. */ GUI_EVENT_REQUEST_SCENE_STATISTICS, /**< Request update of scene statistics data. */ + GUI_EVENT_REQUEST_EMISSIVITY, /**< Request update of the emissivity setting. + Data is transmitted as a uint16_t (Emissivity multiplied by 100). */ }; /** @brief Structure representing a screen position. @@ -135,8 +138,8 @@ typedef struct { typedef struct { QueueHandle_t Lepton_FrameEventQueue; /**< Queue for Lepton frame ready events. */ Network_WiFi_STA_Config_t STA_Config; /**< WiFi STA configuration. */ + Network_Provisioning_Config_t Prov_Config; /**< Network provisioning configuration. */ Server_Config_t Server_Config; /**< Server configuration. */ - App_Settings_t Settings; /**< Application settings. */ } App_Context_t; #endif /* APPLICATION_H_ */ \ No newline at end of file diff --git a/main/Application/bitmap.h b/main/Application/bitmap.h deleted file mode 100644 index db35beb..0000000 --- a/main/Application/bitmap.h +++ /dev/null @@ -1,122 +0,0 @@ -/*****************************************************************************/ -/** -* @file bitmap.h -* -* Bitmap file format definitions. -* -* Copyright (C) Daniel Kampert, 2026 -* Website: www.kampis-elektroecke.de -* -* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* -* Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date        Changes
-* ----- ---  --------    -----------------------------------------------
-* 1.00  dk   11.12.2022  First release
-*
-* 
-******************************************************************************/ - -#ifndef BITMAP_H_ -#define BITMAP_H_ - -#include - -/** @brief Magic number for the \ref Bitmap_BMP_Header_t.bType field. - * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. - */ -#define BITMAP_MAGIC 0x4D42 - -/** @brief Byte offset for the blue color channel. - */ -#define BITMAP_BLUE_OFFSET 0 - -/** @brief Byte offset for the green color channel. - */ -#define BITMAP_GREEN_OFFSET 1 - -/** @brief Byte offset for the red color channel. - */ -#define BITMAP_RED_OFFSET 2 - -/** @brief Bitmap compressions of the \ref Bitmap_DIB_Header_t.biCompression field. - * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. - */ -typedef enum { - BITMAP_COMP_RGB = 0x00, /**< Uncompressed image data. */ - BITMAP_COMP_RLE8 = 0x01, /**< Run length coded for 8 bpp. Only allowed then \ref Bitmap_DIB_Header_t.biBitCount = 8 and \ref biBitCount.biHeight > 0. */ - BITMAP_COMP_RLE4 = 0x02, /**< Run length coded for 4 bpp. Only allowed then \ref Bitmap_DIB_Header_t.biBitCount = 4 and \ref biBitCount.biHeight > 0. */ - BITMAP_COMP_BITFIELDS = 0x03 /**< Uncompressed and customized image data. Only allowed then \ref Bitmap_DIB_Header_t.biBitCount = 16 or 32. */ -} Bitmap_Compression_t; - -/** @brief 16 bpp pixel object. - * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. - */ -typedef union { - struct { - uint8_t Blue: 5; /**< Blue color channel. */ - uint8_t Green: 6; /**< Green color channel. */ - uint8_t Red: 5; /**< Red color channel. */ - } BGR; - uint16_t Raw; /**< RGB raw data. */ -} __attribute__((packed)) Bitmap_16bpp_t; - -/** @brief 24 bpp pixel object. - * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. - */ -typedef union { - struct { - uint8_t Blue; /**< Blue color channel. */ - uint8_t Green; /**< Green color channel. */ - uint8_t Red; /**< Red color channel. */ - } BGR; - uint8_t Raw[3]; /**< RGB raw data. */ -} __attribute__((packed)) Bitmap_24bpp_t; - -/** @brief Bitmap file header. - * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. - */ -typedef struct { - uint16_t bType; /**< Contains the characters "BM". */ - uint32_t bfSize; /**< Size of the bitmap in bytes. */ - uint16_t bReserved; /**< Reserved. Default 0. */ - uint16_t bReserved1; /**< Reserved. Default 0. */ - uint32_t bfOffBits; /**< Image data offset. */ -} __attribute__((packed)) Bitmap_BMP_Header_t; - -/** @brief Bitmap information header. - * NOTE: Please check https://en.wikipedia.org/wiki/BMP_file_format if you need additional information. - */ -typedef struct { - uint32_t biSize; /**< Size of the \ref Bitmap_DIB_Header_t in bytes. */ - int32_t biWidth; /**< Width of the bitmap in pixel. The first byte contains the LSB, the last byte contains the MSB. */ - int32_t biHeight; /**< Height of the bitmap in pixel. The first byte contains the LSB, the last byte contains the MSB. - - Positive value: The image data start with the bottom row (bottom-up). - - Negative value: The image data start with the top row (top-down). */ - uint16_t biPlanes; /**< Always 1. */ - uint16_t biBitCount; /**< Color depth of the bitmap in bpp. */ - uint32_t biCompression; /**< Bitmap compression. See \ref Bitmap_Compression_t for more information. */ - uint32_t biSizeImage; /**< When \ref Bitmap_DIB_Header_t.biBitCount = BI_RGB: 0 or image size in bytes. - Else: Image size in bytes. */ - int32_t biXPelsPerMeter; /**< Horizontal resolution of the target output device. Is set to 0 mostly. */ - int32_t biYPelsPerMeter; /**< Vertical resolution of the target output device. Is set to 0 mostly. */ - uint32_t biClrUsed; /**< When \ref Bitmap_DIB_Header_t.biBitCount = 1: 0. - When \ref Bitmap_DIB_Header_t.biBitCount = 4 or 8: Color table entry count. If value is 0 the maximum count (2, 16 or 256) is used. - Else: Color table entry count (0 = no color table). */ - uint32_t biClrImportant; /**< When \ref Bitmap_DIB_Header_t.biBitCount = 1, 4 or 8: Number of colors used in the image. All colors of the color table when 0. - Else: When: Number of colors when a color table with all used colors is available. - Else: 0. */ -} __attribute__((packed)) Bitmap_DIB_Header_t; - -#endif /* BITMAP_H_ */ \ No newline at end of file diff --git a/main/main.cpp b/main/main.cpp index 33546e5..0d9d910 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -31,17 +31,7 @@ #include "Application/Manager/Devices/devicesManager.h" #include "Application/Manager/SD/sdManager.h" -static App_Context_t _App_Context = { - .Lepton_FrameEventQueue = NULL, - .Server_Config = { - .HTTP_Port = 80, - .MaxClients = 4, - .WSPingIntervalSec = 30, - .EnableCORS = true, - .API_Key = NULL, - }, - .Settings = {0}, -}; +static App_Context_t _App_Context; static const char *TAG = "main"; @@ -62,13 +52,7 @@ extern "C" void app_main(void) ESP_ERROR_CHECK(SettingsManager_Init()); - while(1) - { - vTaskDelay(pdMS_TO_TICKS(100)); - } - ESP_LOGI(TAG, "Loading settings..."); - ESP_ERROR_CHECK(SettingsManager_Get(&_App_Context.Settings)); ESP_LOGI(TAG, "Initializing application tasks..."); ESP_ERROR_CHECK(DevicesTask_Init()); @@ -76,10 +60,12 @@ extern "C" void app_main(void) /* Initialize Time Manager (requires RTC from DevicesManager) */ if (DevicesManager_GetRTCHandle(&RtcHandle) == ESP_OK) { if (TimeManager_Init(RtcHandle) == ESP_OK) { - TimeManager_SetTimezone(_App_Context.Settings.System.Timezone); - ESP_LOGI(TAG, "Time Manager initialized with CET timezone"); + App_Settings_System_t SystemSettings; + + SettingsManager_GetSystem(&SystemSettings); + TimeManager_SetTimezone(SystemSettings.Timezone); } else { - ESP_LOGW(TAG, "Failed to initialize Time Manager"); + ESP_LOGW(TAG, "Failed to initialize Time Manager!"); } } else { ESP_LOGW(TAG, "RTC not available, Time Manager initialization skipped"); From 94bf29341d8a5ce301e1cfe687f9cc0972af09a5 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Wed, 14 Jan 2026 17:03:52 +0100 Subject: [PATCH 05/26] Remove emoji from repository checkout step name --- .github/workflows/documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index fe2be94..8b81393 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -26,7 +26,7 @@ jobs: steps: - - name: 🧰 Repository Checkout + - name: Repository Checkout uses: actions/checkout@v4 with: fetch-depth: 0 From d182ef7ba3fe8ba3edf021d90c1b6bd7b8bea5bf Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Thu, 15 Jan 2026 22:51:44 +0100 Subject: [PATCH 06/26] Change provisioning from Bluetooth to WiFi SoftAP --- .github/copilot-instructions.md | 114 ++- .github/workflows/documentation.yml | 2 - README.md | 29 +- data/default_settings.json | 3 +- docs/NetworkManager.adoc | 8 +- main/Application/Manager/Devices/SPI/spi.cpp | 2 +- .../Manager/Network/DNS/dnsServer.cpp | 217 +++++ .../Manager/Network/DNS/dnsServer.h | 39 + .../Provisioning/provisionHandlers.cpp | 273 +++++++ .../Network/Provisioning/provisionHandlers.h | 54 ++ .../Network/Provisioning/provisioning.cpp | 215 +++-- .../Network/Provisioning/provisioning.h | 5 - .../{ => ImageEncoder}/imageEncoder.cpp | 20 +- .../Server/{ => ImageEncoder}/imageEncoder.h | 2 +- .../VISA/Private/visaCommands.cpp | 12 +- .../{ => Server}/VISA/Private/visaCommands.h | 0 .../Network/{ => Server}/VISA/visaServer.cpp | 58 +- .../Network/{ => Server}/VISA/visaServer.h | 9 +- .../Manager/Network/Server/Websocket.md | 2 +- .../Manager/Network/Server/http_server.cpp | 152 ++-- .../Manager/Network/Server/http_server.h | 2 +- .../Manager/Network/Server/server.h | 21 +- .../Network/Server/websocket_handler.cpp | 18 +- .../Network/Server/websocket_handler.h | 2 +- .../Manager/Network/networkManager.cpp | 50 +- .../Manager/Network/networkManager.h | 4 +- .../Manager/Network/networkTypes.h | 26 +- .../Private/settingsDefaultLoader.cpp | 59 +- .../Settings/Private/settingsJSONLoader.cpp | 100 ++- .../Manager/Settings/Private/settingsLoader.h | 32 +- .../Manager/Settings/settingsManager.cpp | 70 +- .../Manager/Settings/settingsManager.h | 6 + .../Manager/Settings/settingsTypes.h | 13 +- .../Application/Tasks/Devices/devicesTask.cpp | 2 +- .../Tasks/GUI/Export/fonts/ui_font_fa.c | 3 +- .../GUI/Export/images/ui_img_logo_80x44_png.c | 226 +++--- .../Export/images/ui_img_text_218x40_png.c | 550 ++++++------- .../Application/Tasks/GUI/Export/project.info | 6 +- .../Tasks/GUI/Export/screens/ui_Info.c | 104 +-- .../Tasks/GUI/Export/screens/ui_Info.h | 90 +-- .../Tasks/GUI/Export/screens/ui_Main.c | 93 +-- .../Tasks/GUI/Export/screens/ui_Main.h | 65 +- .../Tasks/GUI/Export/screens/ui_Menu.c | 24 +- .../Tasks/GUI/Export/screens/ui_Menu.h | 14 +- .../Tasks/GUI/Export/screens/ui_Splash.c | 24 +- .../Tasks/GUI/Export/screens/ui_Splash.h | 14 +- main/Application/Tasks/GUI/Export/ui.c | 10 +- main/Application/Tasks/GUI/Export/ui.h | 84 +- .../Tasks/GUI/Export/ui_events.cpp | 165 +--- .../Application/Tasks/GUI/Export/ui_helpers.c | 158 ++-- .../Application/Tasks/GUI/Export/ui_helpers.h | 282 +++---- .../Tasks/GUI/Private/guiHelper.cpp | 8 +- main/Application/Tasks/GUI/guiTask.cpp | 29 +- main/Application/Tasks/Lepton/leptonTask.cpp | 52 +- .../Application/Tasks/Network/networkTask.cpp | 184 +++-- main/Application/application.h | 9 +- main/CMakeLists.txt | 4 +- main/Kconfig.projbuild | 21 +- platformio.ini | 2 + sdkconfig.debug | 420 ++-------- ui/PyroVision.sll | 4 +- ui/PyroVision.spj | 739 +++++++++++------- ui/project.info | 4 +- webserver/provision.html | 308 ++++++++ 64 files changed, 3270 insertions(+), 2047 deletions(-) create mode 100644 main/Application/Manager/Network/DNS/dnsServer.cpp create mode 100644 main/Application/Manager/Network/DNS/dnsServer.h create mode 100644 main/Application/Manager/Network/Provisioning/provisionHandlers.cpp create mode 100644 main/Application/Manager/Network/Provisioning/provisionHandlers.h rename main/Application/Manager/Network/Server/{ => ImageEncoder}/imageEncoder.cpp (90%) rename main/Application/Manager/Network/Server/{ => ImageEncoder}/imageEncoder.h (98%) rename main/Application/Manager/Network/{ => Server}/VISA/Private/visaCommands.cpp (99%) rename main/Application/Manager/Network/{ => Server}/VISA/Private/visaCommands.h (100%) rename main/Application/Manager/Network/{ => Server}/VISA/visaServer.cpp (88%) rename main/Application/Manager/Network/{ => Server}/VISA/visaServer.h (90%) create mode 100644 webserver/provision.html diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index abae2e5..abd1c04 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -450,6 +450,117 @@ astyle --options=scripts/astyle.cfg "main/**/*.cpp" "main/**/*.h" --- +## Documentation Maintenance + +### AsciiDoc Documentation in `docs/` + +The project maintains comprehensive AsciiDoc documentation in the `docs/` directory. **When modifying code, always update the corresponding documentation.** + +#### Documentation Structure + +``` +docs/ +├── index.adoc # Overview and getting started +├── SettingsManager.adoc # Settings management system +├── NetworkManager.adoc # Network and communication +├── DeviceManager.adoc # Device drivers and peripherals +├── TimeManager.adoc # Time management and RTC +├── SDManager.adoc # SD card management +├── LeptonTask.adoc # Lepton camera task +├── GUITask.adoc # GUI task and LVGL +├── NetworkTask.adoc # Network task +└── VISAServer.adoc # VISA/SCPI server +``` + +#### When to Update Documentation + +**Always update the corresponding `.adoc` file when:** +- Adding new public API functions +- Modifying function signatures or parameters +- Changing behavior or semantics of existing functions +- Adding new modules or managers +- Modifying settings structure or event types +- Changing initialization requirements or dependencies +- Adding new features or capabilities +- Fixing bugs that affect documented behavior + +#### Documentation Update Pattern + +1. **Update Code First**: Make your code changes +2. **Update Documentation**: Modify the relevant `.adoc` file(s) +3. **Keep in Sync**: Ensure examples, function signatures, and descriptions match the code exactly +4. **Test Documentation**: Verify that code examples in documentation still compile and work + +#### Module-to-Documentation Mapping + +| Code Location | Documentation File | +|--------------|-------------------| +| `Manager/Settings/` | `SettingsManager.adoc` | +| `Manager/Network/` | `NetworkManager.adoc` | +| `Manager/Devices/` | `DeviceManager.adoc` | +| `Manager/Time/` | `TimeManager.adoc` | +| `Manager/SD/` | `SDManager.adoc` | +| `Tasks/Lepton/` | `LeptonTask.adoc` | +| `Tasks/GUI/` | `GUITask.adoc` | +| `Tasks/Network/` | `NetworkTask.adoc` | +| `Manager/Network/VISA/` | `VISAServer.adoc` | + +#### Documentation Style Guidelines + +- Use AsciiDoc syntax consistently +- Include code examples for new API functions +- Document all parameters, return values, and error codes +- Add diagrams for complex workflows (using PlantUML or similar) +- Keep examples realistic and tested +- Document thread-safety and RTOS considerations +- Include usage warnings and common pitfalls + +**Example Documentation Entry:** +```asciidoc +=== MyModule_DoSomething() + +[source,c] +---- +esp_err_t MyModule_DoSomething(uint8_t *p_Data, size_t Size); +---- + +Performs an important operation on the provided data buffer. + +**Parameters:** + +* `p_Data` - Pointer to data buffer (must not be NULL) +* `Size` - Size of data buffer in bytes + +**Return Values:** + +* `ESP_OK` - Operation successful +* `ESP_ERR_INVALID_ARG` - NULL pointer or invalid size +* `ESP_ERR_INVALID_STATE` - Module not initialized + +**Thread Safety:** This function is thread-safe and can be called from multiple tasks. + +**Example:** +[source,c] +---- +uint8_t Buffer[128]; +esp_err_t Error = MyModule_DoSomething(Buffer, sizeof(Buffer)); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Operation failed: %d", Error); +} +---- +``` + +#### Automated Documentation Build + +Documentation is automatically built and deployed via GitHub Actions workflow (`.github/workflows/documentation.yml`). The CI/CD pipeline: +- Builds all `.adoc` files to HTML and PDF +- Deploys to GitHub Pages: https://kampi.github.io/PyroVision/ +- Creates release artifacts with PDF documentation + +**Do not commit generated HTML/PDF files** - these are built automatically by the CI/CD pipeline. + +--- + ## Testing and Debugging ### Debugging @@ -521,6 +632,7 @@ astyle --options=scripts/astyle.cfg "main/**/*.cpp" "main/**/*.h" - Use appropriate log levels - Clean up resources on failure - Follow the established module patterns +- **Update corresponding AsciiDoc documentation when changing code** --- @@ -533,5 +645,5 @@ astyle --options=scripts/astyle.cfg "main/**/*.cpp" "main/**/*.h" --- -**Last Updated**: January 14, 2026 +**Last Updated**: January 15, 2026 **Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 8b81393..f6115ef 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -28,8 +28,6 @@ jobs: - name: Repository Checkout uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Install AsciiDoctor run: | diff --git a/README.md b/README.md index 1adac03..21ac99a 100644 --- a/README.md +++ b/README.md @@ -1 +1,28 @@ -# PyroVision - Firmware \ No newline at end of file +# PyroVision - Firmware + +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg?logo=opensourceinitiative)](https://www.gnu.org/licenses/gpl-3.0) +[![ESP-IDF](https://img.shields.io/badge/ESP--IDF-v5.1+-blue.svg)](https://github.com/espressif/esp-idf) +[![Documentation](https://img.shields.io/badge/User%20Guide-PDF-007ec6?longCache=true&style=flat&logo=asciidoctor&colorA=555555)](https://github.com/PyroVision-ThermalCam/Firmware) + +## Table of Contents + +- [PyroVision - Firmware](#pyrovision---firmware) + - [Table of Contents](#table-of-contents) + - [License](#license) + - [Maintainer](#maintainer) + +## License + +This project is licensed under the **GNU General Public License v3.0**. + +See [LICENSE](LICENSE) for full text. + +## Maintainer + +**Daniel Kampert** +📧 [DanielKampert@kampis-elektroecke.de](mailto:DanielKampert@kampis-elektroecke.de) +🌐 [www.kampis-elektroecke.de](https://www.kampis-elektroecke.de) + +--- + +**Contributions Welcome!** Please open issues or pull requests on GitHub. diff --git a/data/default_settings.json b/data/default_settings.json index 51de673..f47e77b 100644 --- a/data/default_settings.json +++ b/data/default_settings.json @@ -57,8 +57,7 @@ "autoConnect" : true }, "provisioning" : { - "name" : "PyroVision_PROV", - "pop" : "pyrovision123", + "name" : "PyroVision-PROV", "timeout" : 300 }, "display" : { diff --git a/docs/NetworkManager.adoc b/docs/NetworkManager.adoc index 80d5667..1732eef 100644 --- a/docs/NetworkManager.adoc +++ b/docs/NetworkManager.adoc @@ -146,7 +146,7 @@ typedef struct { uint16_t WSPingIntervalSec; // WebSocket ping interval (seconds) bool EnableCORS; // Enable CORS headers const char *API_Key; // Optional API key for authentication -} Server_Config_t; +} Network_Server_Config_t; ---- === Event System @@ -715,7 +715,7 @@ esp_err_t NetworkManager_StartServer(Server_Config_t *p_Config); [source,cpp] ---- -Server_Config_t server_cfg = { +Network_Server_Config_t server_cfg = { .HTTP_Port = 80, .MaxClients = 4, .WSPingIntervalSec = 30, @@ -916,7 +916,7 @@ void start_web_interface(void) SettingsManager_GetHTTPServer(&http_settings); // Configure server - Server_Config_t server_cfg = { + Network_Server_Config_t server_cfg = { .HTTP_Port = http_settings.Port, .MaxClients = http_settings.MaxClients, .WSPingIntervalSec = http_settings.WSPingIntervalSec, @@ -961,7 +961,7 @@ Network_WiFi_STA_Config_t wifi_config = { [source,cpp] ---- -Server_Config_t server_config = { +Network_Server_Config_t server_config = { .HTTP_Port = 80, // HTTP port (80 or 8080 typical) .MaxClients = 4, // Max simultaneous clients .WSPingIntervalSec = 30, // WebSocket keepalive (seconds) diff --git a/main/Application/Manager/Devices/SPI/spi.cpp b/main/Application/Manager/Devices/SPI/spi.cpp index 3f5ff29..1446650 100644 --- a/main/Application/Manager/Devices/SPI/spi.cpp +++ b/main/Application/Manager/Devices/SPI/spi.cpp @@ -51,7 +51,7 @@ esp_err_t SPIM_Init(const spi_bus_config_t *p_Config, spi_host_device_t Host, in { esp_err_t Error; - if ((p_Config == NULL) || (Host >= SOC_SPI_PERIPH_NUM)){ + if ((p_Config == NULL) || (Host >= SOC_SPI_PERIPH_NUM)) { return ESP_ERR_INVALID_ARG; } diff --git a/main/Application/Manager/Network/DNS/dnsServer.cpp b/main/Application/Manager/Network/DNS/dnsServer.cpp new file mode 100644 index 0000000..a5872f2 --- /dev/null +++ b/main/Application/Manager/Network/DNS/dnsServer.cpp @@ -0,0 +1,217 @@ +/* + * dnsServer.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Simple DNS server implementation for captive portal. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include "dnsServer.h" + +#define DNS_PORT 53 +#define DNS_BUFFER_SIZE 512 + +/** @brief DNS header structure. + */ +typedef struct __attribute__((packed)) +{ + uint16_t ID; /**< Identification */ + uint16_t Flags; /**< Flags */ + uint16_t QDCount; /**< Number of questions */ + uint16_t ANCount; /**< Number of answer RRs */ + uint16_t NSCount; /**< Number of authority RRs */ + uint16_t ARCount; /**< Number of additional RRs */ +} +DNS_Header_t; + +typedef struct { + bool isRunning; + int Socket; + TaskHandle_t Task; +} DNS_Server_State_t; + +static DNS_Server_State_t _DNS_Server_State; + +static const char *TAG = "DNS_Server"; + +/** @brief DNS server task. + * @param p_Arg Task argument (not used) + */ +static void DNS_Server_Task(void *p_Arg) +{ + uint8_t Buffer[DNS_BUFFER_SIZE]; + struct sockaddr_in ClientAddr; + socklen_t ClientAddrLen = sizeof(ClientAddr); + esp_netif_ip_info_t IP_Info; + esp_netif_t *AP_NetIF; + + /* Get AP IP address */ + AP_NetIF = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); + if (AP_NetIF == NULL) { + ESP_LOGE(TAG, "Failed to get AP netif!"); + vTaskDelete(NULL); + return; + } + + esp_netif_get_ip_info(AP_NetIF, &IP_Info); + + esp_task_wdt_add(NULL); + + ESP_LOGI(TAG, "DNS server started, redirecting all queries to " IPSTR, IP2STR(&IP_Info.ip)); + + while (_DNS_Server_State.isRunning) { + DNS_Header_t *Header; + int Length; + + esp_task_wdt_reset(); + + Length = recvfrom(_DNS_Server_State.Socket, Buffer, sizeof(Buffer), 0, + (struct sockaddr *)&ClientAddr, &ClientAddrLen); + + /* Timeout or no data - continue loop to reset watchdog */ + if (Length < 0) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + continue; + } + + ESP_LOGW(TAG, "recvfrom error: %d", errno); + + continue; + } + + if (Length < sizeof(DNS_Header_t)) { + continue; + } + + Header = (DNS_Header_t *)Buffer; + + Header->Flags = htons(0x8180); + Header->ANCount = Header->QDCount; + Header->NSCount = 0; + Header->ARCount = 0; + + uint8_t *ResponsePtr = Buffer + sizeof(DNS_Header_t); + while (ResponsePtr < (Buffer + Length) && (*ResponsePtr != 0)) { + ResponsePtr += *ResponsePtr + 1; + } + ResponsePtr += 5; + + uint16_t *AnswerPtr = (uint16_t *)ResponsePtr; + *AnswerPtr++ = htons(0xC00C); /* Name pointer to question */ + *AnswerPtr++ = htons(0x0001); /* Type A */ + *AnswerPtr++ = htons(0x0001); /* Class IN */ + *AnswerPtr++ = htons(0x0000); /* TTL high */ + *AnswerPtr++ = htons(0x003C); /* TTL low (60 seconds) */ + *AnswerPtr++ = htons(0x0004); /* Data length */ + + memcpy(AnswerPtr, &IP_Info.ip.addr, sizeof(IP_Info.ip.addr)); + ResponsePtr = (uint8_t *)AnswerPtr + sizeof(IP_Info.ip.addr); + + sendto(_DNS_Server_State.Socket, Buffer, ResponsePtr - Buffer, 0, + (struct sockaddr *)&ClientAddr, ClientAddrLen); + + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + ESP_LOGI(TAG, "DNS server task exiting"); + + esp_task_wdt_delete(NULL); + + vTaskDelete(NULL); +} + +esp_err_t DNS_Server_Start(void) +{ + struct sockaddr_in ServerAddr; + + if (_DNS_Server_State.isRunning) { + ESP_LOGW(TAG, "DNS server already running"); + return ESP_OK; + } + + /* Create UDP socket */ + _DNS_Server_State.Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (_DNS_Server_State.Socket < 0) { + ESP_LOGE(TAG, "Failed to create socket: %d!", errno); + return ESP_FAIL; + } + + /* Set socket timeout to allow watchdog reset */ + struct timeval Timeout; + Timeout.tv_sec = 1; + Timeout.tv_usec = 0; + if (setsockopt(_DNS_Server_State.Socket, SOL_SOCKET, SO_RCVTIMEO, &Timeout, sizeof(Timeout)) < 0) { + ESP_LOGW(TAG, "Failed to set socket timeout: %d", errno); + } + + /* Bind to DNS port */ + memset(&ServerAddr, 0, sizeof(ServerAddr)); + ServerAddr.sin_family = AF_INET; + ServerAddr.sin_addr.s_addr = INADDR_ANY; + ServerAddr.sin_port = htons(DNS_PORT); + + if (bind(_DNS_Server_State.Socket, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) { + ESP_LOGE(TAG, "Failed to bind socket: %d!", errno); + close(_DNS_Server_State.Socket); + return ESP_FAIL; + } + + /* Start DNS server task on CPU 1 to avoid blocking IDLE0 */ + _DNS_Server_State.isRunning = true; + + if (xTaskCreatePinnedToCore(DNS_Server_Task, "DNS_Server", 4096, NULL, 3, &_DNS_Server_State.Task, 1) != pdPASS) { + ESP_LOGE(TAG, "Failed to create DNS server task!"); + + close(_DNS_Server_State.Socket); + _DNS_Server_State.isRunning = false; + + return ESP_ERR_NO_MEM; + } + + ESP_LOGD(TAG, "DNS server initialized"); + + return ESP_OK; +} + +void DNS_Server_Stop(void) +{ + if (_DNS_Server_State.isRunning == false) { + return; + } + + _DNS_Server_State.isRunning = false; + + if (_DNS_Server_State.Socket >= 0) { + close(_DNS_Server_State.Socket); + _DNS_Server_State.Socket = -1; + } + + ESP_LOGD(TAG, "DNS server stopped"); +} diff --git a/main/Application/Manager/Network/DNS/dnsServer.h b/main/Application/Manager/Network/DNS/dnsServer.h new file mode 100644 index 0000000..4e649d1 --- /dev/null +++ b/main/Application/Manager/Network/DNS/dnsServer.h @@ -0,0 +1,39 @@ +/* + * dnsServer.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Simple DNS server for captive portal. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef DNSSERVER_H_ +#define DNSSERVER_H_ + +#include + +/** @brief Start DNS server for captive portal. + * Redirects all DNS queries to the ESP32's IP address. + * @return ESP_OK on success + */ +esp_err_t DNS_Server_Start(void); + +/** @brief Stop DNS server. + */ +void DNS_Server_Stop(void); + +#endif /* DNSSERVER_H_ */ diff --git a/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp b/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp new file mode 100644 index 0000000..ce3988c --- /dev/null +++ b/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp @@ -0,0 +1,273 @@ +/* + * provisionHandlers.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: HTTP provisioning endpoint handlers. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "provisionHandlers.h" +#include "../networkTypes.h" +#include "../networkManager.h" +#include "../../Settings/settingsManager.h" + +static const char *TAG = "ProvisionHandlers"; + +/* Embed HTML file */ +extern const uint8_t provision_html_start[] asm("_binary_provision_html_start"); +extern const uint8_t provision_html_end[] asm("_binary_provision_html_end"); + +/** @brief Send JSON response. + * @param p_Request HTTP request handle + * @param p_JSON JSON object to send + * @param StatusCode HTTP status code + * @return ESP_OK on success + */ +static esp_err_t send_JSON_Response(httpd_req_t *p_Request, cJSON *p_JSON, int StatusCode) +{ + esp_err_t Error; + + char *ResponseStr = cJSON_PrintUnformatted(p_JSON); + if (ResponseStr == NULL) { + httpd_resp_send_500(p_Request); + return ESP_ERR_NO_MEM; + } + + httpd_resp_set_status(p_Request, StatusCode == 200 ? HTTPD_200 : HTTPD_400); + httpd_resp_set_type(p_Request, "application/json"); + httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Origin", "*"); + + Error = httpd_resp_send(p_Request, ResponseStr, strlen(ResponseStr)); + + free(ResponseStr); + cJSON_Delete(p_JSON); + + return Error; +} + +esp_err_t Provision_Handler_Root(httpd_req_t *p_Request) +{ + httpd_resp_set_type(p_Request, "text/html"); + httpd_resp_set_hdr(p_Request, "Cache-Control", "no-cache"); + + return httpd_resp_send(p_Request, (const char *)provision_html_start, provision_html_end - provision_html_start); +} + +esp_err_t Provision_Handler_CaptivePortal(httpd_req_t *p_Request) +{ + char address[26] = {0}; + esp_netif_t *ap_netif; + + ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); + if (ap_netif != NULL) { + esp_netif_ip_info_t ip_info; + + if (esp_netif_get_ip_info(ap_netif, &ip_info) == ESP_OK) { + snprintf((char *)address, sizeof(address) - 1, "http://" IPSTR, IP2STR(&ip_info.ip)); + } else { + strncpy((char *)address, "http://192.168.4.1", sizeof(address) - 1); + } + } else { + strncpy((char *)address, "http://192.168.4.1", sizeof(address) - 1); + } + + ESP_LOGD(TAG, "Captive portal redirect to %s", address); + + /* Redirect captive portal detection to main page */ + httpd_resp_set_status(p_Request, "302 Found"); + httpd_resp_set_hdr(p_Request, "Location", address); + httpd_resp_send(p_Request, NULL, 0); + + return ESP_OK; +} + +esp_err_t Provision_Handler_Scan(httpd_req_t *p_Request) +{ + wifi_scan_config_t ScanConfig; + uint16_t APCount = 0; + esp_err_t Error; + + memset(&ScanConfig, 0, sizeof(ScanConfig)); + + /* Start async scan */ + Error = esp_wifi_scan_start(&ScanConfig, false); + if (Error != ESP_OK) { + cJSON *Response; + + ESP_LOGW(TAG, "Scan start failed: %d", Error); + + Response = cJSON_CreateObject(); + cJSON_AddArrayToObject(Response, "networks"); + + return send_JSON_Response(p_Request, Response, 200); + } + + /* Wait for scan to complete (max 10 seconds) */ + for (uint8_t i = 0; i < 100; i++) { + vTaskDelay(100 / portTICK_PERIOD_MS); + if (esp_wifi_scan_get_ap_num(&APCount) == ESP_OK) { + break; + } + } + + if (APCount == 0) { + cJSON *Response; + + Response = cJSON_CreateObject(); + cJSON_AddArrayToObject(Response, "networks"); + return send_JSON_Response(p_Request, Response, 200); + } + + wifi_ap_record_t *APList = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * APCount); + if (APList == NULL) { + httpd_resp_send_500(p_Request); + return ESP_ERR_NO_MEM; + } + + esp_wifi_scan_get_ap_records(&APCount, APList); + + cJSON *Response = cJSON_CreateObject(); + cJSON *Networks = cJSON_AddArrayToObject(Response, "networks"); + + for (uint16_t i = 0; i < APCount; i++) { + cJSON *Network = cJSON_CreateObject(); + cJSON_AddStringToObject(Network, "ssid", (const char *)APList[i].ssid); + cJSON_AddNumberToObject(Network, "rssi", APList[i].rssi); + cJSON_AddNumberToObject(Network, "channel", APList[i].primary); + cJSON_AddStringToObject(Network, "auth", + APList[i].authmode == WIFI_AUTH_OPEN ? "open" : "secured"); + + cJSON_AddItemToArray(Networks, Network); + } + + free(APList); + + return send_JSON_Response(p_Request, Response, 200); +} + +esp_err_t Provision_Handler_Connect(httpd_req_t *p_Request) +{ + char *Buffer = NULL; + cJSON *JSON = NULL; + cJSON *SSID_JSON = NULL; + cJSON *Password_JSON = NULL; + cJSON *Response = NULL; + esp_err_t Error = ESP_OK; + int Received; + Network_WiFi_Credentials_t Credentials; + + int ContentLen = p_Request->content_len; + if (ContentLen > 512) { + httpd_resp_send_err(p_Request, HTTPD_400_BAD_REQUEST, "Request too large"); + return ESP_FAIL; + } + + Buffer = (char *)heap_caps_malloc(ContentLen + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (Buffer == NULL) { + httpd_resp_send_500(p_Request); + return ESP_ERR_NO_MEM; + } + + Received = httpd_req_recv(p_Request, Buffer, ContentLen); + if (Received <= 0) { + free(Buffer); + httpd_resp_send_err(p_Request, HTTPD_400_BAD_REQUEST, "Failed to read request"); + return ESP_FAIL; + } + + Buffer[Received] = '\0'; + + JSON = cJSON_Parse(Buffer); + free(Buffer); + + if (JSON == NULL) { + httpd_resp_send_err(p_Request, HTTPD_400_BAD_REQUEST, "Invalid JSON"); + return ESP_FAIL; + } + + SSID_JSON = cJSON_GetObjectItem(JSON, "ssid"); + Password_JSON = cJSON_GetObjectItem(JSON, "password"); + + if ((cJSON_IsString(SSID_JSON) == false) || (cJSON_IsString(Password_JSON) == false)) { + cJSON_Delete(JSON); + httpd_resp_send_err(p_Request, HTTPD_400_BAD_REQUEST, "Missing ssid or password"); + return ESP_FAIL; + } + + const char *SSID = SSID_JSON->valuestring; + const char *Password = Password_JSON->valuestring; + + ESP_LOGI(TAG, "Provisioning request: SSID=%s", SSID); + + strncpy(Credentials.SSID, SSID, sizeof(Credentials.SSID) - 1); + strncpy(Credentials.Password, Password, sizeof(Credentials.Password) - 1); + + Error = NetworkManager_SetCredentials(&Credentials); + + Response = cJSON_CreateObject(); + + if (Error == ESP_OK) { + App_Settings_WiFi_t WiFiSettings; + esp_err_t SaveError; + + SettingsManager_GetWiFi(&WiFiSettings); + + strncpy(WiFiSettings.SSID, SSID, sizeof(WiFiSettings.SSID) - 1); + strncpy(WiFiSettings.Password, Password, sizeof(WiFiSettings.Password) - 1); + + SettingsManager_UpdateWiFi(&WiFiSettings); + + SaveError = SettingsManager_Save(); + if (SaveError == ESP_OK) { + ESP_LOGI(TAG, "WiFi credentials saved to NVS"); + + cJSON_AddBoolToObject(Response, "success", true); + cJSON_AddStringToObject(Response, "message", "Credentials saved, connecting to WiFi..."); + + send_JSON_Response(p_Request, Response, 200); + + /* Post event with short timeout to avoid blocking HTTP task */ + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_SUCCESS, NULL, 0, pdMS_TO_TICKS(100)); + } else { + ESP_LOGE(TAG, "Failed to save credentials to NVS: %d!", SaveError); + + cJSON_AddBoolToObject(Response, "success", false); + cJSON_AddStringToObject(Response, "error", "NVS storage full, please reset device"); + send_JSON_Response(p_Request, Response, 500); + } + } else { + cJSON_AddBoolToObject(Response, "success", false); + cJSON_AddStringToObject(Response, "error", "Failed to save credentials"); + send_JSON_Response(p_Request, Response, 400); + } + + cJSON_Delete(JSON); + + return Error; +} diff --git a/main/Application/Manager/Network/Provisioning/provisionHandlers.h b/main/Application/Manager/Network/Provisioning/provisionHandlers.h new file mode 100644 index 0000000..f244984 --- /dev/null +++ b/main/Application/Manager/Network/Provisioning/provisionHandlers.h @@ -0,0 +1,54 @@ +/* + * provisionHandlers.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: HTTP provisioning endpoint handlers. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef PROVISIONHANDLERS_H_ +#define PROVISIONHANDLERS_H_ + +#include + +/** @brief Serve provision HTML page. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +esp_err_t Provision_Handler_Root(httpd_req_t *p_Request); + +/** @brief Handle WiFi scan request. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +esp_err_t Provision_Handler_Scan(httpd_req_t *p_Request); + +/** @brief Handle WiFi connect request. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +esp_err_t Provision_Handler_Connect(httpd_req_t *p_Request); + +/** @brief Handle captive portal detection. + * Responds to Android/iOS captive portal checks. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +esp_err_t Provision_Handler_CaptivePortal(httpd_req_t *p_Request); + +#endif /* PROVISIONHANDLERS_H_ */ diff --git a/main/Application/Manager/Network/Provisioning/provisioning.cpp b/main/Application/Manager/Network/Provisioning/provisioning.cpp index a3a488e..1534759 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.cpp +++ b/main/Application/Manager/Network/Provisioning/provisioning.cpp @@ -23,25 +23,27 @@ #include #include -#include +#include +#include #include -#include #include #include #include "../networkManager.h" +#include "../Server/server.h" +#include "../DNS/dnsServer.h" #include "provisioning.h" typedef struct { bool isInitialized; bool active; + bool use_captive_portal; char device_name[32]; char pop[32]; uint32_t timeout_sec; - TimerHandle_t timeout_timer; - TaskHandle_t network_task_handle; + esp_timer_handle_t timeout_timer; wifi_sta_config_t WiFi_STA_Config; bool hasCredentials; } Provisioning_State_t; @@ -51,13 +53,12 @@ static Provisioning_State_t _Provisioning_State; static const char *TAG = "Provisioning"; /** @brief Timeout timer callback. - * @param timer Timer handle + * @param p_Arg Timer argument */ -static void on_Timeout_Timer_Handler(TimerHandle_t p_Timer) +static void on_Timeout_Timer_Handler(void *p_Arg) { - if (_Provisioning_State.network_task_handle != NULL) { - xTaskNotify(_Provisioning_State.network_task_handle, 0x01, eSetBits); - } + ESP_LOGI(TAG, "Provisioning timeout reached"); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_TIMEOUT, NULL, 0, pdMS_TO_TICKS(100)); } /** @brief Provisioning event handler. @@ -70,7 +71,7 @@ static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t Event { switch (EventId) { case WIFI_PROV_START: { - ESP_LOGD(TAG, "Provisioning started"); + ESP_LOGI(TAG, "Provisioning started"); break; } case WIFI_PROV_CRED_RECV: { @@ -102,7 +103,7 @@ static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t Event ESP_LOGD(TAG, "Provisioning successful"); if (_Provisioning_State.timeout_timer != NULL) { - xTimerStop(_Provisioning_State.timeout_timer, 0); + esp_timer_stop(_Provisioning_State.timeout_timer); } memset(&Credentials, 0, sizeof(Credentials)); @@ -112,8 +113,6 @@ static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t Event strncpy(Credentials.SSID, (const char *)_Provisioning_State.WiFi_STA_Config.ssid, sizeof(Credentials.SSID) - 1); strncpy(Credentials.Password, (const char *)_Provisioning_State.WiFi_STA_Config.password, sizeof(Credentials.Password) - 1); - - ESP_LOGD(TAG, "Credentials - SSID: %s, Password: %s", Credentials.SSID, Credentials.Password); } else { ESP_LOGE(TAG, "No WiFi credentials available!"); } @@ -123,10 +122,9 @@ static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t Event break; } case WIFI_PROV_END: { - ESP_LOGD(TAG, "Provisioning ended"); + ESP_LOGI(TAG, "Provisioning ended"); wifi_prov_mgr_deinit(); - wifi_prov_scheme_ble_event_cb_free_btdm(NULL, WIFI_PROV_END, NULL); _Provisioning_State.active = false; @@ -157,7 +155,7 @@ static esp_err_t on_Custom_Data_Prov_Handler(uint32_t session_id, const uint8_t const char *response = "{\"device\":\"PyroVision\",\"version\":\"1.0\"}"; *p_OutLen = strlen(response); - *p_OutBuf = (uint8_t *)malloc(*p_OutLen); + *p_OutBuf = (uint8_t *)heap_caps_malloc(*p_OutLen, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (*p_OutBuf == NULL) { ESP_LOGE(TAG, "Failed to allocate response buffer!"); @@ -181,16 +179,19 @@ esp_err_t Provisioning_Init(Network_Provisioning_Config_t *p_Config) ESP_LOGD(TAG, "Initializing Provisioning Manager"); strncpy(_Provisioning_State.device_name, p_Config->Name, sizeof(_Provisioning_State.device_name) - 1); - strncpy(_Provisioning_State.pop, p_Config->PoP, sizeof(_Provisioning_State.pop) - 1); _Provisioning_State.timeout_sec = p_Config->Timeout; + _Provisioning_State.use_captive_portal = true; ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &on_Prov_Event, NULL)); - _Provisioning_State.timeout_timer = xTimerCreate("prov_timeout", - (_Provisioning_State.timeout_sec * 1000) / portTICK_PERIOD_MS, - pdFALSE, - NULL, - on_Timeout_Timer_Handler); + const esp_timer_create_args_t timer_args = { + .callback = on_Timeout_Timer_Handler, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "prov_timeout", + .skip_unhandled_events = false + }; + ESP_ERROR_CHECK(esp_timer_create(&timer_args, &_Provisioning_State.timeout_timer)); _Provisioning_State.isInitialized = true; @@ -212,7 +213,7 @@ void Provisioning_Deinit(void) wifi_prov_mgr_deinit(); if (_Provisioning_State.timeout_timer != NULL) { - xTimerDelete(_Provisioning_State.timeout_timer, portMAX_DELAY); + esp_timer_delete(_Provisioning_State.timeout_timer); _Provisioning_State.timeout_timer = NULL; } @@ -242,29 +243,118 @@ esp_err_t Provisioning_Start(void) ESP_LOGD(TAG, "Starting Provisioning"); - prov_config.scheme = wifi_prov_scheme_ble; + if (_Provisioning_State.use_captive_portal) { + uint8_t MAC[6]; + wifi_config_t Config; + Network_HTTP_Server_Config_t ServerConfig; + + ESP_LOGI(TAG, "Using captive portal provisioning"); + + NetworkManager_GetMAC(MAC); + + /* Create unique SSID */ + snprintf((char *)Config.ap.ssid, sizeof(Config.ap.ssid), + "%.26s-%02X%02X", _Provisioning_State.device_name, MAC[4], MAC[5]); + Config.ap.ssid_len = strlen((char *)Config.ap.ssid); + Config.ap.channel = 1; + Config.ap.authmode = WIFI_AUTH_OPEN; + Config.ap.max_connection = 4; + + ESP_LOGI(TAG, "Starting SoftAP with SSID: %s", Config.ap.ssid); + + /* Set APSTA mode to allow WiFi scanning while AP is active */ + Error = esp_wifi_set_mode(WIFI_MODE_APSTA); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set APSTA mode: %d!", Error); + return Error; + } + + Error = esp_wifi_set_config(WIFI_IF_AP, &Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set AP config: %d!", Error); + return Error; + } + + Error = esp_wifi_start(); + if ((Error != ESP_OK) && (Error != ESP_ERR_WIFI_STATE)) { + ESP_LOGE(TAG, "Failed to start WiFi: %d!", Error); + return Error; + } + + vTaskDelay(100 / portTICK_PERIOD_MS); + + /* Start HTTP server with minimal configuration for provisioning */ + ServerConfig.Port = 80; + ServerConfig.MaxClients = 1; /* Only one client for provisioning */ + ServerConfig.EnableCORS = true; + ServerConfig.API_Key = NULL; + + /* Initialize HTTP server first (without WebSocket) */ + Error = HTTP_Server_Init(&ServerConfig); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to init HTTP server: 0x%x!", Error); + + esp_wifi_stop(); + + return Error; + } + + Error = HTTP_Server_Start(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to start HTTP server: 0x%x!", Error); + + HTTP_Server_Deinit(); + esp_wifi_stop(); + + return Error; + } + + /* Start DNS server for captive portal */ + Error = DNS_Server_Start(); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to start DNS server: %d!", Error); + /* Continue anyway, DNS is not critical */ + } + + _Provisioning_State.active = true; + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STARTED, NULL, 0, portMAX_DELAY); + + /* Start timeout timer */ + if (_Provisioning_State.timeout_timer != NULL) { + esp_timer_start_once(_Provisioning_State.timeout_timer, _Provisioning_State.timeout_sec * 1000000ULL); + } + + /* Get and log the actual AP IP address */ + esp_netif_t *ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); + if (ap_netif != NULL) { + esp_netif_ip_info_t ip_info; + if (esp_netif_get_ip_info(ap_netif, &ip_info) == ESP_OK) { + ESP_LOGI(TAG, "Captive portal started at http://" IPSTR, IP2STR(&ip_info.ip)); + } else { + ESP_LOGI(TAG, "Captive portal started at http://192.168.4.1"); + } + } else { + ESP_LOGI(TAG, "Captive portal started at http://192.168.4.1"); + } + + return ESP_OK; + } + + /* Use ESP Provisioning API (original protobuf method) */ + prov_config.scheme = wifi_prov_scheme_softap; prov_config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; prov_config.app_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; Error = wifi_prov_mgr_init(prov_config); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to init Provisioning: %d!", Error); - return Error; - } - if (strlen(_Provisioning_State.pop) > 0) { - pop = _Provisioning_State.pop; + return Error; } - esp_wifi_get_mac(WIFI_IF_STA, mac); + NetworkManager_GetMAC(mac); snprintf(service_name, sizeof(service_name), "%.26s_%02X%02X", _Provisioning_State.device_name, mac[4], mac[5]); - uint8_t custom_service_uuid[] = { - 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, - 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, - }; - wifi_prov_scheme_ble_set_service_uuid(custom_service_uuid); - /* Register custom endpoint */ wifi_prov_mgr_endpoint_create("custom-data"); @@ -272,7 +362,9 @@ esp_err_t Provisioning_Start(void) pop, service_name, NULL); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to start provisioning: %d!", Error); + wifi_prov_mgr_deinit(); + return Error; } @@ -282,7 +374,7 @@ esp_err_t Provisioning_Start(void) esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STARTED, NULL, 0, portMAX_DELAY); if (_Provisioning_State.timeout_timer != NULL) { - xTimerStart(_Provisioning_State.timeout_timer, 0); + esp_timer_start_once(_Provisioning_State.timeout_timer, _Provisioning_State.timeout_sec * 1000000ULL); } ESP_LOGD(TAG, "Provisioning started. Service name: %s", service_name); @@ -296,32 +388,50 @@ esp_err_t Provisioning_Stop(void) return ESP_OK; } - ESP_LOGD(TAG, "Stopping Provisioning"); + ESP_LOGI(TAG, "Stopping Provisioning"); - if (_Provisioning_State.timeout_timer != NULL) { - xTimerStop(_Provisioning_State.timeout_timer, 0); - } + _Provisioning_State.active = false; - wifi_prov_mgr_stop_provisioning(); + if (_Provisioning_State.use_captive_portal) { + ESP_LOGD(TAG, "Stopping DNS server"); + DNS_Server_Stop(); - _Provisioning_State.active = false; + ESP_LOGD(TAG, "Stopping HTTP server"); + HTTP_Server_Stop(); + + /* Stop WiFi completely - this closes all sockets and makes httpd_stop return quickly */ + ESP_LOGD(TAG, "Stopping WiFi"); + esp_wifi_stop(); + + /* Small delay for WiFi to fully stop */ + vTaskDelay(50 / portTICK_PERIOD_MS); + + HTTP_Server_Deinit(); - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STOPPED, NULL, 0, portMAX_DELAY); + ESP_LOGD(TAG, "Provisioning stopped"); + } else { + if (_Provisioning_State.timeout_timer != NULL) { + esp_timer_stop(_Provisioning_State.timeout_timer); + } + wifi_prov_mgr_stop_provisioning(); + } + + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STOPPED, NULL, 0, pdMS_TO_TICKS(100)); return ESP_OK; } bool Provisioning_isProvisioned(void) { - bool isProvisioned = false; - wifi_prov_mgr_config_t config; + bool isProvisioned; + wifi_prov_mgr_config_t Config; - memset(&config, 0, sizeof(wifi_prov_mgr_config_t)); + memset(&Config, 0, sizeof(wifi_prov_mgr_config_t)); - config.scheme = wifi_prov_scheme_ble; - config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; + Config.scheme = wifi_prov_scheme_softap; + Config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; - if (wifi_prov_mgr_init(config) == ESP_OK) { + if (wifi_prov_mgr_init(Config) == ESP_OK) { wifi_prov_mgr_is_provisioned(&isProvisioned); wifi_prov_mgr_deinit(); } @@ -343,9 +453,4 @@ esp_err_t Provisioning_Reset(void) bool Provisioning_isActive(void) { return _Provisioning_State.active; -} - -void Provisioning_SetNetworkTaskHandle(TaskHandle_t task_handle) -{ - _Provisioning_State.network_task_handle = task_handle; -} +} \ No newline at end of file diff --git a/main/Application/Manager/Network/Provisioning/provisioning.h b/main/Application/Manager/Network/Provisioning/provisioning.h index 1b91f63..61ae289 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.h +++ b/main/Application/Manager/Network/Provisioning/provisioning.h @@ -64,9 +64,4 @@ esp_err_t Provisioning_Reset(void); */ bool Provisioning_isActive(void); -/** @brief Set network task handle for timeout notification. - * @param task_handle Network task handle - */ -void Provisioning_SetNetworkTaskHandle(TaskHandle_t task_handle); - #endif /* PROVISIONING_H_ */ diff --git a/main/Application/Manager/Network/Server/imageEncoder.cpp b/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp similarity index 90% rename from main/Application/Manager/Network/Server/imageEncoder.cpp rename to main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp index 9441c6e..5b41e8a 100644 --- a/main/Application/Manager/Network/Server/imageEncoder.cpp +++ b/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp @@ -64,8 +64,8 @@ static const uint8_t (*ImageEncoder_GetPalette(Server_Palette_t palette))[3] { * @return ESP_OK on success */ static esp_err_t ImageEncoder_ApplyPalette(const Network_Thermal_Frame_t *p_Frame, - Server_Palette_t palette, - uint8_t *p_Output) + Server_Palette_t palette, + uint8_t *p_Output) { if ((p_Frame == NULL) || (p_Output == NULL) || (p_Frame->buffer == NULL)) { return ESP_ERR_INVALID_ARG; @@ -85,7 +85,7 @@ static esp_err_t ImageEncoder_ApplyPalette(const Network_Thermal_Frame_t *p_Fram * @return ESP_OK on success */ static esp_err_t ImageEncoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, uint16_t height, - uint8_t quality, Network_Encoded_Image_t *p_Encoded) + uint8_t quality, Network_Encoded_Image_t *p_Encoded) { jpeg_enc_config_t enc_config = { .width = width, @@ -140,7 +140,7 @@ esp_err_t ImageEncoder_Init(uint8_t Quality) return ESP_OK; } - ESP_LOGI(TAG, "Initializing image encoder, quality=%d", Quality); + ESP_LOGD(TAG, "Initializing image encoder, quality=%d", Quality); _Encoder_State.JpegQuality = Quality; if (_Encoder_State.JpegQuality < 1) { @@ -164,13 +164,13 @@ void ImageEncoder_Deinit(void) _Encoder_State.isInitialized = false; - ESP_LOGI(TAG, "Image encoder deinitialized"); + ESP_LOGD(TAG, "Image encoder deinitialized"); } esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, - Network_ImageFormat_t Format, - Server_Palette_t Palette, - Network_Encoded_Image_t *p_Encoded) + Network_ImageFormat_t Format, + Server_Palette_t Palette, + Network_Encoded_Image_t *p_Encoded) { esp_err_t Error; @@ -197,7 +197,7 @@ esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, switch (Format) { case NETWORK_IMAGE_FORMAT_JPEG: { Error = ImageEncoder_EncodeJPEG(rgb_buffer, p_Frame->width, p_Frame->height, - _Encoder_State.JpegQuality, p_Encoded); + _Encoder_State.JpegQuality, p_Encoded); break; } case NETWORK_IMAGE_FORMAT_PNG: { @@ -248,5 +248,5 @@ void ImageEncoder_SetQuality(uint8_t Quality) _Encoder_State.JpegQuality = 100; } - ESP_LOGI(TAG, "JPEG quality set to %d", _Encoder_State.JpegQuality); + ESP_LOGD(TAG, "JPEG quality set to %d", _Encoder_State.JpegQuality); } diff --git a/main/Application/Manager/Network/Server/imageEncoder.h b/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.h similarity index 98% rename from main/Application/Manager/Network/Server/imageEncoder.h rename to main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.h index 6377fbb..2952760 100644 --- a/main/Application/Manager/Network/Server/imageEncoder.h +++ b/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.h @@ -26,7 +26,7 @@ #include -#include "../networkTypes.h" +#include "../../networkTypes.h" /** @brief Initialize the image encoder. * @param Quality JPEG quality (1-100) diff --git a/main/Application/Manager/Network/VISA/Private/visaCommands.cpp b/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp similarity index 99% rename from main/Application/Manager/Network/VISA/Private/visaCommands.cpp rename to main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp index 217b109..52f5e54 100644 --- a/main/Application/Manager/Network/VISA/Private/visaCommands.cpp +++ b/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp @@ -21,14 +21,15 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ +#include +#include +#include + #include #include #include #include -#include -#include - #include "visaCommands.h" #include "sdkconfig.h" @@ -92,11 +93,14 @@ static int VISA_ParseCommand(char *Command, char **Tokens, int MaxTokens) */ static int VISA_CMD_IDN(char *Response, size_t MaxLen) { + return 0; + /* return snprintf(Response, MaxLen, "%s,%s,%s,%u.%u.%u\n", CONFIG_NETWORK_VISA_DEVICE_MANUFACTURER, CONFIG_NETWORK_VISA_DEVICE_MODEL, CONFIG_NETWORK_VISA_DEVICE_SERIAL, PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, PYROVISION_VERSION_BUILD); + */ } /** @brief *RST - Reset device @@ -226,7 +230,7 @@ static int VISA_CMD_SENS_IMG_DATA(char *Response, size_t MaxLen) /* Format: # where n = digits in length */ /* Example with dummy data */ - uint8_t *image_data = (uint8_t *)malloc(1024); + uint8_t *image_data = (uint8_t *)heap_caps_malloc(1024, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (image_data == NULL) { VISA_PushError(SCPI_ERROR_OUT_OF_MEMORY); return SCPI_ERROR_OUT_OF_MEMORY; diff --git a/main/Application/Manager/Network/VISA/Private/visaCommands.h b/main/Application/Manager/Network/Server/VISA/Private/visaCommands.h similarity index 100% rename from main/Application/Manager/Network/VISA/Private/visaCommands.h rename to main/Application/Manager/Network/Server/VISA/Private/visaCommands.h diff --git a/main/Application/Manager/Network/VISA/visaServer.cpp b/main/Application/Manager/Network/Server/VISA/visaServer.cpp similarity index 88% rename from main/Application/Manager/Network/VISA/visaServer.cpp rename to main/Application/Manager/Network/Server/VISA/visaServer.cpp index 05d0c78..447bcde 100644 --- a/main/Application/Manager/Network/VISA/visaServer.cpp +++ b/main/Application/Manager/Network/Server/VISA/visaServer.cpp @@ -37,7 +37,6 @@ static const char *TAG = "VISA-Server"; -/** @brief VISA server state */ typedef struct { int ListenSocket; /**< Listening socket */ TaskHandle_t ServerTask; /**< Server task handle */ @@ -46,7 +45,7 @@ typedef struct { SemaphoreHandle_t Mutex; /**< Thread safety mutex */ } VISA_Server_State_t; -static VISA_Server_State_t _VISA_Server_State = {0}; +static VISA_Server_State_t _VISA_Server_State; /** @brief Process VISA command and generate response * @param Command Received command string @@ -73,11 +72,10 @@ static int VISA_ProcessCommand(const char *Command, char *Response, size_t MaxLe cmd_buffer[--len] = '\0'; } - /* Process command */ return VISACommands_Execute(cmd_buffer, Response, MaxLen); } -/** @brief Handle client connection +/** @brief Handle client connection. * @param ClientSocket Client socket descriptor */ static void VISA_HandleClient(int ClientSocket) @@ -95,9 +93,11 @@ static void VISA_HandleClient(int ClientSocket) ESP_LOGI(TAG, "Client connected"); while (_VISA_Server_State.isRunning) { + int len; + memset(rx_buffer, 0, sizeof(rx_buffer)); - int len = recv(ClientSocket, rx_buffer, sizeof(rx_buffer) - 1, 0); + len = recv(ClientSocket, rx_buffer, sizeof(rx_buffer) - 1, 0); if (len < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { @@ -122,12 +122,16 @@ static void VISA_HandleClient(int ClientSocket) int response_len = VISA_ProcessCommand(rx_buffer, tx_buffer, sizeof(tx_buffer)); if (response_len > 0) { + int sent; + /* Send response */ - int sent = send(ClientSocket, tx_buffer, response_len, 0); + sent = send(ClientSocket, tx_buffer, response_len, 0); if (sent < 0) { - ESP_LOGE(TAG, "send failed: errno %d", errno); + ESP_LOGE(TAG, "send failed: %d!", errno); + break; } + ESP_LOGD(TAG, "Sent %d bytes", sent); } else if (response_len < 0) { /* Error response */ @@ -140,11 +144,13 @@ static void VISA_HandleClient(int ClientSocket) ESP_LOGI(TAG, "Client connection closed"); } -/** @brief VISA server task +/** @brief VISA server task. * @param p_Args Task arguments (unused) */ static void VISA_ServerTask(void *p_Args) { + int opt = 1; + int Error; struct sockaddr_in dest_addr; dest_addr.sin_addr.s_addr = htonl(INADDR_ANY); @@ -153,30 +159,35 @@ static void VISA_ServerTask(void *p_Args) _VISA_Server_State.ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (_VISA_Server_State.ListenSocket < 0) { - ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); + ESP_LOGE(TAG, "Unable to create socket: %d!", errno); + _VISA_Server_State.isRunning = false; vTaskDelete(NULL); + return; } - int opt = 1; setsockopt(_VISA_Server_State.ListenSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - int err = bind(_VISA_Server_State.ListenSocket, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); - if (err != 0) { - ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); + Error = bind(_VISA_Server_State.ListenSocket, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); + if (Error != 0) { + ESP_LOGE(TAG, "Socket unable to bind: %d!", errno); + close(_VISA_Server_State.ListenSocket); _VISA_Server_State.isRunning = false; vTaskDelete(NULL); + return; } - err = listen(_VISA_Server_State.ListenSocket, VISA_MAX_CLIENTS); - if (err != 0) { - ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno); + Error = listen(_VISA_Server_State.ListenSocket, VISA_MAX_CLIENTS); + if (Error != 0) { + ESP_LOGE(TAG, "Error occurred during listen: %d!", errno); + close(_VISA_Server_State.ListenSocket); _VISA_Server_State.isRunning = false; vTaskDelete(NULL); + return; } @@ -185,10 +196,12 @@ static void VISA_ServerTask(void *p_Args) while (_VISA_Server_State.isRunning) { struct sockaddr_in source_addr; socklen_t addr_len = sizeof(source_addr); + int Socket; + char addr_str[16]; - int client_socket = accept(_VISA_Server_State.ListenSocket, (struct sockaddr *)&source_addr, &addr_len); + Socket = accept(_VISA_Server_State.ListenSocket, (struct sockaddr *)&source_addr, &addr_len); - if (client_socket < 0) { + if (Socket < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { continue; } @@ -198,12 +211,10 @@ static void VISA_ServerTask(void *p_Args) break; } - char addr_str[16]; inet_ntop(AF_INET, &source_addr.sin_addr, addr_str, sizeof(addr_str)); ESP_LOGI(TAG, "Client connected from %s:%d", addr_str, ntohs(source_addr.sin_port)); - /* Handle client in same task (simple single-client implementation) */ - VISA_HandleClient(client_socket); + VISA_HandleClient(Socket); } close(_VISA_Server_State.ListenSocket); @@ -214,7 +225,7 @@ static void VISA_ServerTask(void *p_Args) vTaskDelete(NULL); } -esp_err_t VISAServer_Init(void) +esp_err_t VISAServer_Init(const Network_VISA_Server_Config_t *p_Config) { esp_err_t Error; @@ -231,11 +242,12 @@ esp_err_t VISAServer_Init(void) return ESP_ERR_NO_MEM; } - /* Initialize command handler */ Error = VISACommands_Init(); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize command handler: 0x%x!", Error); + vSemaphoreDelete(_VISA_Server_State.Mutex); + return Error; } diff --git a/main/Application/Manager/Network/VISA/visaServer.h b/main/Application/Manager/Network/Server/VISA/visaServer.h similarity index 90% rename from main/Application/Manager/Network/VISA/visaServer.h rename to main/Application/Manager/Network/Server/VISA/visaServer.h index 0ec0808..2c97b65 100644 --- a/main/Application/Manager/Network/VISA/visaServer.h +++ b/main/Application/Manager/Network/Server/VISA/visaServer.h @@ -28,6 +28,8 @@ #include #include +#include "../../networkTypes.h" + /** @brief VISA server configuration */ #define VISA_SERVER_PORT 5025 /**< Standard VISA/SCPI port */ #define VISA_MAX_COMMAND_LENGTH 256 /**< Maximum command length */ @@ -47,10 +49,11 @@ typedef enum { VISA_ERR_NOT_INITIALIZED = -7, /**< Server not initialized */ } VISA_Error_t; -/** @brief Initialize VISA server. - * @return VISA_OK on success, error code otherwise +/** @brief Initialize VISA server. + * @param p_Config Pointer to server configuration. + * @return VISA_OK on success, error code otherwise */ -esp_err_t VISAServer_Init(void); +esp_err_t VISAServer_Init(const Network_VISA_Server_Config_t *p_Config); /** @brief Deinitialize VISA server. * @return VISA_OK on success, error code otherwise diff --git a/main/Application/Manager/Network/Server/Websocket.md b/main/Application/Manager/Network/Server/Websocket.md index 07d684e..eaa5d5d 100644 --- a/main/Application/Manager/Network/Server/Websocket.md +++ b/main/Application/Manager/Network/Server/Websocket.md @@ -333,7 +333,7 @@ Image frames are sent as binary WebSocket messages (OPCODE 0x02): ```cpp /* Initialize WebSocket handler */ -esp_err_t WebSocket_Handler_Init(const Server_Config_t *p_Config); +esp_err_t WebSocket_Handler_Init(const Network_Server_Config_t *p_Config); /* Register handler with HTTP server */ esp_err_t WebSocket_Handler_Register(httpd_handle_t p_ServerHandle); diff --git a/main/Application/Manager/Network/Server/http_server.cpp b/main/Application/Manager/Network/Server/http_server.cpp index d3a399c..2d859cc 100644 --- a/main/Application/Manager/Network/Server/http_server.cpp +++ b/main/Application/Manager/Network/Server/http_server.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -33,8 +34,9 @@ #include #include "http_server.h" -#include "imageEncoder.h" #include "../networkTypes.h" +#include "ImageEncoder/imageEncoder.h" +#include "../Provisioning/provisionHandlers.h" #define HTTP_SERVER_API_BASE_PATH "/api/v1" #define HTTP_SERVER_API_KEY_HEADER "X-API-Key" @@ -43,7 +45,7 @@ typedef struct { bool isInitialized; bool isRunning; httpd_handle_t Handle; - Server_Config_t Config; + Network_HTTP_Server_Config_t Config; Network_Thermal_Frame_t *ThermalFrame; uint32_t RequestCount; uint32_t StartTime; @@ -117,7 +119,7 @@ static esp_err_t HTTP_Server_SendError(httpd_req_t *p_Request, int StatusCode, c esp_err_t Error; cJSON *Json = cJSON_CreateObject(); - if(Json == NULL) { + if (Json == NULL) { httpd_resp_send_err(p_Request, HTTPD_500_INTERNAL_SERVER_ERROR, "JSON allocation failed"); return ESP_FAIL; } @@ -142,7 +144,7 @@ static cJSON *HTTP_Server_ParseJSON(httpd_req_t *p_Request) return NULL; } - char *Buffer = (char *)malloc(ContentLen + 1); + char *Buffer = (char *)heap_caps_malloc(ContentLen + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (Buffer == NULL) { return NULL; } @@ -200,7 +202,7 @@ static esp_err_t HTTP_Handler_Time(httpd_req_t *p_Request) portMAX_DELAY); } - ESP_LOGI(TAG, "Time set to epoch: %f", epoch->valuedouble); + ESP_LOGD(TAG, "Time set to epoch: %f", epoch->valuedouble); cJSON_Delete(json); @@ -255,7 +257,6 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) return HTTP_Server_SendError(p_Request, 503, "Frame busy"); } - /* Encode image */ Error = ImageEncoder_Encode(_HTTPServer_State.ThermalFrame, format, palette, &encoded); xSemaphoreGive(_HTTPServer_State.ThermalFrame->mutex); @@ -284,7 +285,6 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) /* Send image data */ Error = httpd_resp_send(p_Request, (const char *)encoded.data, encoded.size); - /* Free encoded image */ ImageEncoder_Free(&encoded); return Error; @@ -296,6 +296,8 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) */ static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) { + esp_err_t Error; + _HTTPServer_State.RequestCount++; if (HTTP_Server_CheckAuth(p_Request) == false) { @@ -331,7 +333,7 @@ static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) cJSON_AddNumberToObject(sdcard, "free_mb", 0); cJSON_AddItemToObject(json, "sdcard", sdcard); - esp_err_t Error = HTTP_Server_SendJSON(p_Request, json, 200); + Error = HTTP_Server_SendJSON(p_Request, json, 200); cJSON_Delete(json); return Error; @@ -370,9 +372,10 @@ static esp_err_t HTTP_Handler_Update(httpd_req_t *p_Request) } /* Receive firmware data */ - char *buffer = (char *)malloc(1024); + char *buffer = (char *)heap_caps_malloc(1024, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (buffer == NULL) { esp_ota_abort(ota_handle); + return HTTP_Server_SendError(p_Request, 500, "Memory allocation failed"); } @@ -386,6 +389,7 @@ static esp_err_t HTTP_Handler_Update(httpd_req_t *p_Request) } free(buffer); esp_ota_abort(ota_handle); + return HTTP_Server_SendError(p_Request, 500, "Receive failed"); } @@ -394,6 +398,7 @@ static esp_err_t HTTP_Handler_Update(httpd_req_t *p_Request) free(buffer); esp_ota_abort(ota_handle); ESP_LOGE(TAG, "esp_ota_write failed: %d!", Error); + return HTTP_Server_SendError(p_Request, 500, "OTA write failed"); } @@ -496,28 +501,77 @@ static const httpd_uri_t _URI_Options = { .supported_subprotocol = NULL, }; -esp_err_t HTTP_Server_Init(const Server_Config_t *p_Config) -{ - esp_err_t Error; +static const httpd_uri_t _URI_Provision_Root = { + .uri = "/", + .method = HTTP_GET, + .handler = Provision_Handler_Root, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +static const httpd_uri_t _URI_Provision_Scan = { + .uri = HTTP_SERVER_API_BASE_PATH "/provision/scan", + .method = HTTP_GET, + .handler = Provision_Handler_Scan, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +static const httpd_uri_t _URI_Provision_Connect = { + .uri = HTTP_SERVER_API_BASE_PATH "/provision", + .method = HTTP_POST, + .handler = Provision_Handler_Connect, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; +static const httpd_uri_t _URI_CaptivePortal_Generate204 = { + .uri = "/generate_204", + .method = HTTP_GET, + .handler = Provision_Handler_CaptivePortal, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +static const httpd_uri_t _URI_CaptivePortal_Generate204_NoUnderscore = { + .uri = "/generate204", + .method = HTTP_GET, + .handler = Provision_Handler_CaptivePortal, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + +esp_err_t HTTP_Server_Init(const Network_HTTP_Server_Config_t *p_Config) +{ if (p_Config == NULL) { return ESP_ERR_INVALID_ARG; - } else if (_HTTPServer_State.isInitialized) { - ESP_LOGW(TAG, "Already initialized"); - return ESP_OK; } - Error = ESP_OK; + if (_HTTPServer_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized, updating config"); + memcpy(&_HTTPServer_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); + return ESP_OK; + } - ESP_LOGI(TAG, "Initializing HTTP server"); + ESP_LOGD(TAG, "Initializing HTTP server"); - memcpy(&_HTTPServer_State.Config, p_Config, sizeof(Server_Config_t)); + memcpy(&_HTTPServer_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); _HTTPServer_State.Handle = NULL; _HTTPServer_State.ThermalFrame = NULL; _HTTPServer_State.RequestCount = 0; _HTTPServer_State.isInitialized = true; - return Error; + return ESP_OK; } void HTTP_Server_Deinit(void) @@ -529,11 +583,13 @@ void HTTP_Server_Deinit(void) HTTP_Server_Stop(); _HTTPServer_State.isInitialized = false; - ESP_LOGI(TAG, "HTTP server deinitialized"); + ESP_LOGD(TAG, "HTTP server deinitialized"); } esp_err_t HTTP_Server_Start(void) { + esp_err_t Error; + if (_HTTPServer_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } else if (_HTTPServer_State.isRunning) { @@ -542,33 +598,43 @@ esp_err_t HTTP_Server_Start(void) } httpd_config_t config = HTTPD_DEFAULT_CONFIG(); - config.server_port = _HTTPServer_State.Config.HTTP_Port; - config.max_uri_handlers = 16; - config.max_open_sockets = _HTTPServer_State.Config.MaxClients; + config.server_port = _HTTPServer_State.Config.Port; + config.max_uri_handlers = 12; + + /* Use only 2 sockets for provisioning */ + config.max_open_sockets = 2; config.lru_purge_enable = true; config.uri_match_fn = httpd_uri_match_wildcard; - /* WebSocket stability configuration */ - config.recv_wait_timeout = 120; /* Increase receive timeout to 120 seconds */ - config.send_wait_timeout = 120; /* Increase send timeout to 120 seconds */ - config.keep_alive_enable = true; /* Enable TCP keep-alive */ - config.keep_alive_idle = 60; /* Start keep-alive after 60s of idle */ - config.keep_alive_interval = 10; /* Send keep-alive probes every 10s */ - config.keep_alive_count = 3; /* Close connection after 3 failed probes */ + /* Very short timeouts to allow quick shutdown */ + config.recv_wait_timeout = 1; + config.send_wait_timeout = 1; + config.keep_alive_enable = false; /* Disable keep-alive to reduce memory */ + + /* Increased stack and header size for Android captive portal requests */ + config.stack_size = 5120; + config.max_resp_headers = 8; + config.max_req_hdr_len = 1024; /* Android sends large headers */ - /* Increase stack size for handling large WebSocket frames */ - config.stack_size = 8192; /* Increase from default 4096 to handle JPEG encoding */ - config.max_resp_headers = 16; /* Increase header limit */ + /* Core affinity and priority - run on core 1 to avoid blocking IDLE0 */ + config.ctrl_port = 0; + config.core_id = 1; + config.task_priority = 3; - ESP_LOGI(TAG, "Starting HTTP server on port %d", config.server_port); + ESP_LOGD(TAG, "Starting HTTP server on port %d", config.server_port); - esp_err_t err = httpd_start(&_HTTPServer_State.Handle, &config); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to start HTTP server: %s", esp_err_to_name(err)); - return err; + Error = httpd_start(&_HTTPServer_State.Handle, &config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to start HTTP server: %d!", Error); + return Error; } /* Register URI handlers */ + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Root); + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Scan); + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Connect); + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_CaptivePortal_Generate204); + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_CaptivePortal_Generate204_NoUnderscore); httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Time); httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Image); httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Telemetry); @@ -581,7 +647,7 @@ esp_err_t HTTP_Server_Start(void) _HTTPServer_State.isRunning = true; _HTTPServer_State.StartTime = esp_timer_get_time() / 1000000; - ESP_LOGI(TAG, "HTTP server started"); + ESP_LOGD(TAG, "HTTP server started"); return ESP_OK; } @@ -592,14 +658,10 @@ esp_err_t HTTP_Server_Stop(void) return ESP_OK; } - ESP_LOGI(TAG, "Stopping HTTP server"); - - if (_HTTPServer_State.Handle != NULL) { - httpd_stop(_HTTPServer_State.Handle); - _HTTPServer_State.Handle = NULL; - } + ESP_LOGD(TAG, "Stopping HTTP server"); _HTTPServer_State.isRunning = false; + _HTTPServer_State.Handle = NULL; return ESP_OK; } diff --git a/main/Application/Manager/Network/Server/http_server.h b/main/Application/Manager/Network/Server/http_server.h index 77fa722..01580b6 100644 --- a/main/Application/Manager/Network/Server/http_server.h +++ b/main/Application/Manager/Network/Server/http_server.h @@ -33,7 +33,7 @@ * @param p_Config Pointer to server configuration. * @return ESP_OK on success. */ -esp_err_t HTTP_Server_Init(const Server_Config_t *p_Config); +esp_err_t HTTP_Server_Init(const Network_HTTP_Server_Config_t *p_Config); /** @brief Deinitialize the HTTP server. */ diff --git a/main/Application/Manager/Network/Server/server.h b/main/Application/Manager/Network/Server/server.h index 66a5629..5fe3515 100644 --- a/main/Application/Manager/Network/Server/server.h +++ b/main/Application/Manager/Network/Server/server.h @@ -26,13 +26,14 @@ #include "http_server.h" #include "websocket_handler.h" -#include "imageEncoder.h" +#include "VISA/visaServer.h" +#include "ImageEncoder/imageEncoder.h" -/** @brief Initialize the complete server (HTTP + WebSocket + Image Encoder). +/** @brief Initialize the complete server (HTTP + WebSocket + Image Encoder + VISA). * @param p_Config Pointer to server configuration * @return ESP_OK on success */ -static inline esp_err_t Server_Init(const Server_Config_t *p_Config) +static inline esp_err_t Server_Init(const Network_Server_Config_t *p_Config) { esp_err_t Error; @@ -42,19 +43,27 @@ static inline esp_err_t Server_Init(const Server_Config_t *p_Config) return Error; } - Error = HTTP_Server_Init(p_Config); + Error = HTTP_Server_Init(&p_Config->HTTP_Server); if (Error != ESP_OK) { ImageEncoder_Deinit(); return Error; } - Error = WebSocket_Handler_Init(p_Config); + Error = WebSocket_Handler_Init(&p_Config->HTTP_Server); if (Error != ESP_OK) { HTTP_Server_Deinit(); ImageEncoder_Deinit(); return Error; } + Error = VISAServer_Init(&p_Config->VISA_Server); + if (Error != ESP_OK) { + WebSocket_Handler_Deinit(); + HTTP_Server_Deinit(); + ImageEncoder_Deinit(); + return Error; + } + return ESP_OK; } @@ -62,6 +71,7 @@ static inline esp_err_t Server_Init(const Server_Config_t *p_Config) */ static inline void Server_Deinit(void) { + VISAServer_Deinit(); WebSocket_Handler_Deinit(); HTTP_Server_Deinit(); ImageEncoder_Deinit(); @@ -100,7 +110,6 @@ static inline esp_err_t Server_Start(void) */ static inline esp_err_t Server_Stop(void) { - /* Stop WebSocket broadcast task first */ WebSocket_Handler_StopTask(); return HTTP_Server_Stop(); diff --git a/main/Application/Manager/Network/Server/websocket_handler.cpp b/main/Application/Manager/Network/Server/websocket_handler.cpp index fc60dfa..a9db677 100644 --- a/main/Application/Manager/Network/Server/websocket_handler.cpp +++ b/main/Application/Manager/Network/Server/websocket_handler.cpp @@ -28,7 +28,7 @@ #include #include "websocket_handler.h" -#include "imageEncoder.h" +#include "ImageEncoder/imageEncoder.h" /** @brief WebSocket client state. */ @@ -47,7 +47,7 @@ typedef struct { typedef struct { bool isInitialized; httpd_handle_t ServerHandle; - Server_Config_t Config; + Network_HTTP_Server_Config_t Config; WS_Client_t Clients[WS_MAX_CLIENTS]; uint8_t ClientCount; Network_Thermal_Frame_t *ThermalFrame; @@ -320,7 +320,7 @@ static void WS_ProcessMessage(WS_Client_t *p_Client, const char *p_Data, size_t cJSON *cmd = cJSON_GetObjectItem(json, "cmd"); cJSON *data = cJSON_GetObjectItem(json, "data"); - if (!cJSON_IsString(cmd)) { + if (cJSON_IsString(cmd) == false) { ESP_LOGW(TAG, "Invalid message format from fd=%d", p_Client->fd); cJSON_Delete(json); return; @@ -375,7 +375,7 @@ static esp_err_t WS_Handler(httpd_req_t *p_Request) } if (Frame.len > 0) { - Frame.payload = (uint8_t *)malloc(Frame.len + 1); + Frame.payload = (uint8_t *)heap_caps_malloc(Frame.len + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (Frame.payload == NULL) { ESP_LOGE(TAG, "Failed to allocate frame buffer!"); return ESP_ERR_NO_MEM; @@ -464,7 +464,7 @@ static const httpd_uri_t _URI_WebSocket = { .supported_subprotocol = NULL, }; -esp_err_t WebSocket_Handler_Init(const Server_Config_t *p_Config) +esp_err_t WebSocket_Handler_Init(const Network_HTTP_Server_Config_t *p_Config) { if (p_Config == NULL) { return ESP_ERR_INVALID_ARG; @@ -477,7 +477,7 @@ esp_err_t WebSocket_Handler_Init(const Server_Config_t *p_Config) ESP_LOGI(TAG, "Initializing WebSocket handler"); - memcpy(&_WSHandler_State.Config, p_Config, sizeof(Server_Config_t)); + memcpy(&_WSHandler_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); memset(_WSHandler_State.Clients, 0, sizeof(_WSHandler_State.Clients)); _WSHandler_State.ClientCount = 0; _WSHandler_State.ThermalFrame = NULL; @@ -591,7 +591,7 @@ static void WS_BroadcastTask(void *p_Param) /* Encode frame ONCE for all clients (assume JPEG format for simplicity) */ if (xSemaphoreTake(_WSHandler_State.ThermalFrame->mutex, 50 / portTICK_PERIOD_MS) == pdTRUE) { esp_err_t err = ImageEncoder_Encode(_WSHandler_State.ThermalFrame, - NETWORK_IMAGE_FORMAT_JPEG, PALETTE_IRON, &Encoded); + NETWORK_IMAGE_FORMAT_JPEG, PALETTE_IRON, &Encoded); xSemaphoreGive(_WSHandler_State.ThermalFrame->mutex); if (err != ESP_OK) { @@ -626,7 +626,7 @@ static void WS_BroadcastTask(void *p_Param) xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); /* Re-validate client is still active and same FD */ - if (_WSHandler_State.Clients[client_idx].active && + if (_WSHandler_State.Clients[client_idx].active && _WSHandler_State.Clients[client_idx].fd == client_fd) { if (send_err == ESP_OK) { _WSHandler_State.Clients[client_idx].last_frame_time = Now; @@ -772,8 +772,6 @@ esp_err_t WebSocket_Handler_StartTask(void) return ESP_ERR_NO_MEM; } - ESP_LOGI(TAG, "WebSocket broadcast task started"); - return ESP_OK; } diff --git a/main/Application/Manager/Network/Server/websocket_handler.h b/main/Application/Manager/Network/Server/websocket_handler.h index 957ce8c..faa9d54 100644 --- a/main/Application/Manager/Network/Server/websocket_handler.h +++ b/main/Application/Manager/Network/Server/websocket_handler.h @@ -37,7 +37,7 @@ * @param p_Config Pointer to server configuration * @return ESP_OK on success */ -esp_err_t WebSocket_Handler_Init(const Server_Config_t *p_Config); +esp_err_t WebSocket_Handler_Init(const Network_HTTP_Server_Config_t *p_Config); /** @brief Deinitialize the WebSocket handler. */ diff --git a/main/Application/Manager/Network/networkManager.cpp b/main/Application/Manager/Network/networkManager.cpp index 5c4cb6e..d8cebe9 100644 --- a/main/Application/Manager/Network/networkManager.cpp +++ b/main/Application/Manager/Network/networkManager.cpp @@ -411,6 +411,7 @@ void NetworkManager_Deinit(void) esp_err_t NetworkManager_StartSTA(void) { wifi_config_t WifiConfig; + esp_err_t err; if (_Network_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; @@ -432,19 +433,56 @@ esp_err_t NetworkManager_StartSTA(void) strncpy((char *)WifiConfig.sta.password, _Network_Manager_State.STA_Config->Credentials.Password, sizeof(WifiConfig.sta.password) - 1); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &WifiConfig)); - ESP_ERROR_CHECK(esp_wifi_start()); + /* Set STA mode - WiFi might still be in APSTA mode from provisioning */ + err = esp_wifi_set_mode(WIFI_MODE_STA); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set WiFi mode: %s", esp_err_to_name(err)); + return err; + } + + err = esp_wifi_set_config(WIFI_IF_STA, &WifiConfig); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set WiFi config: %s", esp_err_to_name(err)); + return err; + } + + /* Start WiFi if not already running */ + err = esp_wifi_start(); + if (err != ESP_OK && err != ESP_ERR_WIFI_STATE) { + ESP_LOGE(TAG, "Failed to start WiFi: %s", esp_err_to_name(err)); + return err; + } + + ESP_LOGI(TAG, "WiFi started, initiating connection..."); + + /* Explicitly connect - STA_START event may not fire if WiFi was already running */ + err = esp_wifi_connect(); + if (err != ESP_OK && err != ESP_ERR_WIFI_CONN) { + ESP_LOGW(TAG, "esp_wifi_connect returned: %s (may be normal if already connecting)", esp_err_to_name(err)); + } _Network_Manager_State.State = NETWORK_STATE_CONNECTING; + ESP_LOGI(TAG, "WiFi connection initiated"); + return ESP_OK; } -esp_err_t NetworkManager_StartServer(Server_Config_t *p_Config) +esp_err_t NetworkManager_StartServer(Network_Server_Config_t *p_Config) { - ESP_ERROR_CHECK(Server_Init(p_Config)); - ESP_ERROR_CHECK(Server_Start()); + esp_err_t Error; + + Error = Server_Init(p_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize server: %d!", Error); + return Error; + } + + Error = Server_Start(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to start server: %d!", Error); + return Error; + } return ESP_OK; } diff --git a/main/Application/Manager/Network/networkManager.h b/main/Application/Manager/Network/networkManager.h index 742a5bc..3013f42 100644 --- a/main/Application/Manager/Network/networkManager.h +++ b/main/Application/Manager/Network/networkManager.h @@ -103,10 +103,10 @@ esp_err_t NetworkManager_SetCredentials(Network_WiFi_Credentials_t *p_Credential */ uint8_t NetworkManager_GetConnectedStations(void); -/** @brief Start the network server (HTTP + WebSocket). +/** @brief Start the network server (HTTP + Websocket + VISA). * @param p_Config Pointer to server configuration * @return ESP_OK on success */ -esp_err_t NetworkManager_StartServer(Server_Config_t *p_Config); +esp_err_t NetworkManager_StartServer(Network_Server_Config_t *p_Config); #endif /* NETWORKMANAGER_H_ */ diff --git a/main/Application/Manager/Network/networkTypes.h b/main/Application/Manager/Network/networkTypes.h index 18e5d7c..7777a25 100644 --- a/main/Application/Manager/Network/networkTypes.h +++ b/main/Application/Manager/Network/networkTypes.h @@ -190,8 +190,7 @@ typedef struct { /** @brief WiFi provisioning configuration. */ -typedef struct -{ +typedef struct { char Name[32]; char PoP[32]; uint32_t Timeout; @@ -205,24 +204,27 @@ typedef struct { uint16_t RetryInterval; } Network_WiFi_STA_Config_t; -/** @brief Server configuration. +/** @brief HTTP Server configuration. */ typedef struct { - uint16_t HTTP_Port; + uint16_t Port; uint8_t MaxClients; uint16_t WSPingIntervalSec; bool EnableCORS; const char *API_Key; -} Server_Config_t; +} Network_HTTP_Server_Config_t; + +/** @brief VISA Server configuration. + */ +typedef struct { + uint16_t Port; +} Network_VISA_Server_Config_t; -/** @brief Server status. +/** @brief Server configuration. */ typedef struct { - bool running; - uint8_t http_clients; - uint8_t ws_clients; - uint32_t requests_served; - uint32_t frames_streamed; -} Server_Status_t; + Network_HTTP_Server_Config_t HTTP_Server; + Network_VISA_Server_Config_t VISA_Server; +} Network_Server_Config_t; #endif /* NETWORK_TYPES_H_ */ diff --git a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp index f7e45cf..e3077db 100644 --- a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp @@ -71,67 +71,68 @@ void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settin /* No emissiviy values available */ p_Settings->Lepton.EmissivityCount = 1; p_Settings->Lepton.EmissivityPresets[0].Value = 100.0f; - strncpy(p_Settings->Lepton.EmissivityPresets[0].Description, "Unknown", sizeof(p_Settings->Lepton.EmissivityPresets[0].Description)); + strncpy(p_Settings->Lepton.EmissivityPresets[0].Description, "Unknown", + sizeof(p_Settings->Lepton.EmissivityPresets[0].Description)); } -void SettingsManager_InitDefaults(App_Settings_t *p_Settings) +void SettingsManager_InitDefaults(SettingsManager_State_t *p_State) { - memset(p_Settings, 0, sizeof(App_Settings_t)); - - SettingsManager_InitDefaultDisplay(p_Settings); - SettingsManager_InitDefaultProvisioning(p_Settings); - SettingsManager_InitDefaultWiFi(p_Settings); - SettingsManager_InitDefaultSystem(p_Settings); - SettingsManager_InitDefaultLepton(p_Settings); - SettingsManager_InitDefaultHTTPServer(p_Settings); - SettingsManager_InitDefaultVISAServer(p_Settings); + memset(&p_State->Settings, 0, sizeof(App_Settings_t)); + + SettingsManager_InitDefaultDisplay(&p_State->Settings); + SettingsManager_InitDefaultProvisioning(&p_State->Settings); + SettingsManager_InitDefaultWiFi(&p_State->Settings); + SettingsManager_InitDefaultSystem(p_State); + SettingsManager_InitDefaultLepton(&p_State->Settings); + SettingsManager_InitDefaultHTTPServer(&p_State->Settings); + SettingsManager_InitDefaultVISAServer(&p_State->Settings); } void SettingsManager_InitDefaultDisplay(App_Settings_t *p_Settings) { ESP_LOGW(TAG, "Loading default Display settings"); - p_Settings->Display.Brightness = 80; - p_Settings->Display.Timeout = 0; + p_Settings->Display.Brightness = SETTINGS_DISPLAY_DEFAULT_BRIGHTNESS; + p_Settings->Display.Timeout = SETTINGS_DISPLAY_DEFAULT_TIMEOUT; } void SettingsManager_InitDefaultProvisioning(App_Settings_t *p_Settings) { ESP_LOGW(TAG, "Loading default Provisioning settings"); - p_Settings->Provisioning.Timeout = 300; - strncpy(p_Settings->Provisioning.Name, "PyroVision-Provision", sizeof(p_Settings->Provisioning.Name)); - strncpy(p_Settings->Provisioning.PoP, "pyrovision", sizeof(p_Settings->Provisioning.PoP)); + p_Settings->Provisioning.Timeout = SETTINGS_PROVISIONING_DEFAULT_TIMEOUT; + strncpy(p_Settings->Provisioning.Name, SETTINGS_PROVISIONING_DEFAULT_NAME, sizeof(p_Settings->Provisioning.Name)); } void SettingsManager_InitDefaultWiFi(App_Settings_t *p_Settings) { ESP_LOGW(TAG, "Loading default WiFi settings"); - p_Settings->WiFi.AutoConnect = true; - p_Settings->WiFi.MaxRetries = 5; - p_Settings->WiFi.RetryInterval = 2000; + p_Settings->WiFi.AutoConnect = SETTINGS_WIFI_DEFAULT_AUTOCONNECT; + p_Settings->WiFi.MaxRetries = SETTINGS_WIFI_DEFAULT_MAX_RETRIES; + p_Settings->WiFi.RetryInterval = SETTINGS_WIFI_DEFAULT_RETRY_INTERVAL; strncpy(p_Settings->WiFi.SSID, "", sizeof(p_Settings->WiFi.SSID)); strncpy(p_Settings->WiFi.Password, "", sizeof(p_Settings->WiFi.Password)); } -void SettingsManager_InitDefaultSystem(App_Settings_t *p_Settings) +void SettingsManager_InitDefaultSystem(SettingsManager_State_t *p_State) { uint8_t Mac[6]; ESP_LOGW(TAG, "Loading default System settings"); if (esp_efuse_mac_get_default(Mac) == ESP_OK) { - snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision-%02X%02X%02X%02X%02X%02X", + snprintf(p_State->Settings.System.DeviceName, sizeof(p_State->Settings.System.DeviceName), + "PyroVision-%02X%02X%02X%02X%02X%02X", Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]); } else { - snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision"); + snprintf(p_State->Settings.System.DeviceName, sizeof(p_State->Settings.System.DeviceName), + SETTINGS_SYSTEM_DEFAULT_DEVICENAME); ESP_LOGW(TAG, "Failed to get MAC address, using default name"); } - p_Settings->System.SDCard_AutoMount = true; - p_Settings->System.Bluetooth_Enabled = false; - strncpy(p_Settings->System.Timezone, "CET-1CEST,M3.5.0,M10.5.0/3", sizeof(p_Settings->System.Timezone)); + p_State->Settings.System.SDCard_AutoMount = true; + strncpy(p_State->Settings.System.Timezone, SETTINGS_SYSTEM_DEFAULT_TIMEZONE, sizeof(p_State->Settings.System.Timezone)); } void SettingsManager_InitDefaultLepton(App_Settings_t *p_Settings) @@ -146,14 +147,14 @@ void SettingsManager_InitDefaultHTTPServer(App_Settings_t *p_Settings) { ESP_LOGW(TAG, "Loading default HTTP Server settings"); - p_Settings->HTTPServer.Port = 80; - p_Settings->HTTPServer.WSPingIntervalSec = 30; - p_Settings->HTTPServer.MaxClients = 4; + p_Settings->HTTPServer.Port = SETTINGS_DEFAULT_HTTP_PORT; + p_Settings->HTTPServer.WSPingIntervalSec = SETTINGS_DEFAULT_WS_PING_INTERVAL; + p_Settings->HTTPServer.MaxClients = SETTINGS_DEFAULT_HTTP_MAX_CLIENTS; } void SettingsManager_InitDefaultVISAServer(App_Settings_t *p_Settings) { ESP_LOGW(TAG, "Loading default VISA Server settings"); - p_Settings->VISAServer.Port = 5025; + p_Settings->VISAServer.Port = SETTINGS_DEFAULT_VISA_PORT; } \ No newline at end of file diff --git a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp index f2abe5b..96635f0 100644 --- a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp @@ -33,9 +33,9 @@ static const char *TAG = "settings_json_loader"; -/** @brief - * @param p_State - * @param p_JSON +/** @brief + * @param p_State + * @param p_JSON */ static void SettingsManager_LoadLepton(SettingsManager_State_t *p_State, const cJSON *p_JSON) { @@ -88,9 +88,9 @@ static void SettingsManager_LoadLepton(SettingsManager_State_t *p_State, const c } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief + * @param p_State + * @param p_JSON */ static void SettingsManager_LoadDisplay(SettingsManager_State_t *p_State, const cJSON *p_JSON) { @@ -101,20 +101,24 @@ static void SettingsManager_LoadDisplay(SettingsManager_State_t *p_State, const cJSON *brightness = cJSON_GetObjectItem(display, "brightness"); if (cJSON_IsNumber(brightness)) { p_State->Settings.Display.Brightness = (uint8_t)(brightness->valueint); + } else { + p_State->Settings.Display.Brightness = SETTINGS_DISPLAY_DEFAULT_BRIGHTNESS; } cJSON *timeout = cJSON_GetObjectItem(display, "timeout"); if (cJSON_IsNumber(timeout)) { p_State->Settings.Display.Timeout = (uint16_t)(timeout->valueint); + } else { + p_State->Settings.Display.Timeout = SETTINGS_DISPLAY_DEFAULT_TIMEOUT; } } else { SettingsManager_InitDefaultDisplay(&p_State->Settings); } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief + * @param p_State + * @param p_JSON */ static void SettingsManager_LoadWiFi(SettingsManager_State_t *p_State, const cJSON *p_JSON) { @@ -125,35 +129,45 @@ static void SettingsManager_LoadWiFi(SettingsManager_State_t *p_State, const cJS cJSON *maxRetries = cJSON_GetObjectItem(wifi, "maxRetries"); if (cJSON_IsNumber(maxRetries)) { p_State->Settings.WiFi.MaxRetries = (uint8_t)(maxRetries->valueint); + } else { + p_State->Settings.WiFi.MaxRetries = SETTINGS_WIFI_DEFAULT_MAX_RETRIES; } cJSON *retryInterval = cJSON_GetObjectItem(wifi, "retryInterval"); if (cJSON_IsNumber(retryInterval)) { p_State->Settings.WiFi.RetryInterval = (uint32_t)(retryInterval->valueint); + } else { + p_State->Settings.WiFi.RetryInterval = SETTINGS_WIFI_DEFAULT_RETRY_INTERVAL; } cJSON *autoConnect = cJSON_GetObjectItem(wifi, "autoConnect"); if (cJSON_IsBool(autoConnect)) { p_State->Settings.WiFi.AutoConnect = cJSON_IsTrue(autoConnect); + } else { + p_State->Settings.WiFi.AutoConnect = SETTINGS_WIFI_DEFAULT_AUTOCONNECT; } cJSON *ssid = cJSON_GetObjectItem(wifi, "ssid"); if (cJSON_IsString(ssid)) { strncpy(p_State->Settings.WiFi.SSID, ssid->valuestring, sizeof(p_State->Settings.WiFi.SSID)); + } else { + strncpy(p_State->Settings.WiFi.SSID, "", sizeof(p_State->Settings.WiFi.SSID)); } cJSON *password = cJSON_GetObjectItem(wifi, "password"); if (cJSON_IsString(password)) { strncpy(p_State->Settings.WiFi.Password, password->valuestring, sizeof(p_State->Settings.WiFi.Password)); + } else { + strncpy(p_State->Settings.WiFi.Password, "", sizeof(p_State->Settings.WiFi.Password)); } } else { SettingsManager_InitDefaultWiFi(&p_State->Settings); } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief + * @param p_State + * @param p_JSON */ static void SettingsManager_LoadProvisioning(SettingsManager_State_t *p_State, const cJSON *p_JSON) { @@ -164,25 +178,25 @@ static void SettingsManager_LoadProvisioning(SettingsManager_State_t *p_State, c cJSON *name = cJSON_GetObjectItem(provisioning, "name"); if (cJSON_IsString(name)) { strncpy(p_State->Settings.Provisioning.Name, name->valuestring, sizeof(p_State->Settings.Provisioning.Name)); - } - - cJSON *pop = cJSON_GetObjectItem(provisioning, "pop"); - if (cJSON_IsString(pop)) { - strncpy(p_State->Settings.Provisioning.PoP, pop->valuestring, sizeof(p_State->Settings.Provisioning.PoP)); + } else { + strncpy(p_State->Settings.Provisioning.Name, SETTINGS_PROVISIONING_DEFAULT_NAME, + sizeof(p_State->Settings.Provisioning.Name)); } cJSON *timeout = cJSON_GetObjectItem(provisioning, "timeout"); if (cJSON_IsNumber(timeout)) { p_State->Settings.Provisioning.Timeout = (uint32_t)(timeout->valueint); + } else { + p_State->Settings.Provisioning.Timeout = SETTINGS_PROVISIONING_DEFAULT_TIMEOUT; } } else { SettingsManager_InitDefaultProvisioning(&p_State->Settings); } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief + * @param p_State + * @param p_JSON */ static void SettingsManager_LoadSystem(SettingsManager_State_t *p_State, const cJSON *p_JSON) { @@ -193,15 +207,25 @@ static void SettingsManager_LoadSystem(SettingsManager_State_t *p_State, const c cJSON *timezone = cJSON_GetObjectItem(system, "timezone"); if (cJSON_IsString(timezone)) { strncpy(p_State->Settings.System.Timezone, timezone->valuestring, sizeof(p_State->Settings.System.Timezone)); + } else { + strncpy(p_State->Settings.System.Timezone, SETTINGS_SYSTEM_DEFAULT_TIMEZONE, sizeof(p_State->Settings.System.Timezone)); + } + + cJSON *devicename = cJSON_GetObjectItem(system, "devicename"); + if (cJSON_IsString(devicename)) { + strncpy(p_State->Settings.System.DeviceName, devicename->valuestring, sizeof(p_State->Settings.System.DeviceName)); + } else { + strncpy(p_State->Settings.System.DeviceName, SETTINGS_SYSTEM_DEFAULT_DEVICENAME, + sizeof(p_State->Settings.System.DeviceName)); } } else { - SettingsManager_InitDefaultSystem(&p_State->Settings); + SettingsManager_InitDefaultSystem(p_State); } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief + * @param p_State + * @param p_JSON */ static void SettingsManager_LoadHTTPServer(SettingsManager_State_t *p_State, const cJSON *p_JSON) { @@ -212,25 +236,31 @@ static void SettingsManager_LoadHTTPServer(SettingsManager_State_t *p_State, con cJSON *port = cJSON_GetObjectItem(http_server, "port"); if (cJSON_IsNumber(port)) { p_State->Settings.HTTPServer.Port = (uint16_t)(port->valueint); + } else { + p_State->Settings.HTTPServer.Port = SETTINGS_DEFAULT_HTTP_PORT; } cJSON *wsPingIntervalSec = cJSON_GetObjectItem(http_server, "wsPingIntervalSec"); if (cJSON_IsNumber(wsPingIntervalSec)) { p_State->Settings.HTTPServer.WSPingIntervalSec = (uint16_t)(wsPingIntervalSec->valueint); + } else { + p_State->Settings.HTTPServer.WSPingIntervalSec = SETTINGS_DEFAULT_WS_PING_INTERVAL; } cJSON *maxClients = cJSON_GetObjectItem(http_server, "maxClients"); if (cJSON_IsNumber(maxClients)) { p_State->Settings.HTTPServer.MaxClients = (uint8_t)(maxClients->valueint); + } else { + p_State->Settings.HTTPServer.MaxClients = SETTINGS_DEFAULT_HTTP_MAX_CLIENTS; } } else { SettingsManager_InitDefaultHTTPServer(&p_State->Settings); } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief + * @param p_State + * @param p_JSON */ static void SettingsManager_LoadVISAServer(SettingsManager_State_t *p_State, const cJSON *p_JSON) { @@ -241,6 +271,8 @@ static void SettingsManager_LoadVISAServer(SettingsManager_State_t *p_State, con cJSON *port = cJSON_GetObjectItem(visa_server, "port"); if (cJSON_IsNumber(port)) { p_State->Settings.VISAServer.Port = (uint16_t)(port->valueint); + } else { + p_State->Settings.VISAServer.Port = SETTINGS_DEFAULT_VISA_PORT; } } else { SettingsManager_InitDefaultVISAServer(&p_State->Settings); @@ -259,17 +291,17 @@ esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State) char *SettingsBuffer = NULL; long FileSize; esp_vfs_littlefs_conf_t LittleFS_Config = { - .base_path = "/littlefs", - .partition_label = "storage", - .format_if_mount_failed = true, - .read_only = true, - .dont_mount = false + .base_path = "/littlefs", + .partition_label = "storage", + .format_if_mount_failed = true, + .read_only = true, + .dont_mount = false }; Error = nvs_get_u8(p_State->NVS_Handle, "config_loaded", &ConfigLoaded); if ((Error == ESP_OK) && (ConfigLoaded == true)) { ESP_LOGD(TAG, "Default config already loaded, skipping"); - //return ESP_OK; + return ESP_OK; } ESP_LOGD(TAG, "Initializing LittleFS"); @@ -400,6 +432,6 @@ esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State) } ESP_LOGD(TAG, "Default config loaded and marked as valid"); - + return ESP_OK; } \ No newline at end of file diff --git a/main/Application/Manager/Settings/Private/settingsLoader.h b/main/Application/Manager/Settings/Private/settingsLoader.h index b4e080a..21f9f1f 100644 --- a/main/Application/Manager/Settings/Private/settingsLoader.h +++ b/main/Application/Manager/Settings/Private/settingsLoader.h @@ -36,12 +36,32 @@ #include "../settingsTypes.h" +#define SETTINGS_DEFAULT_VISA_PORT 5025 + +#define SETTINGS_DEFAULT_HTTP_PORT 80 +#define SETTINGS_DEFAULT_WS_PING_INTERVAL 30 +#define SETTINGS_DEFAULT_HTTP_MAX_CLIENTS 4 + +#define SETTINGS_SYSTEM_DEFAULT_DEVICENAME "PyroVision-Device" +#define SETTINGS_SYSTEM_DEFAULT_TIMEZONE "CET-1CEST,M3.5.0,M10.5.0/3" + +#define SETTINGS_PROVISIONING_DEFAULT_TIMEOUT 300 +#define SETTINGS_PROVISIONING_DEFAULT_NAME "PyroVision-Provision" + +#define SETTINGS_WIFI_DEFAULT_MAX_RETRIES 5 +#define SETTINGS_WIFI_DEFAULT_RETRY_INTERVAL 2000 +#define SETTINGS_WIFI_DEFAULT_AUTOCONNECT true + +#define SETTINGS_DISPLAY_DEFAULT_BRIGHTNESS 80 +#define SETTINGS_DISPLAY_DEFAULT_TIMEOUT 0 + /** @brief Settings Manager state. */ typedef struct { bool isInitialized; nvs_handle_t NVS_Handle; App_Settings_t Settings; + App_Settings_Info_t Info; SemaphoreHandle_t Mutex; } SettingsManager_State_t; @@ -61,10 +81,10 @@ void SettingsManager_InitDefaultLeptonROIs(App_Settings_t *p_Settings); */ void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settings); -/** @brief Initialize settings with factory defaults. - * @param p_Settings Pointer to settings structure +/** @brief Initialize settings with factory defaults. + * @param p_State Pointer to Settings Manager state structure */ -void SettingsManager_InitDefaults(App_Settings_t *p_Settings); +void SettingsManager_InitDefaults(SettingsManager_State_t *p_State); /** @brief Initialize Display settings with factory defaults. * @param p_Settings Pointer to settings structure @@ -81,10 +101,10 @@ void SettingsManager_InitDefaultProvisioning(App_Settings_t *p_Settings); */ void SettingsManager_InitDefaultWiFi(App_Settings_t *p_Settings); -/** @brief Initialize System settings with factory defaults. - * @param p_Settings Pointer to settings structure +/** @brief Initialize System settings with factory defaults. + * @param p_State Pointer to Settings Manager state structure */ -void SettingsManager_InitDefaultSystem(App_Settings_t *p_Settings); +void SettingsManager_InitDefaultSystem(SettingsManager_State_t *p_State); /** @brief Initialize Lepton settings with factory defaults. * @param p_Settings Pointer to settings structure diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index 1dd4163..98b3fd9 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -52,7 +52,7 @@ static SettingsManager_State_t _State; * @param p_Dst Pointer to destination settings structure in RAM * @param Size Size of the settings structure to copy * @param EventID Event identifier to emit after update - * @return ESP_OK on success + * @return ESP_OK on success */ static esp_err_t SettingsManager_Update(void* p_Src, void* p_Dst, size_t Size, int EventID) { @@ -75,6 +75,7 @@ static esp_err_t SettingsManager_Update(void* p_Src, void* p_Dst, size_t Size, i esp_err_t SettingsManager_Init(void) { + uint16_t Serial; esp_err_t Error; if (_State.isInitialized) { @@ -86,6 +87,16 @@ esp_err_t SettingsManager_Init(void) ESP_ERROR_CHECK(nvs_flash_init()); + Error = nvs_flash_init_partition("settings"); + if ((Error == ESP_ERR_NVS_NO_FREE_PAGES) || (Error == ESP_ERR_NVS_NEW_VERSION_FOUND)) { + ESP_LOGW(TAG, "Settings partition needs erase, erasing..."); + ESP_ERROR_CHECK(nvs_flash_erase_partition("settings")); + Error = nvs_flash_init_partition("settings"); + } else if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize settings partition: %d!", Error); + return Error; + } + _State.Mutex = xSemaphoreCreateMutex(); if (_State.Mutex == NULL) { ESP_LOGE(TAG, "Failed to create mutex!"); @@ -93,7 +104,7 @@ esp_err_t SettingsManager_Init(void) return ESP_ERR_NO_MEM; } - Error = nvs_open(SETTINGS_NVS_NAMESPACE, NVS_READWRITE, &_State.NVS_Handle); + Error = nvs_open_from_partition("settings", SETTINGS_NVS_NAMESPACE, NVS_READWRITE, &_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to open NVS handle: %d!", Error); @@ -104,6 +115,23 @@ esp_err_t SettingsManager_Init(void) _State.isInitialized = true; + /* Copy the read-only data */ + sprintf(_State.Info.FirmwareVersion, "%u.%u.%u", PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, + PYROVISION_VERSION_BUILD); + sprintf(_State.Info.Manufacturer, "%s", CONFIG_DEVICE_MANUFACTURER); + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + + /* Get the serial from NVS. Use a temporary variable to prevent alignment errors. */ + Error = nvs_get_u16(_State.NVS_Handle, "serial", &Serial); + _State.Info.Serial = Serial; + + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to get serial number from NVS: %d!. Using 0", Error); + _State.Info.Serial = 0; + } + xSemaphoreGive(_State.Mutex); + /* Load the settings from the NVS */ Error = SettingsManager_Load(&_State.Settings); if (Error != ESP_OK) { @@ -114,7 +142,7 @@ esp_err_t SettingsManager_Init(void) ESP_LOGW(TAG, "Failed to load default settings from JSON, using built-in defaults"); /* Use built-in defaults */ - SettingsManager_InitDefaults(&_State.Settings); + SettingsManager_InitDefaults(&_State); } /* Save the default settings to NVS */ @@ -229,6 +257,21 @@ esp_err_t SettingsManager_Save(void) return ESP_OK; } +esp_err_t SettingsManager_GetInfo(App_Settings_Info_t* p_Settings) +{ + if ( p_Settings == NULL ) { + return ESP_ERR_INVALID_ARG; + } else if (_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + xSemaphoreTake(_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_State.Info, sizeof(App_Settings_Info_t)); + xSemaphoreGive(_State.Mutex); + + return ESP_OK; +} + esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings) { if ( p_Settings == NULL ) { @@ -246,7 +289,8 @@ esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings) esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.Lepton, sizeof(App_Settings_Lepton_t), SETTINGS_EVENT_LEPTON_CHANGED); + return SettingsManager_Update(p_Settings, &_State.Settings.Lepton, sizeof(App_Settings_Lepton_t), + SETTINGS_EVENT_LEPTON_CHANGED); } esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t* p_Settings) @@ -266,7 +310,8 @@ esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t* p_Settings) esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t* p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.WiFi, sizeof(App_Settings_WiFi_t), SETTINGS_EVENT_WIFI_CHANGED); + return SettingsManager_Update(p_Settings, &_State.Settings.WiFi, sizeof(App_Settings_WiFi_t), + SETTINGS_EVENT_WIFI_CHANGED); } esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t* p_Settings) @@ -286,7 +331,8 @@ esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t* p_Setting esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t* p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.Provisioning, sizeof(App_Settings_Provisioning_t), SETTINGS_EVENT_PROVISIONING_CHANGED); + return SettingsManager_Update(p_Settings, &_State.Settings.Provisioning, sizeof(App_Settings_Provisioning_t), + SETTINGS_EVENT_PROVISIONING_CHANGED); } esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t* p_Settings) @@ -306,7 +352,8 @@ esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t* p_Settings) esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t* p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.Display, sizeof(App_Settings_Display_t), SETTINGS_EVENT_DISPLAY_CHANGED); + return SettingsManager_Update(p_Settings, &_State.Settings.Display, sizeof(App_Settings_Display_t), + SETTINGS_EVENT_DISPLAY_CHANGED); } esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t* p_Settings) @@ -326,7 +373,8 @@ esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t* p_Settings) esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t* p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.HTTPServer, sizeof(App_Settings_HTTP_Server_t), SETTINGS_EVENT_HTTP_SERVER_CHANGED); + return SettingsManager_Update(p_Settings, &_State.Settings.HTTPServer, sizeof(App_Settings_HTTP_Server_t), + SETTINGS_EVENT_HTTP_SERVER_CHANGED); } esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t* p_Settings) @@ -346,7 +394,8 @@ esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t* p_Settings) esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t* p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.VISAServer, sizeof(App_Settings_VISA_Server_t), SETTINGS_EVENT_VISA_SERVER_CHANGED); + return SettingsManager_Update(p_Settings, &_State.Settings.VISAServer, sizeof(App_Settings_VISA_Server_t), + SETTINGS_EVENT_VISA_SERVER_CHANGED); } esp_err_t SettingsManager_GetSystem(App_Settings_System_t* p_Settings) @@ -366,7 +415,8 @@ esp_err_t SettingsManager_GetSystem(App_Settings_System_t* p_Settings) esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t* p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.System, sizeof(App_Settings_System_t), SETTINGS_EVENT_SYSTEM_CHANGED); + return SettingsManager_Update(p_Settings, &_State.Settings.System, sizeof(App_Settings_System_t), + SETTINGS_EVENT_SYSTEM_CHANGED); } esp_err_t SettingsManager_ResetToDefaults(void) diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h index fd2ed3d..884634d 100644 --- a/main/Application/Manager/Settings/settingsManager.h +++ b/main/Application/Manager/Settings/settingsManager.h @@ -50,6 +50,12 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings); */ esp_err_t SettingsManager_Save(void); +/** @brief Get the device information from the Settings Manager RAM. + * @param p_Settings Pointer to Info structure to populate + * @return ESP_OK on success, ESP_ERR_* on failure +*/ +esp_err_t SettingsManager_GetInfo(App_Settings_Info_t* p_Settings); + /** @brief Get the Lepton settings from the Settings Manager RAM. * @param p_Settings Pointer to System settings structure to populate * @return ESP_OK on success, ESP_ERR_* on failure diff --git a/main/Application/Manager/Settings/settingsTypes.h b/main/Application/Manager/Settings/settingsTypes.h index c125556..929ca0d 100644 --- a/main/Application/Manager/Settings/settingsTypes.h +++ b/main/Application/Manager/Settings/settingsTypes.h @@ -106,10 +106,17 @@ typedef struct { */ typedef struct { char Name[32]; /**< Device name for provisioning. */ - char PoP[32]; /**< Proof of Possession for provisioning. */ uint32_t Timeout; /**< Provisioning timeout in seconds. */ } __attribute__((packed)) App_Settings_Provisioning_t; +/** @brief Device informations. + */ +typedef struct { + char FirmwareVersion[16]; /**< Firmware version string. */ + char Manufacturer[16]; /**< Manufacturer string. */ + uint16_t Serial; /**< Device serial number. */ +} __attribute__((packed)) App_Settings_Info_t; + /** @brief Display settings. */ typedef struct { @@ -134,16 +141,16 @@ typedef struct { /** @brief System settings. */ typedef struct { - char DeviceName[32]; /**< Device name. */ bool SDCard_AutoMount; /**< Automatically mount SD card. */ - bool Bluetooth_Enabled; /**< Bluetooth enabled. */ char Timezone[32]; /**< Timezone string (e.g., "CET-1CEST,M3.5.0,M10.5.0/3"). */ + char DeviceName[32]; /**< Device name. */ uint8_t Reserved[100]; /**< Reserved for future use. */ } __attribute__((packed)) App_Settings_System_t; /** @brief Complete application settings structure. */ typedef struct { + App_Settings_Info_t Info; /**< General device information. */ App_Settings_Lepton_t Lepton; /**< Lepton camera settings. */ App_Settings_WiFi_t WiFi; /**< WiFi settings. */ App_Settings_Provisioning_t Provisioning; /**< Provisioning settings. */ diff --git a/main/Application/Tasks/Devices/devicesTask.cpp b/main/Application/Tasks/Devices/devicesTask.cpp index 8015a37..7d327a8 100644 --- a/main/Application/Tasks/Devices/devicesTask.cpp +++ b/main/Application/Tasks/Devices/devicesTask.cpp @@ -144,7 +144,7 @@ esp_err_t DevicesTask_Init(void) Error = DevicesManager_Init(); if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize Devices Manager: %d!", Error); + ESP_LOGE(TAG, "Failed to initialize Devices Manager: 0x%x!", Error); return Error; } diff --git a/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c b/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c index 4544656..4fcb8b3 100644 --- a/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c +++ b/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c @@ -17094,8 +17094,7 @@ static const uint16_t unicode_list_30[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ +static const lv_font_fmt_txt_cmap_t cmaps[] = { { .range_start = 32, .range_length = 16, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c b/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c index 164f507..38ee026 100644 --- a/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c +++ b/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c @@ -6,124 +6,124 @@ #include "../ui.h" #ifndef LV_ATTRIBUTE_MEM_ALIGN - #define LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN #endif // IMAGE DATA: assets/Logo_80x44.png const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_logo_80x44_png_data[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0xFD,0x23,0xFD,0x45,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xE4,0xFB,0x40,0xFC,0xA0,0xFC,0x47,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0xFB,0x22,0xFB,0xA0,0xFB,0x00,0xFC,0x80,0xFC,0xCA,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFD,0x23,0xFD,0x43,0xFD,0x43,0xFD,0x4D,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xFA,0xA1,0xFA,0x20,0xFB,0xA0,0xFB,0xE0,0xFB,0x40,0xFC,0xAC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFD,0x00,0xFD,0x00,0xFD,0x20,0xFD,0xEF,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xFC,0xC3,0xF9,0x01,0xFA,0x81,0xFA,0x20,0xFB,0x80,0xFB,0xC0,0xFB,0x00,0xFC,0x87,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0xFC,0xA0,0xFC,0xA0,0xFC,0xE0,0xFC,0xAE,0xFD,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xFA,0x02,0xF9,0x62,0xF9,0xE1,0xF9,0x80,0xFA, - 0x00,0xFB,0x60,0xFB,0xA0,0xFB,0xE0,0xFB,0x64,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0xFC,0x81,0xFC,0x81,0xFC,0xC1,0xFC,0x8F,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0xF9,0x63,0xF8,0xE2,0xF8,0x62,0xF9,0xC1,0xF9,0x60,0xFA,0xE0,0xFA,0x80,0xFB,0xC0,0xFB,0x40,0xFC,0x81,0xFC,0x00,0x00,0xCF,0xFD,0xC7,0xFD,0xE4,0xFD,0x8A,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0xFA,0x84,0xF8,0x03,0xF8,0x63,0xF8,0xE2,0xF8,0x42,0xF9,0xC1,0xF9,0x40,0xFA,0xC0,0xFA,0x60,0xFB,0xA0,0xFB,0x20,0xFC,0x80,0xFC,0xE0,0xFC,0x20,0xFD,0x60,0xFD,0xC1,0xFD,0xC9,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xFD,0xA1,0xFD,0xA1,0xFD,0xA4,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xFC,0xE7,0xF8,0x04,0xF8,0x04,0xF8,0x03,0xF8,0x43,0xF8,0xC2,0xF8,0x41,0xF9,0xC0,0xF9,0x20,0xFA,0x80,0xFA,0xE0,0xFA,0x00,0xFB,0x60,0xFB,0xA0,0xFB,0xA0,0xFC,0xE0,0xFC,0x20,0xFD,0xA1,0xFD,0x0B,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xA6,0xFD,0x80,0xFD,0x60,0xFD,0x63,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xF9,0xAB,0xF8,0x28,0xF8,0x06,0xF8,0x05,0xF8,0x05,0xF8,0x04,0xF8,0x43,0xF8,0xA2,0xF8,0x21,0xF9,0xA0,0xF9,0x00,0xFA, - 0x60,0xFA,0xA0,0xFA,0xC0,0xFA,0x00,0xFB,0x40,0xFB,0x60,0xFC,0xC0,0xFC,0x00,0xFD,0x81,0xFD,0x4D,0xFE,0x00,0x00,0x00,0x00,0x2A,0xFE,0x25,0xFE,0x25,0xFE,0x25,0xFE,0x6D,0xFE,0x87,0xFD,0x41,0xFD,0x21,0xFD,0x23,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xBC,0x5F,0xB3,0x1F,0xC3,0xBF,0xCB,0x3F,0xDC,0x9F,0xF4,0x3D,0xFC,0x7B,0xFB,0x97,0xFA, - 0xD4,0xF9,0x31,0xF9,0xAF,0xF8,0x2E,0xF8,0x0C,0xF8,0x0A,0xF8,0x09,0xF8,0x07,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x43,0xF8,0xA2,0xF8,0x21,0xF9,0xA0,0xF9,0x00,0xFA,0x40,0xFA,0x80,0xFA,0xA0,0xFA,0xC0,0xFA,0xE0,0xFA,0x20,0xFC,0xA0,0xFC,0xE0,0xFC,0x40,0xFD,0x62,0xFC,0xA2,0xFB,0xC2,0xFB,0x81,0xFD,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x67,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,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,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xC3,0xBF,0xC2,0x7F,0xCA,0x1F,0xE2,0x7D,0xF9,0xD9,0xF8,0x76,0xF8,0x53,0xF8,0x31,0xF8,0x0F,0xF8,0x2E,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x62,0xF8,0xE1,0xF8,0x20,0xFA,0x60,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x40,0xFA,0x60,0xFA,0x40,0xFB,0x80,0xFC,0xC0,0xFC,0x00,0xFD,0x20,0xFC,0xA0,0xFB,0xA0,0xFB,0x40,0xFD,0x40,0xFE,0x40,0xFE,0x40,0xFE,0x87,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x7F,0xCB,0x1F,0xE2,0x7E,0xF9,0xFA,0xF8,0x96,0xF8,0x74,0xF8,0x31,0xF8,0x30,0xF8,0x2E,0xF8,0x2D,0xF8,0x2B,0xF8,0x0A,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x61,0xF8,0xA1,0xF8,0x00,0xF9,0xC0,0xF9,0xA0,0xFA,0xC0,0xFA,0x80,0xFA,0x00,0xFA,0x20,0xFA,0x60,0xFA,0x20,0xFC,0x80,0xFC,0xA0,0xFC,0xE0,0xFB,0xA0,0xFB,0xC0,0xFB,0x40,0xFD,0x40,0xFE,0x40,0xFE,0x40,0xFE, - 0x87,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xFD,0x03,0xFD,0x03,0xFD,0xE3,0xFC,0x30,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xEF,0x1F,0xDF,0x7F,0xEF,0x3F,0xDF,0x7F,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xFE,0xFE,0xF9,0x1B,0xF9,0xB7,0xF8,0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x2A,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x41,0xF8,0x00,0xF9,0x80,0xF9,0xC0,0xF9, - 0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x00,0xFA,0x40,0xFA,0x20,0xFB,0x20,0xFB,0x40,0xFB,0x20,0xFC,0xA0,0xFC,0x00,0xFD,0x00,0xFD,0xC0,0xFC,0xE0,0xFC,0x40,0xFD,0xC7,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFC,0xE0,0xFC,0xC0,0xFC,0xC0,0xFC,0x0C,0xFD,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xDF,0xFF,0x7F,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0xDF,0xFF,0xBF,0xF7,0x9F,0xF7,0x9F,0xF7,0xDF,0xFF,0xDE,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xF9,0xD8,0xF8, - 0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x09,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0xE5,0xFA,0x44,0xFA,0x41,0xF8,0x40,0xF9,0xE0,0xF9,0x44,0xFB,0x85,0xFC,0x60,0xF9,0x80,0xF9,0xA0,0xF9,0xC0,0xF9,0x87,0xFE,0x24,0xFD,0x60,0xFA,0xA0,0xFA,0xE0,0xFB,0xA0,0xFC,0xE0,0xFC,0xC0,0xFC,0xA0,0xFC,0xC0,0xFC,0x20,0xFD,0x84,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0xFC,0xA0,0xFC,0x80,0xFC,0x80,0xFC,0xCC,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xEF,0xDF,0xFF,0xDF,0xFF,0x5F,0xD7,0x7F,0xDF,0xBF,0xE7, - 0xBF,0xE7,0xBF,0xE7,0xBF,0xE7,0x9F,0xE7,0x7F,0xD7,0xDF,0xB6,0xBF,0xF7,0x9E,0xFF,0x9F,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x98,0xF9,0x75,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x0A,0xF8,0x08,0xF8,0x07,0xF8,0x06,0xF8,0x68,0xFD,0x89,0xFF,0x83,0xFA,0x20,0xF9,0xA0,0xF9,0xE4,0xFB,0xE9,0xFF,0x25,0xFD,0x60,0xF9,0x80,0xF9,0x80,0xF9,0xA6,0xFE,0xC7,0xFF,0x82,0xFB,0xA0,0xFA,0xC0,0xFB,0x60,0xFC,0x80,0xFC,0xA0,0xFC,0xC0,0xFC,0xE0,0xFC,0x20,0xFD,0x84,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,0xFC,0x62,0xFC,0x62,0xFC,0x42,0xFC,0x51,0xFD,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,0xDF,0xFF,0xDF,0xFF,0xBF,0xFF,0xBF,0xFF,0x3F,0xD7,0xBF,0xE7,0xBF,0xEF,0x9F,0xE7,0x5F,0xD7,0x3F,0xE7,0x5F,0xF7,0xFF,0xD6,0xFF,0xCE,0x5F,0xD7,0x7F,0xE7,0x7F,0xE7,0x1F,0xC7,0xBF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x7E,0xFF,0xF5,0xF8,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0x2D,0xF8,0x2C,0xF8,0x0A,0xF8,0x08,0xF8,0x27,0xF8,0x26,0xF8,0x47,0xFD,0xE7,0xFF,0xE4,0xFD,0x80,0xF8,0x60,0xF8,0x63,0xFB,0xE8,0xFF,0x06,0xFF,0x40,0xF9,0x40,0xF9,0x40,0xF9,0xC6,0xFE,0xE7,0xFF,0x24,0xFD,0xE0,0xFA,0xE0,0xFA,0x20,0xFB,0x80,0xFB,0x20,0xFC,0x00,0xFD,0x20,0xFD,0x60,0xFD, - 0x82,0xFD,0xC2,0xFD,0xE2,0xFD,0x22,0xFE,0x49,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,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBF,0xF7,0x5F,0xD7,0x7F,0xDF,0x3F,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x9F,0xEF,0xDF,0xBE,0xFF,0x64,0xFF,0xC6,0x7F,0xDF,0x7F,0xD7,0x9F,0xF7,0xDE,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0xFC,0x74,0xF8,0x31,0xF8,0x10,0xF8,0x0E,0xF8,0x2C,0xF8,0x0A,0xF8,0x09,0xF8,0x07,0xF8,0x26,0xF8,0x65,0xFE,0xC5,0xFF,0x64,0xFE,0x60,0xF8,0x40,0xF8,0x04,0xFD, - 0xE6,0xFF,0x26,0xFF,0x40,0xF9,0x20,0xF9,0x41,0xFA,0xA6,0xFF,0xE7,0xFF,0xA3,0xFC,0xE0,0xFA,0xC0,0xFA,0x00,0xFB,0x40,0xFB,0x20,0xFC,0x00,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x80,0xFD,0xA0,0xFD,0x00,0xFE,0x47,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0x9F,0xEF,0x5F,0xCF,0x7F,0xD7,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0x7F,0xEF,0xBF,0xAE,0x3F,0x5D,0x3F,0x2C,0x7F,0x6B,0xBF,0xE7,0x7F,0xD7,0x5F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, - 0xFF,0xFF,0xB5,0xF9,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x47,0xFA,0x45,0xFF,0xA5,0xFF,0x03,0xFD,0x60,0xF8,0xE0,0xF8,0x04,0xFF,0xC5,0xFF,0x24,0xFE,0x20,0xF9,0xE0,0xF8,0xA4,0xFD,0xA5,0xFF,0x45,0xFF,0x00,0xFA,0x20,0xFA,0xC0,0xFA,0x40,0xFB,0x80,0xFB,0xE0,0xFB,0x60,0xFC,0xA0,0xFC,0xC0,0xFC,0x20,0xFD,0x40,0xFD,0x80,0xFD,0xC0,0xFD,0x27,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xEF,0xBF,0xFF,0x1F,0xC7,0x5F,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xBF,0xF7,0x5F,0xD7,0x3F,0x8E,0xDF,0x24,0xDF,0x1B,0xDF,0x22,0x9F,0x31,0xFF,0xEF,0x3F,0xCF,0xBF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1B,0xFE,0x74,0xF8,0x32,0xF8,0x30,0xF8,0x0E,0xF8,0x0B,0xF8,0x0A,0xF8,0x08,0xF8,0x64,0xFE,0x43,0xFF,0xE3,0xFE,0xA0,0xF8,0x40,0xF8,0x62,0xFD,0x63,0xFF,0x44,0xFF,0x41,0xFA,0x00,0xF9,0x61,0xFB,0x64,0xFF,0x84,0xFF,0x62,0xFC,0x80,0xF9,0xA0,0xF9,0xE0,0xFA,0xA0,0xFB,0xE0,0xFB,0xE0,0xFB,0xA0,0xFB,0x00,0xFC,0x60,0xFC,0x00,0xFD,0x20,0xFD,0x60,0xFD,0xA0,0xFD,0x07,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFB,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA, - 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0xDF,0xB6,0x3F,0xCF,0x3F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xBF,0xF7,0x3F,0x5C,0x9F,0x23,0xDF,0x12,0x3F,0x12,0x1F,0x40,0x00,0xF8,0x3F,0xD7,0x9F,0xAE,0x7E,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0xF9,0x33,0xF8,0x31,0xF8,0x2F,0xF8,0x2C,0xF8,0x0A,0xF8,0x66,0xFD,0x22,0xFF,0x22,0xFF,0x41,0xFC,0x41,0xF8,0x21,0xFB,0x03,0xFF,0x23,0xFF,0x42,0xFD,0xC0,0xF8,0xE0,0xF8,0x42,0xFE,0x63,0xFF,0x82,0xFE,0x00,0xF9,0x60,0xF9,0x80,0xF9,0xE0,0xFA,0x80,0xFB,0xC0,0xFB,0x40,0xFC,0x60,0xFD,0xA0,0xFD,0xC0,0xFD, - 0x41,0xFE,0x81,0xFE,0xA2,0xFE,0xC1,0xFE,0x82,0xFE,0x63,0xFE,0x83,0xFE,0x23,0xFE,0x02,0xFA,0x02,0xFA,0xE2,0xF9,0x82,0xF9,0x46,0xFA,0x08,0xFB,0xE8,0xFA,0xE8,0xFA,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xE7,0x9F,0xF7,0x7F,0xD7,0xBF,0xB6,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xE7,0x3F,0xDF,0x3F,0xEF,0x5F,0xFF,0xBF,0x2A,0x1F,0x42,0x1F,0xF8,0x1F,0x50,0x5F,0xAD,0x3F,0xCF,0xBF,0xCE,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x17,0xFB,0x53,0xF8,0x51,0xF8,0x2E,0xF8,0x2A,0xF8,0x27,0xF9,0x02,0xFF,0x01,0xFF,0x41,0xFE,0x21,0xF8,0x40,0xF8,0xC1,0xFD,0x02,0xFF,0x82,0xFE, - 0xA0,0xF8,0xE0,0xF8,0x00,0xFB,0x02,0xFF,0x22,0xFF,0x21,0xFC,0xE0,0xF9,0x20,0xFA,0x40,0xFA,0x80,0xFA,0xC0,0xFA,0x00,0xFB,0x60,0xFC,0xC0,0xFE,0xC0,0xFE,0xE0,0xFE,0x61,0xFF,0xE2,0xFF,0xE2,0xFF,0xE2,0xFF,0x81,0xFE,0x40,0xFE,0x40,0xFE,0xE0,0xFD,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x80,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xBE,0xFF,0xDF,0xF7,0xFF,0xBE,0x7F,0xCF,0x9F,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0x7F,0xDF,0xFF,0x64,0x3F,0x11,0x9F,0xE6,0xFD,0xFE,0x1F,0xF8,0x1F,0x30,0x1F,0x18,0x1F,0x18,0x7F,0xDF,0x9F,0xB6,0x9F,0xF7,0xFF,0xFF,0xFF,0xFF, - 0xDF,0xFF,0xFF,0xFF,0x7E,0xFF,0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2C,0xF8,0x66,0xFD,0xE1,0xFE,0xE1,0xFE,0x40,0xFC,0x80,0xF8,0xA0,0xF8,0x61,0xFE,0xC1,0xFE,0xC1,0xFD,0xC0,0xF8,0xE0,0xF8,0xE0,0xFB,0xC1,0xFE,0xE1,0xFE,0x60,0xFA,0x40,0xFA,0x80,0xFA,0xA0,0xFA,0x60,0xFA,0x60,0xFA,0x80,0xFA,0x40,0xFC,0xC0,0xFE,0xC0,0xFE,0xC0,0xFE,0x61,0xFF,0xC2,0xFF,0xC2,0xFF,0xC2,0xFF,0x61,0xFE,0x20,0xFE,0x40,0xFE,0xC0,0xFD,0x00,0xFA,0x00,0xFA,0xC0,0xF9,0x80,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x7F,0xF7,0x9F,0xF7,0x1F,0xCF,0x3F,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xF7, - 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x1F,0x63,0x1F,0x30,0x1F,0x08,0xBF,0xC5,0x7F,0x93,0x1F,0x10,0x1F,0x08,0x5F,0x08,0x3F,0xCF,0x9F,0xDF,0xBF,0xFF,0x3F,0xDF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0xF8,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0xE6,0xFD,0xC2,0xFE,0xA1,0xFE,0x21,0xFC,0x60,0xF8,0xA0,0xF8,0x21,0xFE,0xA1,0xFE,0xE1,0xFD,0xC0,0xF8,0xE0,0xF8,0x20,0xFB,0xA1,0xFE,0xA1,0xFE,0xC0,0xFC,0x20,0xFA,0x60,0xFA,0x80,0xFA,0x60,0xFA,0x40,0xFA,0x80,0xFA,0x00,0xFC,0x40,0xFE,0x40,0xFE,0x40,0xFE,0xC1,0xFE,0x22,0xFF,0x02,0xFF,0x22,0xFF,0x21,0xFE,0xE0,0xFD,0x00,0xFE,0x80,0xFD,0xE0,0xF9,0xC0,0xF9,0xA0,0xF9,0x60,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00, - 0x5D,0xFC,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x1F,0x74,0xBF,0xF7,0x5F,0xD7,0xDF,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFF,0x21,0x5F,0x11,0x7F,0x08,0x7F,0x29,0xBF,0x94,0x7F,0x08,0x9F,0x10,0x1F,0x11,0x5F,0x4A,0xBF,0xDF,0x9F,0xF7,0x5F,0xEF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x57,0xF9,0x54,0xF8,0x53,0xF8,0x50,0xF8,0x49,0xFC,0xA1,0xFE,0x81,0xFE,0xA1,0xFD,0x40,0xF8,0x41,0xF8,0x61,0xFD,0x60,0xFE,0x41,0xFE,0x40,0xFB,0xE0,0xF8,0x00,0xF9,0x01,0xFE,0x61,0xFE,0x00,0xFE,0xA0,0xFA,0x80,0xF9,0x80,0xF9,0xA0,0xF9,0xC0,0xFA,0x00,0xFB,0x20,0xFB,0xE0,0xFB,0xA0,0xFC,0xC0,0xFC, - 0x00,0xFD,0x20,0xFD,0x40,0xFD,0x60,0xFD,0xA0,0xFD,0xC0,0xFD,0xC1,0xFD,0x44,0xFD,0x04,0xFA,0xE4,0xF9,0xE4,0xF9,0xC5,0xF9,0x4C,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x3D,0xFC,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x3F,0xBE,0xBF,0xF7,0x1F,0xCF,0xDF,0x8D,0x9F,0xB6,0x7F,0x9E,0x5F,0x8E,0x9F,0x6D,0xBF,0xF7,0xBF,0x9E,0xBF,0xAE,0x3F,0xE7,0xBF,0xF7,0xBF,0xF7,0xFF,0x08,0x9F,0x09,0xDF,0x09,0x1F,0x11,0x5F,0x09,0xBF,0x63,0x1F,0x11,0x7F,0x11,0xDF,0x19,0x9F,0x19,0xBF,0xDF,0x5F,0xE7,0xBF,0xF7,0xFE,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x78,0xF9,0x75,0xF8,0x54,0xF8,0x52,0xF8,0x4F,0xF8,0x23,0xFE,0x20,0xFE,0x00,0xFE,0x41,0xFC,0x01,0xF8,0xE1,0xF9,0x01,0xFE,0x20,0xFE, - 0xC0,0xFD,0x20,0xFA,0x00,0xF9,0x81,0xFB,0x21,0xFE,0x00,0xFE,0x81,0xFD,0x80,0xF9,0x20,0xF9,0x40,0xF9,0xC0,0xFA,0x20,0xFB,0x20,0xFB,0xA0,0xFB,0x60,0xFC,0xA0,0xFC,0xE0,0xFC,0x00,0xFD,0x40,0xFD,0x60,0xFD,0x80,0xFD,0xA0,0xFD,0xC1,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC9,0xFB,0x62,0xFB,0x61,0xFB,0x44,0xFB,0x00,0x00,0xFD,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x5F,0xBE,0x9F,0xFF,0x3F,0xCF,0xBF,0x85,0xBF,0x65,0x1F,0x66,0xDF,0x44,0x9F,0x2B,0x9F,0xEF,0x9F,0x12,0x1F,0x00,0x7F,0x62,0x1F,0x20,0x5F,0x10,0x5F,0x11,0x5F,0x12,0x5F,0x12,0x3F,0x1A,0x7F,0x1A,0xBF,0x53,0x3F,0x1A,0x5F,0x22,0x5F,0x2A,0xDF,0x21,0xBF,0xE7,0x5F,0xDF,0x9F,0xF7,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7A,0xF9,0x97,0xF8,0x75,0xF8,0x53,0xF8,0x51,0xF8,0x4E,0xFA,0xA2,0xFD,0x80,0xFD,0x40,0xFD,0xE1,0xF9,0x00,0xF8,0xA2,0xFB,0xA0,0xFD,0xC0,0xFD,0xE0,0xFC,0x00,0xF9,0x01,0xF8,0x21,0xFC,0xA0,0xFD,0xA0,0xFD,0x60,0xFC,0x20,0xF9,0x40,0xF9,0x60,0xFA,0xA0,0xFA,0xA0,0xFA,0xE0,0xFA,0x60,0xFB,0xC0,0xFB,0x40,0xFC,0x80,0xFC,0xA0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0x20,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xFB,0x20,0xFB,0x20,0xFB,0x43,0xFB,0x00,0x00,0x7C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x1F,0x53,0x5F,0xF7,0xFF,0xBE,0x9F,0xA6,0x5F,0x34,0x7F,0x24,0x1F,0x23,0x9F,0x19,0x3D,0xFF,0x1F,0x00,0x1F,0x00,0x1F,0x40, - 0x1F,0x10,0xFF,0x10,0x5F,0x12,0xDF,0x12,0x7F,0x12,0xDF,0x1A,0x1F,0x2B,0xDF,0x53,0xFF,0x2A,0xFF,0x2A,0xFF,0x32,0x7F,0x22,0xBF,0xE7,0x9F,0xEF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7B,0xF9,0x98,0xF8,0x76,0xF8,0x75,0xF8,0x53,0xF8,0x51,0xF8,0x4B,0xFB,0x00,0xFD,0x20,0xFD,0x81,0xFC,0x02,0xF8,0x03,0xF8,0x81,0xFC,0x60,0xFD,0x60,0xFD,0x61,0xFB,0x01,0xF8,0x01,0xF8,0xA0,0xFC,0x60,0xFD,0x40,0xFD,0x60,0xF9,0x20,0xF9,0x40,0xF9,0x60,0xF9,0xA0,0xF9,0xE0,0xF9,0x20,0xFA,0xC0,0xFA,0xC0,0xFB,0x00,0xFC,0x40,0xFC,0x60,0xFC,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0xFB,0x01,0xFB,0x01,0xFB,0x24,0xFB,0x00,0x00, - 0x9C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0xDF,0xDE,0x5F,0xEF,0xFF,0xBE,0x3F,0xC7,0x3F,0x33,0x5F,0x22,0x1F,0x41,0x1F,0xF8,0x5B,0xFE,0xFF,0xFD,0x1F,0x00,0x1F,0xF8,0xBF,0x10,0xDF,0x11,0x9F,0x12,0xDF,0x12,0xDF,0x22,0x1F,0x23,0xFF,0x4B,0x7F,0x43,0x5F,0x33,0x5F,0x3B,0x3F,0x3B,0x1F,0xCF,0xBF,0xE7,0xDF,0xFF,0xFF,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xF9,0xDA,0xF8,0xB8,0xF8,0x76,0xF8,0x74,0xF8,0x51,0xF8,0x2F,0xF8,0x83,0xFC,0xE0,0xFC,0xA0,0xFC,0x03,0xF8,0x03,0xF8,0x43,0xF8,0x00,0xFD,0x00,0xFD,0x60,0xFC,0x01,0xF8,0x01,0xF8,0x61,0xFA,0x20,0xFD,0x20,0xFD,0xA0,0xFA,0x00,0xF9,0x20,0xF9,0x60,0xF9,0x80,0xF9,0xC0,0xF9,0x00,0xFA,0xA0,0xFA, - 0xA0,0xFB,0xE0,0xFB,0x20,0xFC,0x40,0xFC,0x60,0xFC,0x80,0xFC,0x80,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0x7F,0xEF,0x5F,0xA6,0x3F,0xC7,0xBF,0x1A,0xBF,0xAA,0x00,0xF8,0x00,0xF8,0x1F,0xF8,0xBE,0xFE,0x1F,0x6A,0x7F,0x08,0xFF,0x28,0x9F,0x21,0x1F,0x22,0xFF,0x2A,0x7F,0x2B,0xFF,0x43,0x3F,0x54,0x9F,0x43,0x9F,0x43,0x7F,0x43,0x1F,0x43,0x9F,0xE7,0x7F,0xDF,0xBF,0xFF,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xFD,0x1E,0xF9,0xDC,0xF8,0xBA,0xF8,0x97,0xF8,0x75,0xF8,0x73,0xF8,0x70,0xF8,0x06,0xFC,0xA0,0xFC,0x60,0xFC,0x03,0xF8,0x03,0xF8,0x03,0xF8, - 0x80,0xFC,0xC0,0xFC,0x20,0xFC,0x01,0xF8,0x01,0xF8,0x81,0xF8,0xE0,0xFC,0xE0,0xFC,0x80,0xFA,0xE0,0xF8,0x00,0xF9,0x40,0xF9,0xC0,0xF9,0x00,0xFB,0x20,0xFB,0x40,0xFB,0x80,0xFB,0xA0,0xFB,0xE1,0xFB,0x43,0xFC,0x63,0xFC,0x63,0xFC,0x44,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xFB,0x1C,0xFC,0xDF,0xFF,0xFF,0xFF,0xDF,0xFF,0x5F,0xE7,0xFF,0xE6,0x1F,0xBF,0xDF,0x8D,0xBF,0x52,0x00,0xF8,0x1F,0xF8,0x1F,0x20,0xDF,0x51,0xFF,0xEC,0x3F,0xAB,0x9F,0x39,0x5F,0x32,0xDF,0x32,0x3F,0x3B,0x3F,0x64,0x5F,0x64,0xBF,0x53,0xDF,0x53,0x9F,0x53,0x7F,0x53,0x5F,0x3B,0xDF,0xEF,0x3F,0xCF,0x9F,0xF7,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x3F,0xF9,0x1D,0xF9,0xFB,0xF8,0xB9,0xF8,0x97,0xF8,0x94,0xF8,0x71,0xF8,0xA6,0xFB,0x40,0xFC,0x00,0xFC,0x04,0xF8,0x05,0xF8,0x04,0xF8,0x60,0xFC,0x80,0xFC,0xA0,0xFB,0x01,0xF8,0x01,0xF8,0x61,0xF9,0xA0,0xFC,0x80,0xFC,0xE0,0xF8,0x20,0xF9,0x80,0xF9,0xC0,0xF9,0x20,0xFA,0x20,0xFB,0x40,0xFB,0x40,0xFB,0x60,0xFB,0x80,0xFB,0xC2,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xF8,0x60,0xF8,0x60,0xF8,0x60,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0xFB,0xDC,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x5F,0xF7,0x9F,0xFF,0x7F,0xA6,0xFF,0xBE,0x9F,0x1B,0x1F,0x80,0x1F,0x48,0x1F,0x68,0x7F,0x90,0x7F,0x88,0x1F,0xBB, - 0xFF,0xAB,0xDF,0x93,0x1F,0x84,0x3F,0x84,0x9F,0x6B,0xBF,0x73,0x1F,0x7C,0x3F,0x84,0xDF,0x7B,0x3F,0x63,0xDF,0xEF,0xBF,0xEF,0xBF,0xF7,0xBF,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xDA,0x7F,0xF9,0x3E,0xF9,0x1D,0xF9,0xDB,0xF8,0xB9,0xF8,0x96,0xF8,0x73,0xF8,0xA4,0xFB,0x00,0xFC,0x82,0xFB,0x06,0xF8,0x06,0xF8,0x25,0xF9,0x20,0xFC,0x40,0xFC,0x81,0xF9,0x01,0xF8,0x01,0xF8,0x01,0xFB,0x60,0xFC,0xE0,0xFB,0x80,0xF8,0x00,0xFA,0xA0,0xFA,0xC0,0xFA,0xA0,0xFA,0xE0,0xFA,0x00,0xFB,0x00,0xFB,0x20,0xFB,0x20,0xFB,0x42,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xF8,0x20,0xF8,0x20,0xF8,0x40,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x7E,0xFC,0xBD,0xFB,0x7F,0xFE,0xFF,0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xE6,0x7F,0xF7,0xFF,0xBE,0x1F,0xBF,0x1F,0x23,0xBF,0xD8,0x7F,0xF0,0xBF,0xE8,0x5F,0xF1,0x7F,0xF1,0x1F,0xE2,0x1F,0xD2,0x7F,0xBA,0xDF,0xB2,0x3F,0xA3,0x9F,0xA3,0x3F,0xCE,0xDF,0xFF,0xBF,0x9C,0xBF,0xEF,0xFF,0xF7,0x5F,0xDF,0xBF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xCB,0x1F,0xDA,0xBF,0xF1,0x7F,0xF9,0x3E,0xF9,0xFC,0xF8,0xDA,0xF8,0xD8,0xF8,0xB1,0xF9,0xC0,0xFB,0xC0,0xFB,0xA6,0xF9,0x08,0xF8,0x07,0xF8,0x23,0xFB,0xE0,0xFB,0x60,0xFB,0x02,0xF8,0x01,0xF8,0x01,0xF8,0x80,0xFB,0xE0,0xFB,0xE0,0xF9,0x60,0xF8,0x00,0xFA,0xA0,0xFA,0xC0,0xFA,0x60,0xFA,0x80,0xF9,0x80,0xF9,0x80,0xF9, - 0x80,0xF9,0x60,0xF9,0x41,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xF8,0x00,0xF8,0x00,0xF8,0x20,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBE,0xFB,0xFE,0xFB,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xDF,0xFF,0x7F,0xF7,0xBF,0xCE,0x1F,0xC7,0xBF,0xB6,0xBF,0x3A,0x3E,0xF9,0xBB,0xF8,0x1A,0xF9,0x3B,0xF9,0xBC,0xF9,0xFE,0xF9,0x5F,0xF2,0xBF,0xEA,0xFF,0xD2,0x3F,0xCB,0xFF,0xCC,0x5F,0xEF,0x9F,0xE7,0xFF,0xFF,0x9F,0xE7,0xDF,0xFF,0x3F,0xE7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x9F,0xBA,0x3F,0xD2,0xFF,0xE1,0x7F,0xF1,0x5F,0xF9,0x3E,0xF9,0x1C,0xF9,0xD9,0xF8,0x47,0xFB,0xA0,0xFB,0xC6,0xFA,0x2A,0xF8,0x09,0xF8,0x27,0xF9,0x80,0xFB, - 0x60,0xFB,0x82,0xF8,0x02,0xF8,0x02,0xF8,0x20,0xFA,0x40,0xFB,0x60,0xFA,0x41,0xF8,0x41,0xF8,0xC0,0xF9,0x60,0xFA,0x80,0xFA,0x40,0xFA,0x00,0xFA,0x00,0xFA,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x62,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xF9,0xA6,0xF9,0xA6,0xF9,0xE7,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFC,0xBF,0xFB,0x3F,0xFD,0xDF,0xFF,0xDF,0xFF,0xDE,0xFF,0x7F,0xE7,0xBF,0xFF,0xFF,0xD6,0x1F,0xC7,0xFF,0xC6,0x3F,0x5D,0x3F,0xBA,0x39,0xF9,0xF8,0xF8,0x19,0xF9,0x7B,0xF9,0xDD,0xF9,0x5E,0xFA,0xBF,0xEA,0xDF,0xDA,0x5F,0x73,0xDF,0xF7,0xFF,0xF7,0x9F,0xE7,0xDF,0xFF,0x5F,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xA2,0x7F,0xB2,0x3F,0xC2,0xFF,0xD9,0xDF,0xE9,0x7F,0xF9,0x5F,0xF9,0x3D,0xF9,0x58,0xF9,0x09,0xFB,0xC9,0xFA,0x2E,0xF8,0x0C,0xF8,0x0A,0xF8,0x67,0xF9,0x84,0xFA,0x44,0xF9,0x03,0xF8,0x02,0xF8,0x02,0xF8,0x01,0xF8,0x61,0xF8,0x21,0xF8,0x42,0xF8,0x42,0xF8,0x41,0xF9,0xE0,0xF9,0x40,0xFA,0x80,0xFA,0xC0,0xFA,0x00,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xFA,0x08,0xFA,0xE7,0xF9,0x69,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0xF3,0xBF,0xF3,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x5F,0xE7,0xBF,0xFF,0xBF,0xD6,0xBF,0xBE,0x1F,0xCF,0xFF,0xC6,0xBF,0x8D,0x5F,0x1B, - 0x9F,0xAA,0x1F,0xFA,0x7F,0xEA,0xFF,0x42,0xDF,0xBE,0xFF,0xF7,0xFF,0xF7,0xDF,0xF7,0xBF,0xE7,0xDF,0xF7,0x7F,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x9C,0xBF,0x9A,0x7F,0xAA,0x3F,0xBA,0x1F,0xD2,0xFF,0xE9,0xBF,0xF1,0x7F,0xF9,0x5E,0xF9,0x1B,0xF9,0xB7,0xF8,0x53,0xF8,0x30,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x03,0xF8,0x03,0xF8,0x02,0xF8,0x22,0xF8,0x21,0xF8,0x22,0xF8,0x22,0xF8,0x40,0xF9,0xC0,0xF9,0x00,0xFA,0x60,0xFA,0xA0,0xFA,0xC0,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xF8,0x80,0xF8,0x80,0xF8,0xE3,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,0x7F,0xF5,0x7F,0xEB,0x7F,0xE3,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xBF,0xF7,0x1F,0xEF,0x1F,0xEF,0x7F,0xBE,0xBF,0xBE,0x3F,0xD7,0x7F,0xDF,0x7F,0xE7,0xDF,0xEF,0xDF,0xF7,0xFF,0xF7,0xFF,0xF7,0xFF,0xF7,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF,0xD6,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x8C,0x1F,0x7B,0xDF,0x92,0x7F,0xA2,0x5F,0xB2,0x3F,0xD2,0xFF,0xE9,0xDF,0xF9,0x9F,0xF9,0x7E,0xF9,0x1C,0xF9,0xD8,0xF8,0x74,0xF8,0x30,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x80,0xF8,0x80,0xF8,0x40,0xF8,0x21,0xF8,0x40,0xF8,0x60,0xF8,0x80,0xF8,0xC0,0xF8,0x21,0xF9,0x07,0xFB,0x28,0xFB,0x00,0x00, - 0x00,0x00,0x00,0x00,0x60,0xF8,0x60,0xF8,0x60,0xF8,0xE3,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,0x3F,0xEC,0x5F,0xE3,0x7F,0xDB,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x8D,0x1F,0xEF,0x5F,0xEF,0x1F,0xEF,0xFF,0xCE,0x3F,0xCF,0x7F,0xE7,0x9F,0xE7,0x9F,0xE7,0x9F,0xF7,0xBF,0xFF,0xDF,0xFF,0x7F,0xE7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7C,0x5F,0x5B,0x3F,0x73,0xFF,0x8A,0x9F,0x9A,0x5F,0xB2,0x3F,0xCA,0x1F,0xE2,0x1F,0xFA,0xDF,0xF9,0x7E,0xF9,0x3B,0xF9,0xF8,0xF8,0xB5,0xF8,0x51,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8, - 0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x80,0xF8,0xA0,0xF8,0x40,0xF8,0x20,0xF8,0x40,0xF8,0x60,0xF8,0x80,0xF8,0xA0,0xF8,0x23,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xF8,0x20,0xF8,0x20,0xF8,0xC2,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,0x5F,0xDC,0x1F,0xCB,0x3F,0xC3,0xBF,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x5F,0xEF,0x5F,0xB6,0x5F,0xEF,0xBF,0xFF,0xBF,0xFF,0xDF,0xFF,0xDF,0xFF,0x9F,0xE7,0xBF,0x95,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x5B,0x7F,0x4B,0x7F,0x53,0x5F,0x6B, - 0x3F,0x7B,0xFF,0x9A,0x5F,0xAB,0x5F,0xC4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xFC,0xDA,0xFA,0xB6,0xF9,0xF2,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x07,0xF8,0x06,0xF8,0x05,0xF8,0x24,0xF8,0x61,0xF8,0x81,0xF8,0x21,0xF8,0x20,0xF8,0x20,0xF8,0x60,0xF8,0x60,0xF8,0x60,0xF8,0x4C,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0xFB,0x6D,0xFB,0xCF,0xFB,0x30,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,0xDF,0xD4,0x1F,0xBB,0x1F,0xB3,0x1F,0xB4,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xFF,0xFF,0x9F,0x94,0x1F,0x5B,0x3F,0x4B,0x9F,0x5B,0xDF,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xF9,0xEA,0xF8,0x48,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x03,0xF8,0x02,0xF8,0x02,0xF8,0x01,0xF8,0x00,0xF8,0x20,0xF8,0x60,0xF8,0xA1,0xF8,0x8A,0xFA,0x00,0x00,0xE8,0xFA,0x63,0xFA,0x63,0xFA,0x09,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xAB,0xFF,0xA2,0x1F,0xA3,0x7F,0xAC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xAD,0xDF,0x7B,0x1F,0xE7,0xFF,0xFF,0x5F,0xEF,0x1F,0xA5,0x1F,0x94,0x9F,0x9B,0x5F,0xAB,0x5F,0xBB,0x3F,0xC3,0x9F,0xD3,0x1F,0xE4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFB,0xA8,0xF9,0xE6,0xF8,0xA4,0xF8,0x63,0xF8,0x63,0xF8,0x62,0xF8,0xA3,0xF8,0x04,0xF9,0x49,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFA,0x20,0xFA,0x40,0xFA, - 0x85,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xBC,0x3F,0x9B,0xDF,0x82,0x1F,0x73,0x9F,0x73,0xDF,0x94,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xCE,0x5F,0x6C,0xDF,0x4B,0x9F,0x43,0x7F,0x4B,0x7F,0x63,0x5F,0x6B,0x3F,0x73,0x3F,0x83,0x1F,0x93,0xDF,0xA2,0x9F,0xB2,0x5F,0xC2,0x3F,0xD2,0x3F,0xE2,0x3F,0xEA,0x7F,0xFA,0x7D,0xFA,0x3B,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,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,0xFA,0x20,0xFA,0x20,0xFA,0x65,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDF,0xAC,0x5F,0x7B,0x3F,0x63,0x5F,0x53,0x5F,0x4B,0x5F,0x43,0x7F,0x3B,0x7F,0x3B,0x9F,0x33,0x9F,0x33,0x9F,0x2B,0x9F,0x2B,0x9F,0x2B,0x7F,0x2B,0x9F,0x2B,0x9F,0x33,0x9F,0x3B,0x7F,0x4B,0x7F,0x5B,0x7F,0x6B,0x5F,0x73,0x3F,0x83, - 0x1F,0x93,0xFF,0xA2,0xDF,0xB2,0x9F,0xC2,0x9F,0xD2,0x7F,0xE2,0x5F,0xF2,0x3E,0xFA,0xBB,0xF9,0x78,0xF9,0x56,0xF9,0xF4,0xF9,0x56,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,0xCD,0xFB,0xEE,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0x8C,0xDF,0x5B,0x7F,0x4B, - 0x7F,0x3B,0x7F,0x33,0x9F,0x2B,0x9F,0x2B,0x7F,0x2B,0x9F,0x2B,0x9F,0x2B,0x9F,0x33,0xBF,0x3B,0xDF,0x43,0x1F,0x54,0x5F,0x6C,0x3F,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xFD, 0x23, 0xFD, 0x45, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE4, 0xFB, 0x40, 0xFC, 0xA0, 0xFC, 0x47, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xFB, 0x22, 0xFB, 0xA0, 0xFB, 0x00, 0xFC, 0x80, 0xFC, 0xCA, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFD, 0x23, 0xFD, 0x43, 0xFD, 0x43, 0xFD, 0x4D, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFA, 0xA1, 0xFA, 0x20, 0xFB, 0xA0, 0xFB, 0xE0, 0xFB, 0x40, 0xFC, 0xAC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0xEF, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xFC, 0xC3, 0xF9, 0x01, 0xFA, 0x81, 0xFA, 0x20, 0xFB, 0x80, 0xFB, 0xC0, 0xFB, 0x00, 0xFC, 0x87, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0xAE, 0xFD, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFA, 0x02, 0xF9, 0x62, 0xF9, 0xE1, 0xF9, 0x80, 0xFA, + 0x00, 0xFB, 0x60, 0xFB, 0xA0, 0xFB, 0xE0, 0xFB, 0x64, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0xFC, 0x81, 0xFC, 0x81, 0xFC, 0xC1, 0xFC, 0x8F, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xF9, 0x63, 0xF8, 0xE2, 0xF8, 0x62, 0xF9, 0xC1, 0xF9, 0x60, 0xFA, 0xE0, 0xFA, 0x80, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x81, 0xFC, 0x00, 0x00, 0xCF, 0xFD, 0xC7, 0xFD, 0xE4, 0xFD, 0x8A, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFA, 0x84, 0xF8, 0x03, 0xF8, 0x63, 0xF8, 0xE2, 0xF8, 0x42, 0xF9, 0xC1, 0xF9, 0x40, 0xFA, 0xC0, 0xFA, 0x60, 0xFB, 0xA0, 0xFB, 0x20, 0xFC, 0x80, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x60, 0xFD, 0xC1, 0xFD, 0xC9, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA4, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xFC, 0xE7, 0xF8, 0x04, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x43, 0xF8, 0xC2, 0xF8, 0x41, 0xF9, 0xC0, 0xF9, 0x20, 0xFA, 0x80, 0xFA, 0xE0, 0xFA, 0x00, 0xFB, 0x60, 0xFB, 0xA0, 0xFB, 0xA0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0xA1, 0xFD, 0x0B, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xA6, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0x63, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xF9, 0xAB, 0xF8, 0x28, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x43, 0xF8, 0xA2, 0xF8, 0x21, 0xF9, 0xA0, 0xF9, 0x00, 0xFA, + 0x60, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x40, 0xFB, 0x60, 0xFC, 0xC0, 0xFC, 0x00, 0xFD, 0x81, 0xFD, 0x4D, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xFE, 0x25, 0xFE, 0x25, 0xFE, 0x25, 0xFE, 0x6D, 0xFE, 0x87, 0xFD, 0x41, 0xFD, 0x21, 0xFD, 0x23, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xBC, 0x5F, 0xB3, 0x1F, 0xC3, 0xBF, 0xCB, 0x3F, 0xDC, 0x9F, 0xF4, 0x3D, 0xFC, 0x7B, 0xFB, 0x97, 0xFA, + 0xD4, 0xF9, 0x31, 0xF9, 0xAF, 0xF8, 0x2E, 0xF8, 0x0C, 0xF8, 0x0A, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x43, 0xF8, 0xA2, 0xF8, 0x21, 0xF9, 0xA0, 0xF9, 0x00, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0xE0, 0xFA, 0x20, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0x40, 0xFD, 0x62, 0xFC, 0xA2, 0xFB, 0xC2, 0xFB, 0x81, 0xFD, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x67, 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, 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, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xC3, 0xBF, 0xC2, 0x7F, 0xCA, 0x1F, 0xE2, 0x7D, 0xF9, 0xD9, 0xF8, 0x76, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x0F, 0xF8, 0x2E, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x62, 0xF8, 0xE1, 0xF8, 0x20, 0xFA, 0x60, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x40, 0xFA, 0x60, 0xFA, 0x40, 0xFB, 0x80, 0xFC, 0xC0, 0xFC, 0x00, 0xFD, 0x20, 0xFC, 0xA0, 0xFB, 0xA0, 0xFB, 0x40, 0xFD, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x87, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x7F, 0xCB, 0x1F, 0xE2, 0x7E, 0xF9, 0xFA, 0xF8, 0x96, 0xF8, 0x74, 0xF8, 0x31, 0xF8, 0x30, 0xF8, 0x2E, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x61, 0xF8, 0xA1, 0xF8, 0x00, 0xF9, 0xC0, 0xF9, 0xA0, 0xFA, 0xC0, 0xFA, 0x80, 0xFA, 0x00, 0xFA, 0x20, 0xFA, 0x60, 0xFA, 0x20, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xE0, 0xFB, 0xA0, 0xFB, 0xC0, 0xFB, 0x40, 0xFD, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, + 0x87, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFD, 0x03, 0xFD, 0x03, 0xFD, 0xE3, 0xFC, 0x30, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xEF, 0x1F, 0xDF, 0x7F, 0xEF, 0x3F, 0xDF, 0x7F, 0xE7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xFE, 0xFE, 0xF9, 0x1B, 0xF9, 0xB7, 0xF8, 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x2A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x41, 0xF8, 0x00, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, + 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x00, 0xFA, 0x40, 0xFA, 0x20, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x20, 0xFC, 0xA0, 0xFC, 0x00, 0xFD, 0x00, 0xFD, 0xC0, 0xFC, 0xE0, 0xFC, 0x40, 0xFD, 0xC7, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0x0C, 0xFD, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x7F, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0xDF, 0xFF, 0xBF, 0xF7, 0x9F, 0xF7, 0x9F, 0xF7, 0xDF, 0xFF, 0xDE, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF9, 0xD8, 0xF8, + 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0xE5, 0xFA, 0x44, 0xFA, 0x41, 0xF8, 0x40, 0xF9, 0xE0, 0xF9, 0x44, 0xFB, 0x85, 0xFC, 0x60, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0xC0, 0xF9, 0x87, 0xFE, 0x24, 0xFD, 0x60, 0xFA, 0xA0, 0xFA, 0xE0, 0xFB, 0xA0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0x20, 0xFD, 0x84, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xCC, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0x5F, 0xD7, 0x7F, 0xDF, 0xBF, 0xE7, + 0xBF, 0xE7, 0xBF, 0xE7, 0xBF, 0xE7, 0x9F, 0xE7, 0x7F, 0xD7, 0xDF, 0xB6, 0xBF, 0xF7, 0x9E, 0xFF, 0x9F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0xF9, 0x75, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x68, 0xFD, 0x89, 0xFF, 0x83, 0xFA, 0x20, 0xF9, 0xA0, 0xF9, 0xE4, 0xFB, 0xE9, 0xFF, 0x25, 0xFD, 0x60, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xA6, 0xFE, 0xC7, 0xFF, 0x82, 0xFB, 0xA0, 0xFA, 0xC0, 0xFB, 0x60, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x84, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xFC, 0x62, 0xFC, 0x62, 0xFC, 0x42, 0xFC, 0x51, 0xFD, 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, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0x3F, 0xD7, 0xBF, 0xE7, 0xBF, 0xEF, 0x9F, 0xE7, 0x5F, 0xD7, 0x3F, 0xE7, 0x5F, 0xF7, 0xFF, 0xD6, 0xFF, 0xCE, 0x5F, 0xD7, 0x7F, 0xE7, 0x7F, 0xE7, 0x1F, 0xC7, 0xBF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7E, 0xFF, 0xF5, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x27, 0xF8, 0x26, 0xF8, 0x47, 0xFD, 0xE7, 0xFF, 0xE4, 0xFD, 0x80, 0xF8, 0x60, 0xF8, 0x63, 0xFB, 0xE8, 0xFF, 0x06, 0xFF, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0xC6, 0xFE, 0xE7, 0xFF, 0x24, 0xFD, 0xE0, 0xFA, 0xE0, 0xFA, 0x20, 0xFB, 0x80, 0xFB, 0x20, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x60, 0xFD, + 0x82, 0xFD, 0xC2, 0xFD, 0xE2, 0xFD, 0x22, 0xFE, 0x49, 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, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x5F, 0xD7, 0x7F, 0xDF, 0x3F, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x9F, 0xEF, 0xDF, 0xBE, 0xFF, 0x64, 0xFF, 0xC6, 0x7F, 0xDF, 0x7F, 0xD7, 0x9F, 0xF7, 0xDE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0xFC, 0x74, 0xF8, 0x31, 0xF8, 0x10, 0xF8, 0x0E, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x26, 0xF8, 0x65, 0xFE, 0xC5, 0xFF, 0x64, 0xFE, 0x60, 0xF8, 0x40, 0xF8, 0x04, 0xFD, + 0xE6, 0xFF, 0x26, 0xFF, 0x40, 0xF9, 0x20, 0xF9, 0x41, 0xFA, 0xA6, 0xFF, 0xE7, 0xFF, 0xA3, 0xFC, 0xE0, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x40, 0xFB, 0x20, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0x00, 0xFE, 0x47, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x9F, 0xEF, 0x5F, 0xCF, 0x7F, 0xD7, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0x7F, 0xEF, 0xBF, 0xAE, 0x3F, 0x5D, 0x3F, 0x2C, 0x7F, 0x6B, 0xBF, 0xE7, 0x7F, 0xD7, 0x5F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, + 0xFF, 0xFF, 0xB5, 0xF9, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x47, 0xFA, 0x45, 0xFF, 0xA5, 0xFF, 0x03, 0xFD, 0x60, 0xF8, 0xE0, 0xF8, 0x04, 0xFF, 0xC5, 0xFF, 0x24, 0xFE, 0x20, 0xF9, 0xE0, 0xF8, 0xA4, 0xFD, 0xA5, 0xFF, 0x45, 0xFF, 0x00, 0xFA, 0x20, 0xFA, 0xC0, 0xFA, 0x40, 0xFB, 0x80, 0xFB, 0xE0, 0xFB, 0x60, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0x20, 0xFD, 0x40, 0xFD, 0x80, 0xFD, 0xC0, 0xFD, 0x27, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xEF, 0xBF, 0xFF, 0x1F, 0xC7, 0x5F, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x5F, 0xD7, 0x3F, 0x8E, 0xDF, 0x24, 0xDF, 0x1B, 0xDF, 0x22, 0x9F, 0x31, 0xFF, 0xEF, 0x3F, 0xCF, 0xBF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0xFE, 0x74, 0xF8, 0x32, 0xF8, 0x30, 0xF8, 0x0E, 0xF8, 0x0B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x64, 0xFE, 0x43, 0xFF, 0xE3, 0xFE, 0xA0, 0xF8, 0x40, 0xF8, 0x62, 0xFD, 0x63, 0xFF, 0x44, 0xFF, 0x41, 0xFA, 0x00, 0xF9, 0x61, 0xFB, 0x64, 0xFF, 0x84, 0xFF, 0x62, 0xFC, 0x80, 0xF9, 0xA0, 0xF9, 0xE0, 0xFA, 0xA0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xA0, 0xFB, 0x00, 0xFC, 0x60, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x60, 0xFD, 0xA0, 0xFD, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0xDF, 0xB6, 0x3F, 0xCF, 0x3F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x3F, 0x5C, 0x9F, 0x23, 0xDF, 0x12, 0x3F, 0x12, 0x1F, 0x40, 0x00, 0xF8, 0x3F, 0xD7, 0x9F, 0xAE, 0x7E, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xF9, 0x33, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x66, 0xFD, 0x22, 0xFF, 0x22, 0xFF, 0x41, 0xFC, 0x41, 0xF8, 0x21, 0xFB, 0x03, 0xFF, 0x23, 0xFF, 0x42, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0x42, 0xFE, 0x63, 0xFF, 0x82, 0xFE, 0x00, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0xE0, 0xFA, 0x80, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x60, 0xFD, 0xA0, 0xFD, 0xC0, 0xFD, + 0x41, 0xFE, 0x81, 0xFE, 0xA2, 0xFE, 0xC1, 0xFE, 0x82, 0xFE, 0x63, 0xFE, 0x83, 0xFE, 0x23, 0xFE, 0x02, 0xFA, 0x02, 0xFA, 0xE2, 0xF9, 0x82, 0xF9, 0x46, 0xFA, 0x08, 0xFB, 0xE8, 0xFA, 0xE8, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xE7, 0x9F, 0xF7, 0x7F, 0xD7, 0xBF, 0xB6, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xE7, 0x3F, 0xDF, 0x3F, 0xEF, 0x5F, 0xFF, 0xBF, 0x2A, 0x1F, 0x42, 0x1F, 0xF8, 0x1F, 0x50, 0x5F, 0xAD, 0x3F, 0xCF, 0xBF, 0xCE, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0xFB, 0x53, 0xF8, 0x51, 0xF8, 0x2E, 0xF8, 0x2A, 0xF8, 0x27, 0xF9, 0x02, 0xFF, 0x01, 0xFF, 0x41, 0xFE, 0x21, 0xF8, 0x40, 0xF8, 0xC1, 0xFD, 0x02, 0xFF, 0x82, 0xFE, + 0xA0, 0xF8, 0xE0, 0xF8, 0x00, 0xFB, 0x02, 0xFF, 0x22, 0xFF, 0x21, 0xFC, 0xE0, 0xF9, 0x20, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x60, 0xFC, 0xC0, 0xFE, 0xC0, 0xFE, 0xE0, 0xFE, 0x61, 0xFF, 0xE2, 0xFF, 0xE2, 0xFF, 0xE2, 0xFF, 0x81, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0xE0, 0xFD, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x80, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, 0xDF, 0xF7, 0xFF, 0xBE, 0x7F, 0xCF, 0x9F, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x7F, 0xDF, 0xFF, 0x64, 0x3F, 0x11, 0x9F, 0xE6, 0xFD, 0xFE, 0x1F, 0xF8, 0x1F, 0x30, 0x1F, 0x18, 0x1F, 0x18, 0x7F, 0xDF, 0x9F, 0xB6, 0x9F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xFF, 0xFF, 0x7E, 0xFF, 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2C, 0xF8, 0x66, 0xFD, 0xE1, 0xFE, 0xE1, 0xFE, 0x40, 0xFC, 0x80, 0xF8, 0xA0, 0xF8, 0x61, 0xFE, 0xC1, 0xFE, 0xC1, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0xE0, 0xFB, 0xC1, 0xFE, 0xE1, 0xFE, 0x60, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x80, 0xFA, 0x40, 0xFC, 0xC0, 0xFE, 0xC0, 0xFE, 0xC0, 0xFE, 0x61, 0xFF, 0xC2, 0xFF, 0xC2, 0xFF, 0xC2, 0xFF, 0x61, 0xFE, 0x20, 0xFE, 0x40, 0xFE, 0xC0, 0xFD, 0x00, 0xFA, 0x00, 0xFA, 0xC0, 0xF9, 0x80, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x7F, 0xF7, 0x9F, 0xF7, 0x1F, 0xCF, 0x3F, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x1F, 0x63, 0x1F, 0x30, 0x1F, 0x08, 0xBF, 0xC5, 0x7F, 0x93, 0x1F, 0x10, 0x1F, 0x08, 0x5F, 0x08, 0x3F, 0xCF, 0x9F, 0xDF, 0xBF, 0xFF, 0x3F, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0xE6, 0xFD, 0xC2, 0xFE, 0xA1, 0xFE, 0x21, 0xFC, 0x60, 0xF8, 0xA0, 0xF8, 0x21, 0xFE, 0xA1, 0xFE, 0xE1, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0x20, 0xFB, 0xA1, 0xFE, 0xA1, 0xFE, 0xC0, 0xFC, 0x20, 0xFA, 0x60, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0x00, 0xFC, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0xC1, 0xFE, 0x22, 0xFF, 0x02, 0xFF, 0x22, 0xFF, 0x21, 0xFE, 0xE0, 0xFD, 0x00, 0xFE, 0x80, 0xFD, 0xE0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF9, 0x60, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5D, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x1F, 0x74, 0xBF, 0xF7, 0x5F, 0xD7, 0xDF, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF7, 0xFF, 0x21, 0x5F, 0x11, 0x7F, 0x08, 0x7F, 0x29, 0xBF, 0x94, 0x7F, 0x08, 0x9F, 0x10, 0x1F, 0x11, 0x5F, 0x4A, 0xBF, 0xDF, 0x9F, 0xF7, 0x5F, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0xF9, 0x54, 0xF8, 0x53, 0xF8, 0x50, 0xF8, 0x49, 0xFC, 0xA1, 0xFE, 0x81, 0xFE, 0xA1, 0xFD, 0x40, 0xF8, 0x41, 0xF8, 0x61, 0xFD, 0x60, 0xFE, 0x41, 0xFE, 0x40, 0xFB, 0xE0, 0xF8, 0x00, 0xF9, 0x01, 0xFE, 0x61, 0xFE, 0x00, 0xFE, 0xA0, 0xFA, 0x80, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0xC0, 0xFA, 0x00, 0xFB, 0x20, 0xFB, 0xE0, 0xFB, 0xA0, 0xFC, 0xC0, 0xFC, + 0x00, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0xA0, 0xFD, 0xC0, 0xFD, 0xC1, 0xFD, 0x44, 0xFD, 0x04, 0xFA, 0xE4, 0xF9, 0xE4, 0xF9, 0xC5, 0xF9, 0x4C, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0xBF, 0xF7, 0x1F, 0xCF, 0xDF, 0x8D, 0x9F, 0xB6, 0x7F, 0x9E, 0x5F, 0x8E, 0x9F, 0x6D, 0xBF, 0xF7, 0xBF, 0x9E, 0xBF, 0xAE, 0x3F, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xFF, 0x08, 0x9F, 0x09, 0xDF, 0x09, 0x1F, 0x11, 0x5F, 0x09, 0xBF, 0x63, 0x1F, 0x11, 0x7F, 0x11, 0xDF, 0x19, 0x9F, 0x19, 0xBF, 0xDF, 0x5F, 0xE7, 0xBF, 0xF7, 0xFE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0xF9, 0x75, 0xF8, 0x54, 0xF8, 0x52, 0xF8, 0x4F, 0xF8, 0x23, 0xFE, 0x20, 0xFE, 0x00, 0xFE, 0x41, 0xFC, 0x01, 0xF8, 0xE1, 0xF9, 0x01, 0xFE, 0x20, 0xFE, + 0xC0, 0xFD, 0x20, 0xFA, 0x00, 0xF9, 0x81, 0xFB, 0x21, 0xFE, 0x00, 0xFE, 0x81, 0xFD, 0x80, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0xC0, 0xFA, 0x20, 0xFB, 0x20, 0xFB, 0xA0, 0xFB, 0x60, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0xC1, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0xFB, 0x62, 0xFB, 0x61, 0xFB, 0x44, 0xFB, 0x00, 0x00, 0xFD, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x5F, 0xBE, 0x9F, 0xFF, 0x3F, 0xCF, 0xBF, 0x85, 0xBF, 0x65, 0x1F, 0x66, 0xDF, 0x44, 0x9F, 0x2B, 0x9F, 0xEF, 0x9F, 0x12, 0x1F, 0x00, 0x7F, 0x62, 0x1F, 0x20, 0x5F, 0x10, 0x5F, 0x11, 0x5F, 0x12, 0x5F, 0x12, 0x3F, 0x1A, 0x7F, 0x1A, 0xBF, 0x53, 0x3F, 0x1A, 0x5F, 0x22, 0x5F, 0x2A, 0xDF, 0x21, 0xBF, 0xE7, 0x5F, 0xDF, 0x9F, 0xF7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7A, 0xF9, 0x97, 0xF8, 0x75, 0xF8, 0x53, 0xF8, 0x51, 0xF8, 0x4E, 0xFA, 0xA2, 0xFD, 0x80, 0xFD, 0x40, 0xFD, 0xE1, 0xF9, 0x00, 0xF8, 0xA2, 0xFB, 0xA0, 0xFD, 0xC0, 0xFD, 0xE0, 0xFC, 0x00, 0xF9, 0x01, 0xF8, 0x21, 0xFC, 0xA0, 0xFD, 0xA0, 0xFD, 0x60, 0xFC, 0x20, 0xF9, 0x40, 0xF9, 0x60, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xE0, 0xFA, 0x60, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x43, 0xFB, 0x00, 0x00, 0x7C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x1F, 0x53, 0x5F, 0xF7, 0xFF, 0xBE, 0x9F, 0xA6, 0x5F, 0x34, 0x7F, 0x24, 0x1F, 0x23, 0x9F, 0x19, 0x3D, 0xFF, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x40, + 0x1F, 0x10, 0xFF, 0x10, 0x5F, 0x12, 0xDF, 0x12, 0x7F, 0x12, 0xDF, 0x1A, 0x1F, 0x2B, 0xDF, 0x53, 0xFF, 0x2A, 0xFF, 0x2A, 0xFF, 0x32, 0x7F, 0x22, 0xBF, 0xE7, 0x9F, 0xEF, 0xBF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7B, 0xF9, 0x98, 0xF8, 0x76, 0xF8, 0x75, 0xF8, 0x53, 0xF8, 0x51, 0xF8, 0x4B, 0xFB, 0x00, 0xFD, 0x20, 0xFD, 0x81, 0xFC, 0x02, 0xF8, 0x03, 0xF8, 0x81, 0xFC, 0x60, 0xFD, 0x60, 0xFD, 0x61, 0xFB, 0x01, 0xF8, 0x01, 0xF8, 0xA0, 0xFC, 0x60, 0xFD, 0x40, 0xFD, 0x60, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0xA0, 0xF9, 0xE0, 0xF9, 0x20, 0xFA, 0xC0, 0xFA, 0xC0, 0xFB, 0x00, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0xFB, 0x01, 0xFB, 0x01, 0xFB, 0x24, 0xFB, 0x00, 0x00, + 0x9C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0xDF, 0xDE, 0x5F, 0xEF, 0xFF, 0xBE, 0x3F, 0xC7, 0x3F, 0x33, 0x5F, 0x22, 0x1F, 0x41, 0x1F, 0xF8, 0x5B, 0xFE, 0xFF, 0xFD, 0x1F, 0x00, 0x1F, 0xF8, 0xBF, 0x10, 0xDF, 0x11, 0x9F, 0x12, 0xDF, 0x12, 0xDF, 0x22, 0x1F, 0x23, 0xFF, 0x4B, 0x7F, 0x43, 0x5F, 0x33, 0x5F, 0x3B, 0x3F, 0x3B, 0x1F, 0xCF, 0xBF, 0xE7, 0xDF, 0xFF, 0xFF, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xF9, 0xDA, 0xF8, 0xB8, 0xF8, 0x76, 0xF8, 0x74, 0xF8, 0x51, 0xF8, 0x2F, 0xF8, 0x83, 0xFC, 0xE0, 0xFC, 0xA0, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x43, 0xF8, 0x00, 0xFD, 0x00, 0xFD, 0x60, 0xFC, 0x01, 0xF8, 0x01, 0xF8, 0x61, 0xFA, 0x20, 0xFD, 0x20, 0xFD, 0xA0, 0xFA, 0x00, 0xF9, 0x20, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, 0x00, 0xFA, 0xA0, 0xFA, + 0xA0, 0xFB, 0xE0, 0xFB, 0x20, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0x5F, 0xA6, 0x3F, 0xC7, 0xBF, 0x1A, 0xBF, 0xAA, 0x00, 0xF8, 0x00, 0xF8, 0x1F, 0xF8, 0xBE, 0xFE, 0x1F, 0x6A, 0x7F, 0x08, 0xFF, 0x28, 0x9F, 0x21, 0x1F, 0x22, 0xFF, 0x2A, 0x7F, 0x2B, 0xFF, 0x43, 0x3F, 0x54, 0x9F, 0x43, 0x9F, 0x43, 0x7F, 0x43, 0x1F, 0x43, 0x9F, 0xE7, 0x7F, 0xDF, 0xBF, 0xFF, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFD, 0x1E, 0xF9, 0xDC, 0xF8, 0xBA, 0xF8, 0x97, 0xF8, 0x75, 0xF8, 0x73, 0xF8, 0x70, 0xF8, 0x06, 0xFC, 0xA0, 0xFC, 0x60, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x03, 0xF8, + 0x80, 0xFC, 0xC0, 0xFC, 0x20, 0xFC, 0x01, 0xF8, 0x01, 0xF8, 0x81, 0xF8, 0xE0, 0xFC, 0xE0, 0xFC, 0x80, 0xFA, 0xE0, 0xF8, 0x00, 0xF9, 0x40, 0xF9, 0xC0, 0xF9, 0x00, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0xE1, 0xFB, 0x43, 0xFC, 0x63, 0xFC, 0x63, 0xFC, 0x44, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFB, 0x1C, 0xFC, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x5F, 0xE7, 0xFF, 0xE6, 0x1F, 0xBF, 0xDF, 0x8D, 0xBF, 0x52, 0x00, 0xF8, 0x1F, 0xF8, 0x1F, 0x20, 0xDF, 0x51, 0xFF, 0xEC, 0x3F, 0xAB, 0x9F, 0x39, 0x5F, 0x32, 0xDF, 0x32, 0x3F, 0x3B, 0x3F, 0x64, 0x5F, 0x64, 0xBF, 0x53, 0xDF, 0x53, 0x9F, 0x53, 0x7F, 0x53, 0x5F, 0x3B, 0xDF, 0xEF, 0x3F, 0xCF, 0x9F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x3F, 0xF9, 0x1D, 0xF9, 0xFB, 0xF8, 0xB9, 0xF8, 0x97, 0xF8, 0x94, 0xF8, 0x71, 0xF8, 0xA6, 0xFB, 0x40, 0xFC, 0x00, 0xFC, 0x04, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x60, 0xFC, 0x80, 0xFC, 0xA0, 0xFB, 0x01, 0xF8, 0x01, 0xF8, 0x61, 0xF9, 0xA0, 0xFC, 0x80, 0xFC, 0xE0, 0xF8, 0x20, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x60, 0xFB, 0x80, 0xFB, 0xC2, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xFB, 0xDC, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x5F, 0xF7, 0x9F, 0xFF, 0x7F, 0xA6, 0xFF, 0xBE, 0x9F, 0x1B, 0x1F, 0x80, 0x1F, 0x48, 0x1F, 0x68, 0x7F, 0x90, 0x7F, 0x88, 0x1F, 0xBB, + 0xFF, 0xAB, 0xDF, 0x93, 0x1F, 0x84, 0x3F, 0x84, 0x9F, 0x6B, 0xBF, 0x73, 0x1F, 0x7C, 0x3F, 0x84, 0xDF, 0x7B, 0x3F, 0x63, 0xDF, 0xEF, 0xBF, 0xEF, 0xBF, 0xF7, 0xBF, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xDA, 0x7F, 0xF9, 0x3E, 0xF9, 0x1D, 0xF9, 0xDB, 0xF8, 0xB9, 0xF8, 0x96, 0xF8, 0x73, 0xF8, 0xA4, 0xFB, 0x00, 0xFC, 0x82, 0xFB, 0x06, 0xF8, 0x06, 0xF8, 0x25, 0xF9, 0x20, 0xFC, 0x40, 0xFC, 0x81, 0xF9, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0xFB, 0x60, 0xFC, 0xE0, 0xFB, 0x80, 0xF8, 0x00, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0xE0, 0xFA, 0x00, 0xFB, 0x00, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x42, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0x40, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0xFC, 0xBD, 0xFB, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xE6, 0x7F, 0xF7, 0xFF, 0xBE, 0x1F, 0xBF, 0x1F, 0x23, 0xBF, 0xD8, 0x7F, 0xF0, 0xBF, 0xE8, 0x5F, 0xF1, 0x7F, 0xF1, 0x1F, 0xE2, 0x1F, 0xD2, 0x7F, 0xBA, 0xDF, 0xB2, 0x3F, 0xA3, 0x9F, 0xA3, 0x3F, 0xCE, 0xDF, 0xFF, 0xBF, 0x9C, 0xBF, 0xEF, 0xFF, 0xF7, 0x5F, 0xDF, 0xBF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xCB, 0x1F, 0xDA, 0xBF, 0xF1, 0x7F, 0xF9, 0x3E, 0xF9, 0xFC, 0xF8, 0xDA, 0xF8, 0xD8, 0xF8, 0xB1, 0xF9, 0xC0, 0xFB, 0xC0, 0xFB, 0xA6, 0xF9, 0x08, 0xF8, 0x07, 0xF8, 0x23, 0xFB, 0xE0, 0xFB, 0x60, 0xFB, 0x02, 0xF8, 0x01, 0xF8, 0x01, 0xF8, 0x80, 0xFB, 0xE0, 0xFB, 0xE0, 0xF9, 0x60, 0xF8, 0x00, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x60, 0xFA, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, + 0x80, 0xF9, 0x60, 0xF9, 0x41, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x20, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xFB, 0xFE, 0xFB, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0x7F, 0xF7, 0xBF, 0xCE, 0x1F, 0xC7, 0xBF, 0xB6, 0xBF, 0x3A, 0x3E, 0xF9, 0xBB, 0xF8, 0x1A, 0xF9, 0x3B, 0xF9, 0xBC, 0xF9, 0xFE, 0xF9, 0x5F, 0xF2, 0xBF, 0xEA, 0xFF, 0xD2, 0x3F, 0xCB, 0xFF, 0xCC, 0x5F, 0xEF, 0x9F, 0xE7, 0xFF, 0xFF, 0x9F, 0xE7, 0xDF, 0xFF, 0x3F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x9F, 0xBA, 0x3F, 0xD2, 0xFF, 0xE1, 0x7F, 0xF1, 0x5F, 0xF9, 0x3E, 0xF9, 0x1C, 0xF9, 0xD9, 0xF8, 0x47, 0xFB, 0xA0, 0xFB, 0xC6, 0xFA, 0x2A, 0xF8, 0x09, 0xF8, 0x27, 0xF9, 0x80, 0xFB, + 0x60, 0xFB, 0x82, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x20, 0xFA, 0x40, 0xFB, 0x60, 0xFA, 0x41, 0xF8, 0x41, 0xF8, 0xC0, 0xF9, 0x60, 0xFA, 0x80, 0xFA, 0x40, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x62, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xF9, 0xA6, 0xF9, 0xA6, 0xF9, 0xE7, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0xBF, 0xFB, 0x3F, 0xFD, 0xDF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0x7F, 0xE7, 0xBF, 0xFF, 0xFF, 0xD6, 0x1F, 0xC7, 0xFF, 0xC6, 0x3F, 0x5D, 0x3F, 0xBA, 0x39, 0xF9, 0xF8, 0xF8, 0x19, 0xF9, 0x7B, 0xF9, 0xDD, 0xF9, 0x5E, 0xFA, 0xBF, 0xEA, 0xDF, 0xDA, 0x5F, 0x73, 0xDF, 0xF7, 0xFF, 0xF7, 0x9F, 0xE7, 0xDF, 0xFF, 0x5F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xA2, 0x7F, 0xB2, 0x3F, 0xC2, 0xFF, 0xD9, 0xDF, 0xE9, 0x7F, 0xF9, 0x5F, 0xF9, 0x3D, 0xF9, 0x58, 0xF9, 0x09, 0xFB, 0xC9, 0xFA, 0x2E, 0xF8, 0x0C, 0xF8, 0x0A, 0xF8, 0x67, 0xF9, 0x84, 0xFA, 0x44, 0xF9, 0x03, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x01, 0xF8, 0x61, 0xF8, 0x21, 0xF8, 0x42, 0xF8, 0x42, 0xF8, 0x41, 0xF9, 0xE0, 0xF9, 0x40, 0xFA, 0x80, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xFA, 0x08, 0xFA, 0xE7, 0xF9, 0x69, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xF3, 0xBF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x5F, 0xE7, 0xBF, 0xFF, 0xBF, 0xD6, 0xBF, 0xBE, 0x1F, 0xCF, 0xFF, 0xC6, 0xBF, 0x8D, 0x5F, 0x1B, + 0x9F, 0xAA, 0x1F, 0xFA, 0x7F, 0xEA, 0xFF, 0x42, 0xDF, 0xBE, 0xFF, 0xF7, 0xFF, 0xF7, 0xDF, 0xF7, 0xBF, 0xE7, 0xDF, 0xF7, 0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x9C, 0xBF, 0x9A, 0x7F, 0xAA, 0x3F, 0xBA, 0x1F, 0xD2, 0xFF, 0xE9, 0xBF, 0xF1, 0x7F, 0xF9, 0x5E, 0xF9, 0x1B, 0xF9, 0xB7, 0xF8, 0x53, 0xF8, 0x30, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x03, 0xF8, 0x02, 0xF8, 0x22, 0xF8, 0x21, 0xF8, 0x22, 0xF8, 0x22, 0xF8, 0x40, 0xF9, 0xC0, 0xF9, 0x00, 0xFA, 0x60, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xF8, 0x80, 0xF8, 0x80, 0xF8, 0xE3, 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, 0x7F, 0xF5, 0x7F, 0xEB, 0x7F, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x1F, 0xEF, 0x1F, 0xEF, 0x7F, 0xBE, 0xBF, 0xBE, 0x3F, 0xD7, 0x7F, 0xDF, 0x7F, 0xE7, 0xDF, 0xEF, 0xDF, 0xF7, 0xFF, 0xF7, 0xFF, 0xF7, 0xFF, 0xF7, 0xBF, 0xEF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x8C, 0x1F, 0x7B, 0xDF, 0x92, 0x7F, 0xA2, 0x5F, 0xB2, 0x3F, 0xD2, 0xFF, 0xE9, 0xDF, 0xF9, 0x9F, 0xF9, 0x7E, 0xF9, 0x1C, 0xF9, 0xD8, 0xF8, 0x74, 0xF8, 0x30, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x80, 0xF8, 0x80, 0xF8, 0x40, 0xF8, 0x21, 0xF8, 0x40, 0xF8, 0x60, 0xF8, 0x80, 0xF8, 0xC0, 0xF8, 0x21, 0xF9, 0x07, 0xFB, 0x28, 0xFB, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0xE3, 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, 0x3F, 0xEC, 0x5F, 0xE3, 0x7F, 0xDB, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x8D, 0x1F, 0xEF, 0x5F, 0xEF, 0x1F, 0xEF, 0xFF, 0xCE, 0x3F, 0xCF, 0x7F, 0xE7, 0x9F, 0xE7, 0x9F, 0xE7, 0x9F, 0xF7, 0xBF, 0xFF, 0xDF, 0xFF, 0x7F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7C, 0x5F, 0x5B, 0x3F, 0x73, 0xFF, 0x8A, 0x9F, 0x9A, 0x5F, 0xB2, 0x3F, 0xCA, 0x1F, 0xE2, 0x1F, 0xFA, 0xDF, 0xF9, 0x7E, 0xF9, 0x3B, 0xF9, 0xF8, 0xF8, 0xB5, 0xF8, 0x51, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, + 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x80, 0xF8, 0xA0, 0xF8, 0x40, 0xF8, 0x20, 0xF8, 0x40, 0xF8, 0x60, 0xF8, 0x80, 0xF8, 0xA0, 0xF8, 0x23, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0xC2, 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, 0x5F, 0xDC, 0x1F, 0xCB, 0x3F, 0xC3, 0xBF, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x5F, 0xEF, 0x5F, 0xB6, 0x5F, 0xEF, 0xBF, 0xFF, 0xBF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x9F, 0xE7, 0xBF, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x5B, 0x7F, 0x4B, 0x7F, 0x53, 0x5F, 0x6B, + 0x3F, 0x7B, 0xFF, 0x9A, 0x5F, 0xAB, 0x5F, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xFC, 0xDA, 0xFA, 0xB6, 0xF9, 0xF2, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x24, 0xF8, 0x61, 0xF8, 0x81, 0xF8, 0x21, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x4C, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xFB, 0x6D, 0xFB, 0xCF, 0xFB, 0x30, 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, 0xDF, 0xD4, 0x1F, 0xBB, 0x1F, 0xB3, 0x1F, 0xB4, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0x9F, 0x94, 0x1F, 0x5B, 0x3F, 0x4B, 0x9F, 0x5B, 0xDF, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xF9, 0xEA, 0xF8, 0x48, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x01, 0xF8, 0x00, 0xF8, 0x20, 0xF8, 0x60, 0xF8, 0xA1, 0xF8, 0x8A, 0xFA, 0x00, 0x00, 0xE8, 0xFA, 0x63, 0xFA, 0x63, 0xFA, 0x09, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xAB, 0xFF, 0xA2, 0x1F, 0xA3, 0x7F, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xAD, 0xDF, 0x7B, 0x1F, 0xE7, 0xFF, 0xFF, 0x5F, 0xEF, 0x1F, 0xA5, 0x1F, 0x94, 0x9F, 0x9B, 0x5F, 0xAB, 0x5F, 0xBB, 0x3F, 0xC3, 0x9F, 0xD3, 0x1F, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xFB, 0xA8, 0xF9, 0xE6, 0xF8, 0xA4, 0xF8, 0x63, 0xF8, 0x63, 0xF8, 0x62, 0xF8, 0xA3, 0xF8, 0x04, 0xF9, 0x49, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFA, 0x20, 0xFA, 0x40, 0xFA, + 0x85, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xBC, 0x3F, 0x9B, 0xDF, 0x82, 0x1F, 0x73, 0x9F, 0x73, 0xDF, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xCE, 0x5F, 0x6C, 0xDF, 0x4B, 0x9F, 0x43, 0x7F, 0x4B, 0x7F, 0x63, 0x5F, 0x6B, 0x3F, 0x73, 0x3F, 0x83, 0x1F, 0x93, 0xDF, 0xA2, 0x9F, 0xB2, 0x5F, 0xC2, 0x3F, 0xD2, 0x3F, 0xE2, 0x3F, 0xEA, 0x7F, 0xFA, 0x7D, 0xFA, 0x3B, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x65, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xAC, 0x5F, 0x7B, 0x3F, 0x63, 0x5F, 0x53, 0x5F, 0x4B, 0x5F, 0x43, 0x7F, 0x3B, 0x7F, 0x3B, 0x9F, 0x33, 0x9F, 0x33, 0x9F, 0x2B, 0x9F, 0x2B, 0x9F, 0x2B, 0x7F, 0x2B, 0x9F, 0x2B, 0x9F, 0x33, 0x9F, 0x3B, 0x7F, 0x4B, 0x7F, 0x5B, 0x7F, 0x6B, 0x5F, 0x73, 0x3F, 0x83, + 0x1F, 0x93, 0xFF, 0xA2, 0xDF, 0xB2, 0x9F, 0xC2, 0x9F, 0xD2, 0x7F, 0xE2, 0x5F, 0xF2, 0x3E, 0xFA, 0xBB, 0xF9, 0x78, 0xF9, 0x56, 0xF9, 0xF4, 0xF9, 0x56, 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, 0xCD, 0xFB, 0xEE, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x8C, 0xDF, 0x5B, 0x7F, 0x4B, + 0x7F, 0x3B, 0x7F, 0x33, 0x9F, 0x2B, 0x9F, 0x2B, 0x7F, 0x2B, 0x9F, 0x2B, 0x9F, 0x2B, 0x9F, 0x33, 0xBF, 0x3B, 0xDF, 0x43, 0x1F, 0x54, 0x5F, 0x6C, 0x3F, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + //alpha channel data: - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0xAC,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x9A,0xEF,0xFD,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xD9,0xFE,0xFE,0xFE,0x53,0x00,0x00,0x00,0x00,0x6C,0xA9,0xAA,0xAB,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xF7,0xFE,0xFE,0xFE,0xFD,0x48,0x00,0x00,0x00,0x00,0xA2,0xFE,0xFE,0xFD,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xC6,0xFE,0xFD,0xFD,0xFE,0xFE,0xFD,0x6D,0x00,0x00,0x00,0x00,0xA1,0xFE,0xFE,0xFD,0x3C,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xE4,0xFD,0xFE,0xFD, - 0xFE,0xFE,0xFE,0xFE,0xA3,0x00,0x00,0x00,0x00,0x8A,0xD6,0xD5,0xD4,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xF5,0xFE,0xFC,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xEA,0x00,0x37,0x6E,0xAA,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0xC8,0xFA,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xF9,0xFC,0xFE,0xFE,0x5D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0xD7,0xD9,0xA4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xA2,0xEC,0xFA,0xFB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x4C,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x7D,0xFE,0xFE,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,0x68,0xA9,0xDA,0xE9,0xF2,0xF8,0xFA,0xFB,0xFD,0xFD,0xFD,0xFE, - 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x44,0x00,0x00,0x55,0x87,0x88,0x8B,0x43,0x6F,0xE5,0xE3,0xA8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x62,0x67,0x53,0x41,0x37,0x37,0x42,0x53, - 0x66,0x80,0xA0,0xC1,0xD1,0xD8,0xDE,0xE5,0xEE,0xF6,0xF8,0xFA,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xD0,0xCE,0xD0,0xE4,0xFE,0xFE,0xFE,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,0x00,0x00,0x69,0x9E,0xBB, - 0xC8,0xCE,0xCC,0xC1,0xA6,0x79,0x00,0x00,0x00,0x60,0x8D,0xA1,0x96,0x90,0x98,0xA1,0xAA,0xB3,0xBE,0xC7,0xCE,0xD3,0xDA,0xE1,0xE9,0xF1,0xF7,0xF8,0xFB,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAF,0xE9,0xFC,0xFB,0xF4,0xEA,0xE8,0xEA,0xF1,0xF6,0xF7,0xEC,0xBD,0x5F,0x1E,0x1E,0x53,0x85,0x8C,0x97,0xA1,0xAB,0xB2,0xBB,0xC2,0xC8,0xCD,0xD5,0xDD,0xE4,0xED,0xF3,0xF7,0xFB,0xFD,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, - 0x71,0x00,0x00,0x00,0x7F,0xBE,0xBE,0xBF,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xE8,0xF6,0xDB,0xA8,0x69,0x2D,0x25,0x2D,0x26,0x29,0x5E,0x99,0xCE,0xEE,0xEB,0xB2,0x3C,0x1E,0x26,0x6C,0x91,0x9C,0xA7,0xAF,0xB7,0xBD,0xC3,0xCA,0xD0,0xD7,0xDE,0xE8,0xF0,0xF5,0xFA,0xFC,0xFE,0xFD, - 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x6F,0x00,0x00,0x00,0xA9,0xFE,0xFE,0xFD,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0xD8,0xF2,0xC4,0x70,0x31,0x4C,0x4D,0x4F,0x49,0x48,0x45,0x4B,0x4D,0x48,0x27,0x69,0xC2,0xE4,0xD9,0x71,0x1E,0x1E,0x64,0x97, - 0xA3,0xAC,0xB3,0xB9,0xBF,0xC6,0xCC,0xD2,0xDA,0xE3,0xED,0xF4,0xFA,0xFD,0xFE,0xFD,0xFC,0xFC,0xFD,0xFD,0xFE,0xFD,0xF6,0xF2,0xFB,0xFD,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0x9D,0x00,0x00,0x00,0xA9,0xFE,0xFE,0xFD,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xEF,0xE6,0x89,0x2C,0x4E,0x4B,0x2E,0x3F,0x4A, - 0x4F,0x4C,0x48,0x40,0x31,0x21,0x34,0x42,0x28,0x86,0xDD,0xE2,0x84,0x1E,0x1E,0x6E,0x9E,0xA8,0xAE,0xB4,0xBA,0xC0,0xC5,0xCC,0xD3,0xDC,0xEC,0xFC,0xEE,0xFA,0xFD,0xFD,0xFE,0xEC,0xF5,0xFC,0xFD,0xFD,0xFD,0xDC,0xF3,0xFC,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xA9,0x00,0x00,0x00,0x87,0xC9,0xC9,0xC7,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x99,0xEF,0xD8,0x5B,0x42,0x4B,0x34,0x52,0x58,0x41,0x2C,0x29,0x27,0x1E,0x1E,0x26,0x31,0x31,0x21,0x38,0x39,0x61,0xD3,0xDC,0x7A,0x1E,0x20,0x80,0xA1,0xA9,0xAD,0xB3,0xB9,0xBF,0xC5,0xCD,0xD4,0xE5,0xFE,0xE4,0xE8,0xFA,0xFB,0xFE,0xEF,0xDF,0xFA,0xFD,0xFD,0xFE,0xE1,0xEA,0xFC,0xFC,0xFD,0xFD,0xFC,0xFD,0xFC, - 0xE0,0xCA,0xCB,0xCC,0x5D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xE7,0xD7,0x4A,0x4B,0x3C,0x42,0x52,0x35,0x7B,0xBF,0xAA,0x95,0x6D,0x49,0x35,0x22,0x10,0x16,0x2E,0x28,0x29,0x3B,0x55,0xD2,0xD6,0x56,0x1E,0x35,0x96,0xA3,0xA8,0xAD,0xB3,0xB9,0xC0,0xC7,0xCE,0xEB,0xFE,0xE4,0xD7,0xF5,0xF7, - 0xFE,0xEE,0xD4,0xF6,0xFC,0xFE,0xFE,0xDE,0xE8,0xFC,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFB,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xF0,0xF0,0xE6,0x00,0x00,0x00,0x00,0xD1,0xE0,0x66,0x3C,0x39,0x3F,0x44,0x4B,0xD1,0xFE,0xFF,0xE6,0x95,0x66,0x43,0x2F,0x20,0x17,0x11,0x07,0x20,0x2C,0x24,0x3B,0x68,0xD4,0xB8,0x1F, - 0x1E,0x67,0x9B,0xA0,0xA7,0xAD,0xB4,0xBA,0xC1,0xCB,0xFA,0xFD,0xD1,0xD3,0xF0,0xFA,0xFD,0xDC,0xD3,0xF5,0xFB,0xFE,0xF5,0xDA,0xF0,0xFB,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFD,0xFD,0xFC,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xFE,0xFE,0xF0,0x00,0x00,0x00,0x8F,0xE9,0x9F,0x26,0x3C,0x36,0x3D,0x45,0xE9,0xFF,0xFF,0xFF,0xF1, - 0x8F,0x5A,0x38,0x26,0x1A,0x14,0x11,0x0E,0x05,0x1C,0x28,0x2E,0x2C,0x9E,0xD2,0x7B,0x1E,0x26,0x8C,0x99,0xA0,0xA6,0xAD,0xB3,0xB8,0xE9,0xFE,0xED,0xC1,0xDF,0xF6,0xFE,0xF7,0xC3,0xDE,0xF8,0xFD,0xFD,0xE5,0xE6,0xF9,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFC,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xFE,0xFE,0xF0, - 0x00,0x00,0x00,0xD2,0xD7,0x35,0x43,0x27,0x3D,0x27,0xB3,0xFD,0xFE,0xFE,0xFE,0xD1,0x9F,0x81,0x5A,0x37,0x11,0x10,0x0E,0x0B,0x04,0x01,0x20,0x21,0x35,0x3C,0xC4,0xB5,0x1E,0x1E,0x6A,0x91,0x98,0xA0,0xA4,0xA3,0xC4,0xFE,0xFB,0xB0,0xC1,0xEA,0xFE,0xFE,0xCC,0xC5,0xEC,0xFB,0xFE,0xE8,0xE0,0xF2,0xFD,0xFD,0xFE,0xFE,0xFD,0xFD,0xFD,0xFE, - 0xFE,0xFD,0xFD,0xFC,0xC4,0xB9,0xBA,0xBB,0xC1,0xC3,0xC5,0xC8,0x78,0x6C,0x6A,0x65,0x00,0x00,0x6C,0xE3,0xA1,0x28,0x33,0x38,0x24,0x7E,0xB4,0xD1,0xF0,0xEC,0xE7,0xC7,0x88,0x54,0x36,0x2B,0x2A,0x17,0x06,0x04,0x01,0x03,0x06,0x28,0x20,0x2F,0x97,0xC1,0x5F,0x1E,0x42,0x79,0x74,0x75,0x76,0x77,0xF0,0xFE,0xCE,0x99,0xC9,0xF0,0xFE,0xEF, - 0xBE,0xDA,0xF1,0xFE,0xFE,0xCF,0xEB,0xFC,0xFE,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0xA2,0xDE,0x5F,0x3C,0x24,0x35,0x1B,0x90,0x97,0x98,0x93,0xBD,0xA1,0x81,0x5A,0x32,0x1B,0x10,0x0E,0x1D,0x17,0x01,0x05,0x0A,0x09,0x20,0x22,0x38,0x62,0xBC, - 0x8B,0x1E,0x1F,0x5E,0x61,0x67,0x6D,0x9C,0xFE,0xFE,0xAE,0xB7,0xC6,0xF5,0xFE,0xDF,0xD1,0xED,0xF6,0xFE,0xFE,0xC5,0xF1,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0x7E,0x00,0x00,0x00,0x00,0x00,0xBB,0xD2,0x20,0x3C,0x2B,0x27,0x44,0x77,0x73,0x71,0x81,0x82,0x5F,0x35, - 0xC9,0xEE,0x66,0x10,0x05,0x11,0x1F,0x07,0x0B,0x13,0x1A,0x15,0x2A,0x37,0x1F,0xB4,0x9D,0x1E,0x1E,0x55,0x5E,0x61,0x66,0xA4,0xFE,0xFE,0xB4,0xB7,0xC4,0xF5,0xFE,0xE7,0xD0,0xED,0xF3,0xFE,0xFE,0xD5,0xEF,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFC,0xFE,0xFE,0xFE,0xFE,0x7F,0x00,0x00,0x00, - 0x58,0x00,0xC8,0xBE,0x10,0x39,0x2D,0x1B,0x49,0x54,0x4E,0x49,0x73,0x39,0x29,0x4E,0xF2,0xF8,0x6A,0x2A,0x18,0x14,0x1D,0x22,0x13,0x1E,0x28,0x0E,0x31,0x34,0x27,0xA5,0xAA,0x1E,0x1E,0x4D,0x5C,0x5D,0x62,0x81,0xFC,0xFE,0xD6,0xA1,0xB3,0xDF,0xFE,0xFC,0xD5,0xE0,0xE1,0xEF,0xFE,0xF8,0xE2,0xF1,0xF9,0xFC,0xFE,0xFD,0xFD,0xFD,0xFE,0xFE, - 0xFE,0xFD,0xFD,0xFD,0xFD,0xFE,0xF9,0xA7,0xA1,0x9C,0x96,0x8F,0x48,0x00,0x00,0x00,0x7C,0x00,0xCD,0xB2,0x1A,0x2F,0x2D,0x12,0x1D,0x1F,0x1D,0x1A,0x43,0x20,0x06,0x29,0x44,0x4A,0x23,0x37,0x3A,0x16,0x2F,0x32,0x20,0x2B,0x35,0x19,0x34,0x33,0x33,0x9B,0xAF,0x1F,0x1E,0x4B,0x5C,0x5D,0x61,0x62,0xCC,0xFE,0xFC,0xA9,0x9D,0xB0,0xF2,0xFE, - 0xF7,0xD8,0xD2,0xAC,0xF7,0xFE,0xF5,0xD7,0xF2,0xFA,0xFE,0xFD,0xFD,0xFD,0xFE,0xFD,0xFD,0xFD,0xFD,0xFD,0xFC,0xFD,0xF3,0x00,0x00,0x00,0x00,0x5D,0xD4,0xD5,0x95,0x00,0x97,0x00,0xCA,0xB1,0x18,0x2B,0x2B,0x11,0x15,0x19,0x17,0x12,0x2C,0x10,0x01,0x0A,0x0D,0x20,0x36,0x4D,0x4C,0x25,0x44,0x46,0x33,0x3D,0x47,0x20,0x39,0x34,0x35,0x98, - 0xAF,0x20,0x1E,0x4D,0x5E,0x60,0x63,0x64,0x69,0xE4,0xFE,0xF4,0x9F,0xAF,0xA1,0xF8,0xFE,0xF0,0xCC,0x9E,0xB4,0xFC,0xFE,0xE3,0xDF,0xF6,0xFC,0xFC,0xFC,0xFB,0xFD,0xFC,0xFD,0xFD,0xFD,0xFD,0xFC,0xFC,0xF0,0x00,0x00,0x00,0x00,0x6E,0xFE,0xFE,0xB1,0x00,0xA5,0x00,0xC0,0xB8,0x10,0x2D,0x28,0x16,0x0F,0x14,0x10,0x0A,0x1E,0x04,0x01,0x04, - 0x1A,0x31,0x4A,0x62,0x3C,0x41,0x54,0x58,0x4B,0x53,0x5D,0x1D,0x42,0x38,0x2F,0x9D,0xAC,0x1F,0x1E,0x55,0x62,0x64,0x66,0x67,0x65,0x7C,0xF7,0xFE,0xC8,0x80,0x86,0xBB,0xFE,0xFE,0xA3,0x99,0x9A,0xD2,0xFE,0xFA,0xD1,0xEA,0xF6,0xF9,0xFC,0xFB,0xFC,0xFC,0xFE,0xFD,0xFD,0xFD,0xFD,0xFD,0xF0,0x00,0x00,0x00,0x00,0x5D,0xDA,0xD9,0x99,0x00, - 0xB8,0x00,0xAE,0xC5,0x1A,0x2E,0x24,0x1E,0x0A,0x0E,0x08,0x01,0x17,0x0C,0x06,0x01,0x16,0x36,0x4A,0x3A,0x35,0x64,0x73,0x5E,0x67,0x6E,0x6B,0x22,0x48,0x3C,0x1F,0xA9,0xA2,0x1E,0x1E,0x5F,0x66,0x68,0x69,0x69,0x69,0x67,0xCC,0xFE,0xEA,0x73,0x89,0x8A,0xF5,0xFE,0xBE,0x93,0x9F,0xA7,0xFD,0xFE,0xD4,0xE1,0xF5,0xF7,0xFB,0xFC,0xFC,0xFC, - 0xFE,0xFD,0xFE,0xFE,0xFE,0xFD,0xF1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0x00,0x95,0xC8,0x5D,0x2D,0x1D,0x29,0x09,0x03,0x02,0x02,0x01,0x1F,0x0C,0x11,0x11,0x15,0x23,0x43,0x67,0x77,0x81,0x7A,0x85,0x8B,0x5F,0x3A,0x41,0x3F,0x3A,0xB1,0x8F,0x1E,0x28,0x69,0x6A,0x6C,0x6C,0x6B,0x6D,0x6C,0xB1,0xFE,0xF2,0x75,0x8A,0x8E, - 0xE5,0xFE,0xC2,0x90,0xA3,0xA2,0xFB,0xFE,0xD1,0xDF,0xF5,0xF7,0xFA,0xFD,0xFD,0xFD,0xFE,0xFD,0xE9,0xAE,0xAC,0xAA,0x9F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0x6D,0x64,0xC3,0x8E,0x21,0x20,0x2C,0x16,0x03,0x02,0x02,0x07,0x09,0x20,0x23,0x23,0x34,0x46,0x5A,0x79,0x85,0x89,0x9B,0xA2,0x97,0x22,0x50,0x2F,0x3A,0x73,0xB2, - 0x71,0x1E,0x4B,0x6C,0x6E,0x6F,0x6F,0x6E,0x70,0x70,0xB7,0xFE,0xE8,0x79,0x8C,0x92,0xE9,0xFE,0xB7,0x96,0xA9,0xAD,0xFD,0xFA,0xC5,0xE2,0xF6,0xF9,0xFB,0xFE,0xFE,0xFE,0xFE,0xFD,0xD7,0x00,0x00,0x00,0x00,0xC7,0xF6,0xF6,0xE1,0x00,0x00,0x00,0x00,0x00,0xA0,0xB0,0x20,0xB1,0xB4,0x23,0x2A,0x1E,0x28,0x09,0x02,0x07,0x0E,0x11,0x12,0x1D, - 0x31,0x41,0x55,0x66,0x6D,0x8B,0xAB,0xB2,0xB8,0x5C,0x44,0x4F,0x3B,0x20,0xA7,0xB5,0x38,0x1E,0x84,0x6E,0x70,0x71,0x72,0x72,0x73,0x76,0xD6,0xFE,0xC4,0x80,0x92,0x9D,0xFB,0xF9,0x9A,0xA1,0xAF,0xCA,0xFE,0xE3,0xC2,0xEB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFD,0xFD,0xD7,0x00,0x00,0x00,0x00,0xCE,0xFD,0xFD,0xE6,0x00,0x00,0x00,0x00,0x00, - 0x54,0xDD,0x29,0x80,0xBE,0x81,0x1F,0x28,0x28,0x24,0x08,0x0D,0x13,0x18,0x1F,0x28,0x30,0x3A,0x4D,0x65,0x81,0x9B,0xCB,0xF5,0x8B,0x3D,0x68,0x39,0x46,0x66,0xBD,0x94,0x1E,0x4E,0xA2,0x7D,0x73,0x74,0x75,0x76,0x76,0x8A,0xF9,0xF5,0x87,0x8F,0x9C,0xCD,0xFE,0xD2,0xA2,0xB1,0xB4,0xEF,0xFA,0xBC,0xCA,0xF2,0xFD,0xFE,0xFC,0xFA,0xFB,0xFD, - 0xFD,0xFC,0xD6,0x00,0x00,0x00,0x00,0xD0,0xFE,0xFD,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x93,0x29,0xB0,0xBA,0x47,0x2F,0x20,0x2D,0x20,0x09,0x14,0x23,0x2D,0x37,0x43,0x4E,0x5D,0x6F,0x86,0xA1,0xB0,0x85,0x41,0x7A,0x48,0x57,0x29,0xAD,0xB8,0x48,0x1E,0x93,0xA5,0x95,0x7A,0x78,0x79,0x7A,0x7C,0xD7,0xFE,0xB0,0x8C,0xA2,0xB0,0xF9, - 0xED,0xAA,0xB3,0xC0,0xD5,0xFC,0xCC,0xBA,0xD7,0xF2,0xFD,0xFD,0xFD,0xFC,0xFA,0xE9,0xE7,0xE6,0xC3,0x00,0x00,0x00,0x00,0x69,0x7A,0x78,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xCF,0x3C,0x65,0xBC,0xA8,0x28,0x35,0x1E,0x29,0x28,0x11,0x12,0x2A,0x42,0x58,0x64,0x70,0x79,0x79,0x63,0x20,0x5F,0x82,0x50,0x5F,0x30,0x96,0xBE,0x86,0x1E, - 0x6E,0xB1,0xA9,0xA2,0x88,0x7E,0x7D,0x7E,0x89,0xD4,0xC3,0x90,0xA2,0xAE,0xBD,0xD9,0xBE,0xBB,0xC4,0xC8,0xC9,0xCA,0xD0,0xC8,0xD1,0xEE,0xFD,0xFD,0xFD,0xFE,0xEA,0x00,0x00,0x00,0x55,0x63,0x6E,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA7,0xAB,0x1E,0x85,0xBA,0x9E,0x23,0x2E,0x20,0x24,0x2E,0x25,0x18,0x11, - 0x19,0x22,0x25,0x16,0x22,0x54,0x78,0x75,0x45,0x62,0x31,0x87,0xC2,0xA7,0x24,0x4A,0xB2,0xB4,0xAE,0xA7,0x9F,0x85,0x80,0x82,0x85,0x8C,0x96,0xA4,0xAD,0xB5,0xBB,0xC3,0xC7,0xC9,0xCB,0xCE,0xD1,0xD0,0xDE,0xCF,0xD5,0xEF,0xFE,0xFE,0xFE,0xFD,0xE8,0x00,0x00,0x00,0xF4,0xFE,0xFE,0xC2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x35,0xBD,0x8C,0x1F,0x91,0xB8,0x9F,0x36,0x25,0x2E,0x1E,0x26,0x34,0x37,0x3C,0x45,0x55,0x68,0x79,0x6A,0x43,0x51,0x56,0x28,0x99,0xC7,0xAE,0x39,0x42,0xB5,0xBD,0xB7,0xB2,0xAC,0xA6,0x97,0x83,0x85,0x8A,0x91,0x9A,0xA6,0xB1,0xBA,0xBF,0xC6,0xCB,0xCD,0xCF,0xD6,0xF2,0xF2,0xEF,0xF1,0xF6,0xF9,0xFC,0xFD,0xD5,0x6C,0x64,0x00, - 0x00,0x00,0xF1,0xFE,0xFE,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xBA,0x83,0x20,0x86,0xB2,0xAA,0x67,0x14,0x2A,0x2F,0x2C,0x25,0x29,0x31,0x35,0x37,0x43,0x4F,0x50,0x36,0x5E,0xBC,0xD0,0xAE,0x3A,0x4A,0xBC,0xC9,0xC1,0xBA,0xB4,0xAD,0xA4,0x9B,0x8D,0x87,0x8E,0x95,0x9B,0xA8,0xB5,0xBE,0xC3,0xC8, - 0xCD,0xD0,0xD3,0xDC,0xFB,0xFD,0xF6,0xF6,0xF9,0xF9,0xFB,0xFD,0xAE,0x00,0x00,0x00,0x00,0x00,0xEF,0xFC,0xFC,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xB0,0x8C,0x25,0x63,0xA8,0xB4,0xA0,0x6E,0x25,0x1C,0x2C,0x38,0x43,0x49,0x47,0x36,0x18,0x69,0xB2,0xD7,0xD4,0x93,0x24,0x71,0xC3,0xCE,0xBB, - 0x9B,0x79,0x5B,0x37,0x00,0x00,0x00,0x00,0x1C,0x4C,0x69,0x8B,0xB2,0xC2,0xC6,0xCC,0xD0,0xD3,0xD7,0xDF,0xF4,0xF6,0xF3,0xF6,0xF9,0xFA,0xFC,0xE9,0x45,0x00,0x00,0x00,0x00,0x00,0x3D,0x3F,0x3D,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x99,0x99,0x48,0x32,0x81,0xAA,0xB2,0xB2,0xA0,0x8D, - 0x80,0x79,0x7F,0x92,0xAA,0xCC,0xDC,0xD8,0xAE,0x59,0x3E,0x8E,0xA2,0x7D,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x98,0xBB,0xD2,0xD8,0xDD,0xE3,0xE8,0xEC,0xF1,0xF8,0xFB,0xFA,0xD1,0x57,0x00,0x67,0xA7,0xA9,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x9A,0x76,0x3B,0x2A,0x6B,0x92,0xAE,0xBC,0xBF,0xC0,0xC5,0xCC,0xD0,0xBB,0x95,0x54,0x1E,0x32,0x50,0x22,0x1E,0x21,0x36,0x48,0x55,0x59,0x56,0x52,0x49,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x75,0x9A,0xB5,0xC5,0xCA,0xCD,0xC2,0xA5,0x5D,0x00,0x00,0x00,0x9D,0xFE,0xFE, - 0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x71,0x8F,0x7C,0x5D,0x38,0x1F,0x34,0x59,0x66,0x67,0x55,0x27,0x1E,0x1E,0x25,0x45,0x60,0x6E,0x77,0x7D,0x86,0x86,0x85,0x85,0x82,0x7F,0x7C,0x77,0x73,0x6F,0x65,0x58,0x42,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xFD,0xFC,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2D,0x61,0x81,0x92,0x8D,0x88,0x89,0x8A,0x8A,0x8B,0x8D,0x93,0x9A,0xA1,0xA0,0x9B,0x94,0x8E,0x88,0x83,0x78,0x72, - 0x72,0x70,0x6D,0x69,0x66,0x65,0x63,0x62,0x69,0x71,0x6F,0x5D,0x2D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x62,0x7C, - 0x94,0xA1,0xA8,0xA8,0xA7,0xA4,0x9F,0x92,0x81,0x70,0x5E,0x4A,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xAC, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9A, 0xEF, 0xFD, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xD9, 0xFE, 0xFE, 0xFE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xA9, 0xAA, 0xAB, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xF7, 0xFE, 0xFE, 0xFE, 0xFD, 0x48, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFE, 0xFE, 0xFD, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xC6, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0x6D, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xFE, 0xFE, 0xFD, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xE4, 0xFD, 0xFE, 0xFD, + 0xFE, 0xFE, 0xFE, 0xFE, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xD6, 0xD5, 0xD4, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xF5, 0xFE, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xEA, 0x00, 0x37, 0x6E, 0xAA, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC8, 0xFA, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF9, 0xFC, 0xFE, 0xFE, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0xD7, 0xD9, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xA2, 0xEC, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7D, 0xFE, 0xFE, 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, 0x68, 0xA9, 0xDA, 0xE9, 0xF2, 0xF8, 0xFA, 0xFB, 0xFD, 0xFD, 0xFD, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x44, 0x00, 0x00, 0x55, 0x87, 0x88, 0x8B, 0x43, 0x6F, 0xE5, 0xE3, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x62, 0x67, 0x53, 0x41, 0x37, 0x37, 0x42, 0x53, + 0x66, 0x80, 0xA0, 0xC1, 0xD1, 0xD8, 0xDE, 0xE5, 0xEE, 0xF6, 0xF8, 0xFA, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xD0, 0xCE, 0xD0, 0xE4, 0xFE, 0xFE, 0xFE, 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, 0x00, 0x00, 0x69, 0x9E, 0xBB, + 0xC8, 0xCE, 0xCC, 0xC1, 0xA6, 0x79, 0x00, 0x00, 0x00, 0x60, 0x8D, 0xA1, 0x96, 0x90, 0x98, 0xA1, 0xAA, 0xB3, 0xBE, 0xC7, 0xCE, 0xD3, 0xDA, 0xE1, 0xE9, 0xF1, 0xF7, 0xF8, 0xFB, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAF, 0xE9, 0xFC, 0xFB, 0xF4, 0xEA, 0xE8, 0xEA, 0xF1, 0xF6, 0xF7, 0xEC, 0xBD, 0x5F, 0x1E, 0x1E, 0x53, 0x85, 0x8C, 0x97, 0xA1, 0xAB, 0xB2, 0xBB, 0xC2, 0xC8, 0xCD, 0xD5, 0xDD, 0xE4, 0xED, 0xF3, 0xF7, 0xFB, 0xFD, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0x71, 0x00, 0x00, 0x00, 0x7F, 0xBE, 0xBE, 0xBF, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xE8, 0xF6, 0xDB, 0xA8, 0x69, 0x2D, 0x25, 0x2D, 0x26, 0x29, 0x5E, 0x99, 0xCE, 0xEE, 0xEB, 0xB2, 0x3C, 0x1E, 0x26, 0x6C, 0x91, 0x9C, 0xA7, 0xAF, 0xB7, 0xBD, 0xC3, 0xCA, 0xD0, 0xD7, 0xDE, 0xE8, 0xF0, 0xF5, 0xFA, 0xFC, 0xFE, 0xFD, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x6F, 0x00, 0x00, 0x00, 0xA9, 0xFE, 0xFE, 0xFD, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xD8, 0xF2, 0xC4, 0x70, 0x31, 0x4C, 0x4D, 0x4F, 0x49, 0x48, 0x45, 0x4B, 0x4D, 0x48, 0x27, 0x69, 0xC2, 0xE4, 0xD9, 0x71, 0x1E, 0x1E, 0x64, 0x97, + 0xA3, 0xAC, 0xB3, 0xB9, 0xBF, 0xC6, 0xCC, 0xD2, 0xDA, 0xE3, 0xED, 0xF4, 0xFA, 0xFD, 0xFE, 0xFD, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFD, 0xF6, 0xF2, 0xFB, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0x9D, 0x00, 0x00, 0x00, 0xA9, 0xFE, 0xFE, 0xFD, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xEF, 0xE6, 0x89, 0x2C, 0x4E, 0x4B, 0x2E, 0x3F, 0x4A, + 0x4F, 0x4C, 0x48, 0x40, 0x31, 0x21, 0x34, 0x42, 0x28, 0x86, 0xDD, 0xE2, 0x84, 0x1E, 0x1E, 0x6E, 0x9E, 0xA8, 0xAE, 0xB4, 0xBA, 0xC0, 0xC5, 0xCC, 0xD3, 0xDC, 0xEC, 0xFC, 0xEE, 0xFA, 0xFD, 0xFD, 0xFE, 0xEC, 0xF5, 0xFC, 0xFD, 0xFD, 0xFD, 0xDC, 0xF3, 0xFC, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xA9, 0x00, 0x00, 0x00, 0x87, 0xC9, 0xC9, 0xC7, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xEF, 0xD8, 0x5B, 0x42, 0x4B, 0x34, 0x52, 0x58, 0x41, 0x2C, 0x29, 0x27, 0x1E, 0x1E, 0x26, 0x31, 0x31, 0x21, 0x38, 0x39, 0x61, 0xD3, 0xDC, 0x7A, 0x1E, 0x20, 0x80, 0xA1, 0xA9, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCD, 0xD4, 0xE5, 0xFE, 0xE4, 0xE8, 0xFA, 0xFB, 0xFE, 0xEF, 0xDF, 0xFA, 0xFD, 0xFD, 0xFE, 0xE1, 0xEA, 0xFC, 0xFC, 0xFD, 0xFD, 0xFC, 0xFD, 0xFC, + 0xE0, 0xCA, 0xCB, 0xCC, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xE7, 0xD7, 0x4A, 0x4B, 0x3C, 0x42, 0x52, 0x35, 0x7B, 0xBF, 0xAA, 0x95, 0x6D, 0x49, 0x35, 0x22, 0x10, 0x16, 0x2E, 0x28, 0x29, 0x3B, 0x55, 0xD2, 0xD6, 0x56, 0x1E, 0x35, 0x96, 0xA3, 0xA8, 0xAD, 0xB3, 0xB9, 0xC0, 0xC7, 0xCE, 0xEB, 0xFE, 0xE4, 0xD7, 0xF5, 0xF7, + 0xFE, 0xEE, 0xD4, 0xF6, 0xFC, 0xFE, 0xFE, 0xDE, 0xE8, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFB, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xF0, 0xF0, 0xE6, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xE0, 0x66, 0x3C, 0x39, 0x3F, 0x44, 0x4B, 0xD1, 0xFE, 0xFF, 0xE6, 0x95, 0x66, 0x43, 0x2F, 0x20, 0x17, 0x11, 0x07, 0x20, 0x2C, 0x24, 0x3B, 0x68, 0xD4, 0xB8, 0x1F, + 0x1E, 0x67, 0x9B, 0xA0, 0xA7, 0xAD, 0xB4, 0xBA, 0xC1, 0xCB, 0xFA, 0xFD, 0xD1, 0xD3, 0xF0, 0xFA, 0xFD, 0xDC, 0xD3, 0xF5, 0xFB, 0xFE, 0xF5, 0xDA, 0xF0, 0xFB, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFD, 0xFD, 0xFC, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFE, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0x8F, 0xE9, 0x9F, 0x26, 0x3C, 0x36, 0x3D, 0x45, 0xE9, 0xFF, 0xFF, 0xFF, 0xF1, + 0x8F, 0x5A, 0x38, 0x26, 0x1A, 0x14, 0x11, 0x0E, 0x05, 0x1C, 0x28, 0x2E, 0x2C, 0x9E, 0xD2, 0x7B, 0x1E, 0x26, 0x8C, 0x99, 0xA0, 0xA6, 0xAD, 0xB3, 0xB8, 0xE9, 0xFE, 0xED, 0xC1, 0xDF, 0xF6, 0xFE, 0xF7, 0xC3, 0xDE, 0xF8, 0xFD, 0xFD, 0xE5, 0xE6, 0xF9, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xFE, 0xFE, 0xF0, + 0x00, 0x00, 0x00, 0xD2, 0xD7, 0x35, 0x43, 0x27, 0x3D, 0x27, 0xB3, 0xFD, 0xFE, 0xFE, 0xFE, 0xD1, 0x9F, 0x81, 0x5A, 0x37, 0x11, 0x10, 0x0E, 0x0B, 0x04, 0x01, 0x20, 0x21, 0x35, 0x3C, 0xC4, 0xB5, 0x1E, 0x1E, 0x6A, 0x91, 0x98, 0xA0, 0xA4, 0xA3, 0xC4, 0xFE, 0xFB, 0xB0, 0xC1, 0xEA, 0xFE, 0xFE, 0xCC, 0xC5, 0xEC, 0xFB, 0xFE, 0xE8, 0xE0, 0xF2, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, + 0xFE, 0xFD, 0xFD, 0xFC, 0xC4, 0xB9, 0xBA, 0xBB, 0xC1, 0xC3, 0xC5, 0xC8, 0x78, 0x6C, 0x6A, 0x65, 0x00, 0x00, 0x6C, 0xE3, 0xA1, 0x28, 0x33, 0x38, 0x24, 0x7E, 0xB4, 0xD1, 0xF0, 0xEC, 0xE7, 0xC7, 0x88, 0x54, 0x36, 0x2B, 0x2A, 0x17, 0x06, 0x04, 0x01, 0x03, 0x06, 0x28, 0x20, 0x2F, 0x97, 0xC1, 0x5F, 0x1E, 0x42, 0x79, 0x74, 0x75, 0x76, 0x77, 0xF0, 0xFE, 0xCE, 0x99, 0xC9, 0xF0, 0xFE, 0xEF, + 0xBE, 0xDA, 0xF1, 0xFE, 0xFE, 0xCF, 0xEB, 0xFC, 0xFE, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xDE, 0x5F, 0x3C, 0x24, 0x35, 0x1B, 0x90, 0x97, 0x98, 0x93, 0xBD, 0xA1, 0x81, 0x5A, 0x32, 0x1B, 0x10, 0x0E, 0x1D, 0x17, 0x01, 0x05, 0x0A, 0x09, 0x20, 0x22, 0x38, 0x62, 0xBC, + 0x8B, 0x1E, 0x1F, 0x5E, 0x61, 0x67, 0x6D, 0x9C, 0xFE, 0xFE, 0xAE, 0xB7, 0xC6, 0xF5, 0xFE, 0xDF, 0xD1, 0xED, 0xF6, 0xFE, 0xFE, 0xC5, 0xF1, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xD2, 0x20, 0x3C, 0x2B, 0x27, 0x44, 0x77, 0x73, 0x71, 0x81, 0x82, 0x5F, 0x35, + 0xC9, 0xEE, 0x66, 0x10, 0x05, 0x11, 0x1F, 0x07, 0x0B, 0x13, 0x1A, 0x15, 0x2A, 0x37, 0x1F, 0xB4, 0x9D, 0x1E, 0x1E, 0x55, 0x5E, 0x61, 0x66, 0xA4, 0xFE, 0xFE, 0xB4, 0xB7, 0xC4, 0xF5, 0xFE, 0xE7, 0xD0, 0xED, 0xF3, 0xFE, 0xFE, 0xD5, 0xEF, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0x7F, 0x00, 0x00, 0x00, + 0x58, 0x00, 0xC8, 0xBE, 0x10, 0x39, 0x2D, 0x1B, 0x49, 0x54, 0x4E, 0x49, 0x73, 0x39, 0x29, 0x4E, 0xF2, 0xF8, 0x6A, 0x2A, 0x18, 0x14, 0x1D, 0x22, 0x13, 0x1E, 0x28, 0x0E, 0x31, 0x34, 0x27, 0xA5, 0xAA, 0x1E, 0x1E, 0x4D, 0x5C, 0x5D, 0x62, 0x81, 0xFC, 0xFE, 0xD6, 0xA1, 0xB3, 0xDF, 0xFE, 0xFC, 0xD5, 0xE0, 0xE1, 0xEF, 0xFE, 0xF8, 0xE2, 0xF1, 0xF9, 0xFC, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, + 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, 0xF9, 0xA7, 0xA1, 0x9C, 0x96, 0x8F, 0x48, 0x00, 0x00, 0x00, 0x7C, 0x00, 0xCD, 0xB2, 0x1A, 0x2F, 0x2D, 0x12, 0x1D, 0x1F, 0x1D, 0x1A, 0x43, 0x20, 0x06, 0x29, 0x44, 0x4A, 0x23, 0x37, 0x3A, 0x16, 0x2F, 0x32, 0x20, 0x2B, 0x35, 0x19, 0x34, 0x33, 0x33, 0x9B, 0xAF, 0x1F, 0x1E, 0x4B, 0x5C, 0x5D, 0x61, 0x62, 0xCC, 0xFE, 0xFC, 0xA9, 0x9D, 0xB0, 0xF2, 0xFE, + 0xF7, 0xD8, 0xD2, 0xAC, 0xF7, 0xFE, 0xF5, 0xD7, 0xF2, 0xFA, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFD, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xD4, 0xD5, 0x95, 0x00, 0x97, 0x00, 0xCA, 0xB1, 0x18, 0x2B, 0x2B, 0x11, 0x15, 0x19, 0x17, 0x12, 0x2C, 0x10, 0x01, 0x0A, 0x0D, 0x20, 0x36, 0x4D, 0x4C, 0x25, 0x44, 0x46, 0x33, 0x3D, 0x47, 0x20, 0x39, 0x34, 0x35, 0x98, + 0xAF, 0x20, 0x1E, 0x4D, 0x5E, 0x60, 0x63, 0x64, 0x69, 0xE4, 0xFE, 0xF4, 0x9F, 0xAF, 0xA1, 0xF8, 0xFE, 0xF0, 0xCC, 0x9E, 0xB4, 0xFC, 0xFE, 0xE3, 0xDF, 0xF6, 0xFC, 0xFC, 0xFC, 0xFB, 0xFD, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFC, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x6E, 0xFE, 0xFE, 0xB1, 0x00, 0xA5, 0x00, 0xC0, 0xB8, 0x10, 0x2D, 0x28, 0x16, 0x0F, 0x14, 0x10, 0x0A, 0x1E, 0x04, 0x01, 0x04, + 0x1A, 0x31, 0x4A, 0x62, 0x3C, 0x41, 0x54, 0x58, 0x4B, 0x53, 0x5D, 0x1D, 0x42, 0x38, 0x2F, 0x9D, 0xAC, 0x1F, 0x1E, 0x55, 0x62, 0x64, 0x66, 0x67, 0x65, 0x7C, 0xF7, 0xFE, 0xC8, 0x80, 0x86, 0xBB, 0xFE, 0xFE, 0xA3, 0x99, 0x9A, 0xD2, 0xFE, 0xFA, 0xD1, 0xEA, 0xF6, 0xF9, 0xFC, 0xFB, 0xFC, 0xFC, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xDA, 0xD9, 0x99, 0x00, + 0xB8, 0x00, 0xAE, 0xC5, 0x1A, 0x2E, 0x24, 0x1E, 0x0A, 0x0E, 0x08, 0x01, 0x17, 0x0C, 0x06, 0x01, 0x16, 0x36, 0x4A, 0x3A, 0x35, 0x64, 0x73, 0x5E, 0x67, 0x6E, 0x6B, 0x22, 0x48, 0x3C, 0x1F, 0xA9, 0xA2, 0x1E, 0x1E, 0x5F, 0x66, 0x68, 0x69, 0x69, 0x69, 0x67, 0xCC, 0xFE, 0xEA, 0x73, 0x89, 0x8A, 0xF5, 0xFE, 0xBE, 0x93, 0x9F, 0xA7, 0xFD, 0xFE, 0xD4, 0xE1, 0xF5, 0xF7, 0xFB, 0xFC, 0xFC, 0xFC, + 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFD, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x95, 0xC8, 0x5D, 0x2D, 0x1D, 0x29, 0x09, 0x03, 0x02, 0x02, 0x01, 0x1F, 0x0C, 0x11, 0x11, 0x15, 0x23, 0x43, 0x67, 0x77, 0x81, 0x7A, 0x85, 0x8B, 0x5F, 0x3A, 0x41, 0x3F, 0x3A, 0xB1, 0x8F, 0x1E, 0x28, 0x69, 0x6A, 0x6C, 0x6C, 0x6B, 0x6D, 0x6C, 0xB1, 0xFE, 0xF2, 0x75, 0x8A, 0x8E, + 0xE5, 0xFE, 0xC2, 0x90, 0xA3, 0xA2, 0xFB, 0xFE, 0xD1, 0xDF, 0xF5, 0xF7, 0xFA, 0xFD, 0xFD, 0xFD, 0xFE, 0xFD, 0xE9, 0xAE, 0xAC, 0xAA, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x6D, 0x64, 0xC3, 0x8E, 0x21, 0x20, 0x2C, 0x16, 0x03, 0x02, 0x02, 0x07, 0x09, 0x20, 0x23, 0x23, 0x34, 0x46, 0x5A, 0x79, 0x85, 0x89, 0x9B, 0xA2, 0x97, 0x22, 0x50, 0x2F, 0x3A, 0x73, 0xB2, + 0x71, 0x1E, 0x4B, 0x6C, 0x6E, 0x6F, 0x6F, 0x6E, 0x70, 0x70, 0xB7, 0xFE, 0xE8, 0x79, 0x8C, 0x92, 0xE9, 0xFE, 0xB7, 0x96, 0xA9, 0xAD, 0xFD, 0xFA, 0xC5, 0xE2, 0xF6, 0xF9, 0xFB, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xD7, 0x00, 0x00, 0x00, 0x00, 0xC7, 0xF6, 0xF6, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xB0, 0x20, 0xB1, 0xB4, 0x23, 0x2A, 0x1E, 0x28, 0x09, 0x02, 0x07, 0x0E, 0x11, 0x12, 0x1D, + 0x31, 0x41, 0x55, 0x66, 0x6D, 0x8B, 0xAB, 0xB2, 0xB8, 0x5C, 0x44, 0x4F, 0x3B, 0x20, 0xA7, 0xB5, 0x38, 0x1E, 0x84, 0x6E, 0x70, 0x71, 0x72, 0x72, 0x73, 0x76, 0xD6, 0xFE, 0xC4, 0x80, 0x92, 0x9D, 0xFB, 0xF9, 0x9A, 0xA1, 0xAF, 0xCA, 0xFE, 0xE3, 0xC2, 0xEB, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xD7, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xFD, 0xFD, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0xDD, 0x29, 0x80, 0xBE, 0x81, 0x1F, 0x28, 0x28, 0x24, 0x08, 0x0D, 0x13, 0x18, 0x1F, 0x28, 0x30, 0x3A, 0x4D, 0x65, 0x81, 0x9B, 0xCB, 0xF5, 0x8B, 0x3D, 0x68, 0x39, 0x46, 0x66, 0xBD, 0x94, 0x1E, 0x4E, 0xA2, 0x7D, 0x73, 0x74, 0x75, 0x76, 0x76, 0x8A, 0xF9, 0xF5, 0x87, 0x8F, 0x9C, 0xCD, 0xFE, 0xD2, 0xA2, 0xB1, 0xB4, 0xEF, 0xFA, 0xBC, 0xCA, 0xF2, 0xFD, 0xFE, 0xFC, 0xFA, 0xFB, 0xFD, + 0xFD, 0xFC, 0xD6, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFD, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x93, 0x29, 0xB0, 0xBA, 0x47, 0x2F, 0x20, 0x2D, 0x20, 0x09, 0x14, 0x23, 0x2D, 0x37, 0x43, 0x4E, 0x5D, 0x6F, 0x86, 0xA1, 0xB0, 0x85, 0x41, 0x7A, 0x48, 0x57, 0x29, 0xAD, 0xB8, 0x48, 0x1E, 0x93, 0xA5, 0x95, 0x7A, 0x78, 0x79, 0x7A, 0x7C, 0xD7, 0xFE, 0xB0, 0x8C, 0xA2, 0xB0, 0xF9, + 0xED, 0xAA, 0xB3, 0xC0, 0xD5, 0xFC, 0xCC, 0xBA, 0xD7, 0xF2, 0xFD, 0xFD, 0xFD, 0xFC, 0xFA, 0xE9, 0xE7, 0xE6, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x69, 0x7A, 0x78, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xCF, 0x3C, 0x65, 0xBC, 0xA8, 0x28, 0x35, 0x1E, 0x29, 0x28, 0x11, 0x12, 0x2A, 0x42, 0x58, 0x64, 0x70, 0x79, 0x79, 0x63, 0x20, 0x5F, 0x82, 0x50, 0x5F, 0x30, 0x96, 0xBE, 0x86, 0x1E, + 0x6E, 0xB1, 0xA9, 0xA2, 0x88, 0x7E, 0x7D, 0x7E, 0x89, 0xD4, 0xC3, 0x90, 0xA2, 0xAE, 0xBD, 0xD9, 0xBE, 0xBB, 0xC4, 0xC8, 0xC9, 0xCA, 0xD0, 0xC8, 0xD1, 0xEE, 0xFD, 0xFD, 0xFD, 0xFE, 0xEA, 0x00, 0x00, 0x00, 0x55, 0x63, 0x6E, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0xAB, 0x1E, 0x85, 0xBA, 0x9E, 0x23, 0x2E, 0x20, 0x24, 0x2E, 0x25, 0x18, 0x11, + 0x19, 0x22, 0x25, 0x16, 0x22, 0x54, 0x78, 0x75, 0x45, 0x62, 0x31, 0x87, 0xC2, 0xA7, 0x24, 0x4A, 0xB2, 0xB4, 0xAE, 0xA7, 0x9F, 0x85, 0x80, 0x82, 0x85, 0x8C, 0x96, 0xA4, 0xAD, 0xB5, 0xBB, 0xC3, 0xC7, 0xC9, 0xCB, 0xCE, 0xD1, 0xD0, 0xDE, 0xCF, 0xD5, 0xEF, 0xFE, 0xFE, 0xFE, 0xFD, 0xE8, 0x00, 0x00, 0x00, 0xF4, 0xFE, 0xFE, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x35, 0xBD, 0x8C, 0x1F, 0x91, 0xB8, 0x9F, 0x36, 0x25, 0x2E, 0x1E, 0x26, 0x34, 0x37, 0x3C, 0x45, 0x55, 0x68, 0x79, 0x6A, 0x43, 0x51, 0x56, 0x28, 0x99, 0xC7, 0xAE, 0x39, 0x42, 0xB5, 0xBD, 0xB7, 0xB2, 0xAC, 0xA6, 0x97, 0x83, 0x85, 0x8A, 0x91, 0x9A, 0xA6, 0xB1, 0xBA, 0xBF, 0xC6, 0xCB, 0xCD, 0xCF, 0xD6, 0xF2, 0xF2, 0xEF, 0xF1, 0xF6, 0xF9, 0xFC, 0xFD, 0xD5, 0x6C, 0x64, 0x00, + 0x00, 0x00, 0xF1, 0xFE, 0xFE, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xBA, 0x83, 0x20, 0x86, 0xB2, 0xAA, 0x67, 0x14, 0x2A, 0x2F, 0x2C, 0x25, 0x29, 0x31, 0x35, 0x37, 0x43, 0x4F, 0x50, 0x36, 0x5E, 0xBC, 0xD0, 0xAE, 0x3A, 0x4A, 0xBC, 0xC9, 0xC1, 0xBA, 0xB4, 0xAD, 0xA4, 0x9B, 0x8D, 0x87, 0x8E, 0x95, 0x9B, 0xA8, 0xB5, 0xBE, 0xC3, 0xC8, + 0xCD, 0xD0, 0xD3, 0xDC, 0xFB, 0xFD, 0xF6, 0xF6, 0xF9, 0xF9, 0xFB, 0xFD, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xFC, 0xFC, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xB0, 0x8C, 0x25, 0x63, 0xA8, 0xB4, 0xA0, 0x6E, 0x25, 0x1C, 0x2C, 0x38, 0x43, 0x49, 0x47, 0x36, 0x18, 0x69, 0xB2, 0xD7, 0xD4, 0x93, 0x24, 0x71, 0xC3, 0xCE, 0xBB, + 0x9B, 0x79, 0x5B, 0x37, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x4C, 0x69, 0x8B, 0xB2, 0xC2, 0xC6, 0xCC, 0xD0, 0xD3, 0xD7, 0xDF, 0xF4, 0xF6, 0xF3, 0xF6, 0xF9, 0xFA, 0xFC, 0xE9, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x3F, 0x3D, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x99, 0x99, 0x48, 0x32, 0x81, 0xAA, 0xB2, 0xB2, 0xA0, 0x8D, + 0x80, 0x79, 0x7F, 0x92, 0xAA, 0xCC, 0xDC, 0xD8, 0xAE, 0x59, 0x3E, 0x8E, 0xA2, 0x7D, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x98, 0xBB, 0xD2, 0xD8, 0xDD, 0xE3, 0xE8, 0xEC, 0xF1, 0xF8, 0xFB, 0xFA, 0xD1, 0x57, 0x00, 0x67, 0xA7, 0xA9, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x9A, 0x76, 0x3B, 0x2A, 0x6B, 0x92, 0xAE, 0xBC, 0xBF, 0xC0, 0xC5, 0xCC, 0xD0, 0xBB, 0x95, 0x54, 0x1E, 0x32, 0x50, 0x22, 0x1E, 0x21, 0x36, 0x48, 0x55, 0x59, 0x56, 0x52, 0x49, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x75, 0x9A, 0xB5, 0xC5, 0xCA, 0xCD, 0xC2, 0xA5, 0x5D, 0x00, 0x00, 0x00, 0x9D, 0xFE, 0xFE, + 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x71, 0x8F, 0x7C, 0x5D, 0x38, 0x1F, 0x34, 0x59, 0x66, 0x67, 0x55, 0x27, 0x1E, 0x1E, 0x25, 0x45, 0x60, 0x6E, 0x77, 0x7D, 0x86, 0x86, 0x85, 0x85, 0x82, 0x7F, 0x7C, 0x77, 0x73, 0x6F, 0x65, 0x58, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xFD, 0xFC, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x61, 0x81, 0x92, 0x8D, 0x88, 0x89, 0x8A, 0x8A, 0x8B, 0x8D, 0x93, 0x9A, 0xA1, 0xA0, 0x9B, 0x94, 0x8E, 0x88, 0x83, 0x78, 0x72, + 0x72, 0x70, 0x6D, 0x69, 0x66, 0x65, 0x63, 0x62, 0x69, 0x71, 0x6F, 0x5D, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x62, 0x7C, + 0x94, 0xA1, 0xA8, 0xA8, 0xA7, 0xA4, 0x9F, 0x92, 0x81, 0x70, 0x5E, 0x4A, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; const lv_image_dsc_t ui_img_logo_80x44_png = { .header.w = 80, diff --git a/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c b/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c index b819d0d..bc3ae45 100644 --- a/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c +++ b/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c @@ -6,286 +6,286 @@ #include "../ui.h" #ifndef LV_ATTRIBUTE_MEM_ALIGN - #define LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN #endif // IMAGE DATA: assets/Text_218x40.png const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_text_218x40_png_data[] = { - 0xE1,0x18,0xE2,0x10,0x02,0x19,0x02,0x11,0xC1,0x00,0xA1,0x00,0xC1,0x08,0x02,0x19,0x22,0x21,0x22,0x19,0x22,0x21,0x22,0x21,0x42,0x21,0x42,0x21,0x02,0x21,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,0xE6,0x08,0xE5,0x10,0xA4,0x00,0x23,0x00,0x23,0x00,0x84,0x00,0xC5,0x10,0x46,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0x10,0x26,0x19,0x46,0x21,0x46,0x21,0x67,0x21,0xA7,0x29,0xA8,0x29,0xE5,0x10,0x92,0x94,0x9A,0xD6,0xFB,0xDE,0xFB,0xDE, - 0xFB,0xDE,0xFB,0xDE,0xDB,0xDE,0x14,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA7,0x31,0x79,0xCE,0x1C,0xE7,0x3C,0xE7,0x5D,0xE7,0x5D,0xEF,0x3D,0xE7,0x39,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xCD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x41,0xDD,0x41,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x62,0xDD,0x61,0xDD,0x02,0xCD,0xA3,0xBC,0xA2,0x93,0xA1,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xBE,0xDB,0xDE,0xDB,0xDE,0xBB,0xD6,0xBB,0xD6,0xDB,0xDE,0xDB,0xDE,0x39,0xC6, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x6B,0x7A,0xCE,0xDB,0xDE,0xDB,0xDE,0xDB,0xDE,0xDB,0xDE,0xFB,0xDE,0xBA,0xD6,0xCC,0x52,0x38,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x73,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xED,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE, - 0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x21,0xFE,0x41,0xFE,0x21,0xF6,0xA1,0xE5,0x61,0xB4,0x21,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xEF,0xF0,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xAD,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xDE,0x93,0x8C,0x1C,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x7C,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5D,0xEF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x21,0xFE,0x21,0xFE,0x21,0xFE,0x41,0xFE,0x81,0xE5,0x21,0xAC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x8C,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBA,0xD6,0x00,0x00,0xFB,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x6B,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x20,0xFE,0x20,0xFE,0xE1,0xF5,0x21,0xBC, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x6B,0x1C,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAF,0x73,0x3D,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xD3,0x9C,0x00,0x00,0xB7,0xAD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x4A,0x5D,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0x7A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x81,0xED,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0x61,0xED,0x61,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0x0C,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0xEC,0x5A,0x00,0x00,0x00,0x00,0xB3,0x94, - 0x39,0xC6,0xD3,0x94,0x76,0xAD,0x7A,0xCE,0xF4,0x9C,0x6A,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x73,0x8C,0x7A,0xCE,0xDB,0xD6,0x7A,0xC6,0x5A,0xC6,0x76,0xAD,0x29,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0x21,0xDD,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x01,0xE5,0x21,0xE5,0xA0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0x61,0xCC,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7B,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x00,0xF8,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x59,0xCE,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xED,0xA0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xA1,0xFD,0xC2,0x82,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0x41,0x81,0xA3,0xE1,0xD4,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x21,0xED,0x62,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x31,0x41,0x6A,0xA2,0xB3,0x82,0xAB,0x61,0x72,0x01,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x41,0xC3,0x7A,0x22,0x93,0x82,0xA3,0x81,0xA3,0x61,0x9B,0x41,0x72,0x81,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x3A,0xFC,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0xC6,0xE4,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x6B,0xDB,0xDE,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x14,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x42,0xCF,0x73,0xF3,0x9C,0xF4,0x9C,0x14,0xA5,0xD3,0x9C,0xB3,0x94,0x6A,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x08,0x88,0x31,0x6E,0x6B,0xB3,0x94,0xF4,0x9C,0xF4,0x9C,0xB3,0x94,0x31,0x84,0x4A,0x4A,0xAC,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x00,0x8B,0x01,0x6B,0x00,0x8B,0x01,0x2B,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x52,0xB3,0x94,0x14,0x9D,0x14,0xA5,0xB3,0x94,0x11,0x7C,0xC8,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xED,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0xC1,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x62,0xE1,0xD4,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x82,0xA3,0x22,0xAC,0xA0,0xD4,0xA0,0xD4,0xA0,0xD4,0xA1,0xCC,0xA1,0xCC,0xA1,0xCC,0x61,0xC4,0x03,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xC4,0x81,0xD4,0x81,0xCC,0x60,0xCC, - 0x60,0xCC,0x80,0xCC,0xA0,0xCC,0x22,0xB4,0x00,0x00,0x03,0xAC,0xA1,0xCC,0xA0,0xCC,0xA1,0xCC,0xA1,0xD4,0x80,0xD4,0xE1,0xB3,0x00,0x00,0x00,0x00,0xC2,0x72,0x01,0xB4,0x01,0xE5,0x61,0xF5,0xA1,0xFD,0x81,0xFD,0x60,0xF5,0xA1,0xD4,0x62,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6A,0xC1,0xA3,0xE1,0xD4,0x41,0xED,0xA1,0xF5,0xC1,0xFD,0xC1,0xFD,0xC1,0xFD,0xC1,0xFD,0xA1,0xF5,0x61,0xED,0xC1,0xD4,0xA1,0xA3,0x21,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xDE,0xEF,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x31,0x84,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x2D,0x63,0x00,0x00,0x00,0x00,0x76,0xAD,0x9A,0xCE,0x9A,0xD6,0x9A,0xD6,0xBA,0xD6,0xBA,0xD6,0x9A,0xD6,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0x6B,0x96,0xB5,0xBA,0xD6,0x7D,0xEF,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0xDB,0xDE,0x59,0xCE,0xB3,0x94,0x0D,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x7C,0x39,0xC6,0x79,0xCE,0x79,0xCE,0x79,0xCE,0x79,0xCE,0x79,0xCE,0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7B,0x55,0xA5,0x9A,0xD6, - 0x3D,0xE7,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBF,0xF7,0x7D,0xEF,0xBA,0xD6,0x18,0xC6,0x52,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0x4A,0xB7,0xB5,0x9A,0xCE,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x7A,0xCE,0x14,0xA5,0x00,0x00,0xF0,0x7B,0x76,0xAD,0xDB,0xDE,0x7E,0xEF,0xDF,0xF7,0xDF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBE,0xF7,0x5D,0xE7,0xBB,0xD6,0x35,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xED,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0xA1,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x7A,0x61,0xF5,0x80,0xFD,0x80,0xFD,0x80,0xFD, - 0x80,0xFD,0x80,0xFD,0x80,0xFD,0x42,0xCC,0xE1,0x8A,0x80,0xFD,0x80,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x60,0xF5,0x42,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xDC,0x80,0xFD,0x80,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x80,0xFD,0x81,0xA3,0x00,0x00,0x62,0xC4,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x00,0xED,0x81,0x08,0xC2,0xAB,0x01,0xE5,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0xC1,0xE4,0x81,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x92,0xE1,0xB3,0x01,0xE5,0x80,0xFD,0x80,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA1,0xFD,0xA1,0xFD,0xA1,0xFD,0xA1,0xFD, - 0xC1,0xFD,0xC1,0xFD,0xA1,0xFD,0x01,0xDD,0x81,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x84,0x7E,0xEF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x71,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xC6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x79,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xBD,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x35,0xA5,0xFC,0xDE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0x9E,0xF7,0xDB,0xDE,0x51,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0xEA,0x31,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDB,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xAD,0x3C,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xEF,0xF8,0xBD,0x30,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x4A,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x92,0x8C,0xBB,0xD6,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xBE,0xF7,0xF8,0xBD,0x00,0x00,0x00,0x00,0x21,0xED,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x60,0xFD,0xA2,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x62,0xA1,0xDC,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x41,0xCC,0xE1,0x9A,0xC1,0xDC,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x21,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x93,0x40,0xF5,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x60,0xFD,0xE1,0xE4,0x41,0x39,0x00,0x00,0x22,0xC4,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x40,0xFD,0xE1,0xEC, - 0xE1,0x8A,0x20,0xF5,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x61,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x49,0x01,0xC4,0x20,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x81,0xFD,0xA1,0xFD,0x61,0xF5,0xE1,0xBB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBA,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xF7,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x29,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x55,0xAD,0x00,0x00,0x00,0x00,0x00,0x00, - 0xD7,0xB5,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x00,0x76,0xAD,0x9E,0xEF,0xDF,0xFF,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,0x5D,0xEF,0x71,0x8C,0x00,0x00,0x00,0x00,0x46,0x21,0x7E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xF8,0xBD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF, - 0xFC,0xDE,0x55,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x4A,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0xD6,0xFC,0xDE,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE,0xF7,0xB6,0xB5,0x00,0x00,0x01,0xED,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0xA2,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x41,0x61,0xD4,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x41,0xD4,0x00,0x00,0xA1,0xB3,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD, - 0x81,0xDC,0x61,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xC4,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x41,0xCC,0x00,0x00,0x00,0x00,0xE1,0xC3,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x01,0xFD,0xA1,0xE4,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0xC1,0xC3,0x00,0x00,0x00,0x00,0x61,0x49,0x01,0xC4,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x61,0xFD,0x61,0xFD,0x41,0xFD,0xC1,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB6,0xB5, - 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDB,0xD6,0x31,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x5B,0x9E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x3D,0xE7,0x2D,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xB5,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xA5,0x7D,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0xDE,0xAB,0x52,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7, - 0xDF,0xFF,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xBD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x9A,0xD6,0x2A,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x52,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0x2D,0x63,0xE0,0xEC,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x20,0xFD,0x81,0x82, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x72,0x61,0xDC,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x20,0xFD,0x01,0xCC,0x00,0x00,0x01,0x62,0xA0,0xEC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0xE0,0xF4,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xDC,0x20,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x22,0x9B,0x00,0x00,0x00,0x00,0xC1,0xBB,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x81,0xB3,0x00,0x00,0x00,0x00, - 0x82,0xAB,0x00,0xF5,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0xE0,0xF4,0x81,0x8A,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x7C,0x7D,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9E,0xEF,0x8E,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7A,0xCE,0xBF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x7A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF7,0xBD,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xD6, - 0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0xBA,0xD6,0xFB,0xDE,0x1C,0xDF,0x9A,0xD6,0xDB,0xDE,0x9E,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0xD3,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0x7E,0xEF,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x7D,0xEF,0x7D,0xEF,0xDF,0xF7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE,0xF7,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0xAB,0x52,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF, - 0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x96,0xAD,0xA0,0xEC,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x00,0xFD,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x59,0xA0,0xEC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0xA1,0xC3,0x00,0x00,0x00,0x00,0x41,0xD4,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0x81,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC2,0x82,0xE0,0xEC,0x00,0xFD,0x00,0xFD, - 0x00,0xFD,0x00,0xFD,0x00,0xFD,0x81,0xE4,0x62,0x82,0x00,0x00,0x00,0x00,0xA1,0xBB,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0xA0,0xFC,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC1,0xF4,0xC1,0xEC,0xA1,0xEC,0xA0,0xF4,0xA0,0xF4,0xA1,0x8A,0x00,0x00,0x00,0x00,0x81,0xE4,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0xE0,0xFC,0x21,0xD4,0x62,0xAB,0x02,0x9B,0xE2,0x92,0xA1,0xBB,0x81,0xDC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x01,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xD6,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0xDF,0xF7,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xDB,0xD6,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xBD,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x08,0x00,0x3C,0xE7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0x14,0xA5,0x2D,0x63,0x00,0x00,0x00,0x00,0x88,0x29,0x8C,0x52,0xAF,0x73,0x7A,0xCE,0x3C,0xE7,0xDF,0xF7,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x21,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xD6,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7, - 0xDF,0xF7,0xDF,0xF7,0x9E,0xF7,0x39,0xC6,0xB3,0x94,0x8A,0x52,0x6A,0x4A,0x72,0x8C,0xF8,0xBD,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFB,0xDE,0xEC,0x5A,0x00,0x00,0x00,0x00,0xAB,0x52,0xDB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xBE,0xF7,0xBB,0xD6,0xD7,0xB5,0xB7,0xB5,0x18,0xBE,0x38,0xC6,0x1C,0xDF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x59,0xC6,0xA1,0xEC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xC3,0xC0,0xFC,0xC0,0xFC, - 0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x01,0xA3,0x00,0x00,0x00,0x00,0x62,0xA3,0xC0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xE0,0xD3,0x81,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xAB,0x00,0xFD,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x21,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xBB,0xA0,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xE1,0xD3,0x63,0xB3,0x83,0x72,0x62,0x39,0x61,0x41,0x81,0x82,0x20,0xA3,0xE1,0x51,0x00,0x00,0xC1,0x9A,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x61,0xB3,0x22,0x31,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x01,0x31,0xA1,0xC3,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0x80,0xF4,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xAD,0xBE,0xEF,0xBE,0xF7,0xBE,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBA,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0x52,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0x7D,0xEF,0x6E,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xBD,0xDF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0xC5,0x08,0x9E,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFB,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x8E,0x6B,0xD7,0xB5,0x0C,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0xBA,0xD6,0x0A,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBE,0xF7,0x96,0xB5,0x49,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xA5,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x92,0x8C,0x00,0x00,0x00,0x00,0xAB,0x52,0xBB,0xD6,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9E,0xEF,0x76,0xAD,0x4E,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x6B,0xDB,0xD6,0xDF,0xF7, - 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9A,0xCE,0x81,0xEC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x49,0x60,0xBB,0x60,0xF4,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xFC,0x60,0xFC,0x20,0xEC,0x01,0x7A,0x00,0x00,0x00,0x00,0xA1,0x51,0x20,0xE4,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xF4,0x20,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xE1,0xCB,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0xE1,0xA2,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xBB,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC, - 0x40,0xFC,0x60,0xFC,0x60,0xFC,0xA0,0xCB,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xC3,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x80,0xFC,0x00,0xE4,0x21,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0x69,0x21,0xE4,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x41,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x84,0x7E,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x5D,0xE7,0xCC,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0xB5,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xD7,0xB5,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x07,0x01,0xBE,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDB,0xD6,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0xBF,0xF7,0xBA,0xD6,0x0A,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0xBE,0xF7,0xBE,0xF7,0xBE,0xEF,0xBE,0xEF,0xBE,0xF7,0xBF,0xF7,0xFC,0xDE,0x8F,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7A,0xCE,0xDF,0xF7, - 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x79,0xCE,0x00,0x00,0x00,0x00,0x8B,0x52,0xBB,0xD6,0xBF,0xF7,0xDF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0x79,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xAD,0xBE,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x3D,0xE7,0x41,0xEC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x62,0xBB,0xC1,0xC3,0xA1,0xC3,0xA0,0xC3,0x81,0xC3,0x80,0xC3,0x80,0xC3,0x61,0xCB,0xE0,0xE3,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x40,0xCB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBB,0x60,0xFC,0x60,0xFC, - 0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x7A,0x20,0xE4,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x80,0xFC,0x00,0xE4,0xC1,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBB,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0xC0,0xE3,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xDB,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xC3,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x61,0xFC,0x81,0xCB,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xCE,0x9E,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0xBF,0xF7,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBE,0xEF,0x9A,0xCE,0x35,0xA5,0x0C,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x21,0x5D,0xE7,0xBE,0xEF, - 0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBA,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xC6,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xB5,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x8B,0x4A,0xBB,0xCE,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xF7,0x7E,0xEF,0xF4,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x4A,0x3C,0xDF,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xEF,0x3D,0xE7,0x01,0xEC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC, - 0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xC0,0xF3,0x01,0x8A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x82,0x20,0xF4,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x60,0xFC,0xA0,0xD3,0x81,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x92,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xFC,0x61,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xBB,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x40,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xC1,0xE3,0x20,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x01,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xB3,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0xA1,0xDB,0x82,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x32,0xFC,0xD6,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x5D,0xDF,0xF0,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xAD,0xBE,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xF8,0xB5,0x00,0x00,0x00,0x00, - 0x00,0x00,0x9A,0xCE,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0x9E,0xEF,0x5D,0xE7,0xBB,0xD6,0x18,0xBE,0xB3,0x94,0x33,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x21,0x5D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBA,0xCE,0x00,0x00,0x00,0x00,0x87,0x21,0xDB,0xD6,0x7E,0xEF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xEF,0x14,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x9D,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x1C,0xDF,0x00,0x00,0x00,0x00,0x6A,0x42,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF, - 0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0x3D,0xE7,0xAB,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xD6,0xBF,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0x1C,0xDF,0xC1,0xEB,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC1,0xB2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x10,0x81,0xD3,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xF4,0xC1,0x79,0x00,0x00,0x00,0x00,0xE2,0x28,0x81,0xCB,0x60,0xFC,0x60,0xFC, - 0x60,0xFC,0x40,0xFC,0x60,0xFC,0x40,0xF4,0x61,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xBA,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0x60,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xEB,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x81,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xA2,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x81,0xDB,0xC2,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x73,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x1C,0xD7,0x0A,0x2A, - 0x00,0x00,0x00,0x00,0x93,0x8C,0x5E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9B,0xCE,0xAB,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xA5,0x9E,0xEF,0x9E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x84,0x7D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBF,0xEF,0xBF,0xEF,0x9E,0xEF,0xDB,0xD6,0x59,0xC6,0x72,0x8C,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDD,0x64,0x5E,0xE7,0x9E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xBB,0xCE,0x00,0x00,0x00,0x00,0x4A,0x21,0x9A,0xCE,0x5D,0xE7,0x5E,0xE7,0x7E,0xE7, - 0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x76,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x42,0x5D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x1C,0xDF,0xC5,0x08,0x00,0x00,0x4A,0x42,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x3D,0xDF,0x4A,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xD6,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x1C,0xDF,0xA1,0xE3,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB, - 0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xF3,0xA1,0xBA,0xE1,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xBA,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x01,0xBB,0x00,0x00,0x00,0x00,0x42,0x51,0xC1,0xDB,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0xA1,0xDB,0x21,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x41,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x39,0xA1,0xF3,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x21,0x92,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x92,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xA1,0xE3,0xA2,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x5B,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xF4,0x94,0x00,0x00,0x00,0x00,0xF8,0xB5,0x7E,0xE7,0x7E,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xA5,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x42,0xD7,0xB5,0x5D,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xE7, - 0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x5D,0xE7,0x7A,0xCE,0x31,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD6,0x4B,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x6C,0x42,0x7A,0xC6,0x5D,0xDF,0x5D,0xDF,0x5D,0xDF,0x5E,0xDF,0x5E,0xDF,0x3D,0xDF,0x39,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x21,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x3D,0xDF,0xA8,0x29,0x00,0x00,0x4A,0x42,0x9A,0xCE,0x9E,0xE7,0x9E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x1D,0xDF,0x6B,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xDB,0xD6,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0xFC,0xD6,0x81,0xEB,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x01,0xE3,0x61,0xB2,0x01,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x69,0xC0,0xEB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x41,0xD3,0x00,0x00,0x00,0x00,0x02,0x82,0x00,0xF4,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x01,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0x80,0xFB,0x80,0xFB, - 0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x00,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x80,0xEB,0xA0,0xFB,0xA0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xE1,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x92,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x81,0xE3,0xA2,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xB6,0x3E,0xDF,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x5E,0xDF,0xB7,0xAD,0x00,0x00,0x29,0x3A,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x3D,0xDF,0x72,0x84,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0xA5,0x7E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7E,0xDF,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x42,0x15,0x9D,0xDB,0xCE,0x5E,0xE7,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xFC,0xD6,0xF4,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x19,0xFC,0xD6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7A,0xC6,0x00,0x00,0x00,0x00,0x4D,0x42,0x7A,0xC6,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xD7,0x18,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x46,0x21,0x1D,0xD7,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x1D,0xD7,0x09,0x32,0x00,0x00,0x8B,0x4A,0x7A,0xC6,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x1D,0xD7,0x6B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xCE,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xFC,0xD6,0x61,0xEB,0xA0,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0xE0,0xF2,0xA0,0xDA,0xA1,0xD2,0x22,0xAA,0xA2,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x21,0xD3,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0x80,0xEB,0x01,0x51,0x00,0x00,0xE2,0xBA,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xF3,0x21,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0xE0,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xEB,0x80,0xFB,0x80,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xC1,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x92,0x80,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB, - 0x21,0xDB,0x42,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x74,0x1D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x39,0xB6,0x46,0x19,0xD0,0x6B,0xFD,0xCE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0x5E,0xD7,0x9B,0xC6,0xEB,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xA5,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xD8,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x63,0x76,0xA5,0x7A,0xC6,0x1D,0xD7,0x3D,0xD7,0x3D,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xDC,0xCE,0x6E,0x63,0x00,0x00,0x00,0x00,0x26,0x19, - 0xDC,0xCE,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x5D,0xDF,0x5E,0xDF,0x5A,0xBE,0x00,0x00,0x00,0x00,0xCB,0x31,0x39,0xBE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x1D,0xD7,0x19,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x29,0x1D,0xD7,0x5E,0xDF,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x5E,0xDF,0xFC,0xCE,0x87,0x21,0x00,0x00,0x8B,0x4A,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x1C,0xD7,0x6B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xDB,0xCE,0x41,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB, - 0x60,0xFB,0x60,0xFB,0x40,0xFB,0xA2,0x89,0x82,0x79,0xA2,0x89,0xC1,0x99,0xC1,0x99,0xA1,0x91,0xA1,0x91,0xA2,0x91,0x42,0x69,0x03,0x59,0xE2,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAA,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x41,0xB2,0x00,0x00,0x21,0xD3,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0xA0,0xFB,0x40,0xE3,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xBA,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0xC0,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0xC1,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xA2,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0xE1,0xDA,0xA2,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA9,0x29,0x7B,0xBE,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xBC,0xC6,0xD0,0x6B,0x56,0x9D,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xD7,0x3D,0xD7,0xB7,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x9D,0x5E,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0xD8,0xAD, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0x4A,0xAF,0x63,0xB7,0xA5,0x7A,0xBE,0xBB,0xCE,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xDF,0x56,0xA5,0x00,0x00,0x00,0x00,0x26,0x19,0xBC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x3D,0xD7,0x39,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xCF,0x1D,0xCF,0x1D,0xD7,0x1D,0xD7,0x15,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x8C,0x1D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0xBB,0xC6,0x00,0x00,0x00,0x00,0x6B,0x4A,0x5A,0xBE, - 0x5E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x1C,0xD7,0x8C,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9B,0xC6,0x3E,0xD7,0x3E,0xD7,0x3D,0xD7,0x3D,0xDF,0x5D,0xDF,0xBB,0xCE,0x21,0xEB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x82,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x71,0x20,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0xA0,0xCA,0x63,0x51,0x40,0xF3,0x60,0xFB, - 0x40,0xFB,0x40,0xFB,0x40,0xFB,0x60,0xFB,0xA1,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xBA,0x20,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0x80,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xD2,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x81,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAA,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0xA1,0xDA,0x82,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xA5,0xFD,0xCE,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6, - 0xFD,0xC6,0xFD,0xC6,0x15,0x95,0xF9,0xAD,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xDC,0xC6,0x11,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x9D,0x3E,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x3D,0xD7,0x3E,0xD7,0xB8,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x7C,0xB4,0x8C,0x19,0xB6,0xFC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x39,0xB6,0x09,0x3A,0x00,0x00,0x05,0x19,0x9C,0xC6,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0x19,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xB6,0xFD,0xCE, - 0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0xB7,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF4,0x94,0x1D,0xD7,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xF9,0xAD,0x00,0x00,0x00,0x00,0x2A,0x3A,0x3A,0xBE,0x3E,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0xFC,0xCE,0xED,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0xBE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0xBB,0xC6,0x01,0xE3,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xFA,0x62,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xD2,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0xC0,0xE2,0x41,0x9A,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xF3,0x81,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBA,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xA0,0xFA,0x40,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xCA,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x80,0xDA,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x28,0x81,0xCA,0x00,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x42,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x74,0xBC,0xBE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xB8,0x9D,0x1A,0xAE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDC,0xC6,0x19,0xAE,0xC8,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x95,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x97,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x8C,0xDC,0xC6,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0x3A,0xB6,0xF1,0x73,0x00,0x00,0x26,0x19,0x7B,0xBE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0xF9,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x57,0x9D,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xF9,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xA5,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xB8,0xA5,0x00,0x00,0x00,0x00,0x09,0x3A,0x19,0xB6,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xFC,0xCE,0xED,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x5B,0xBE,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xBB,0xC6,0xC1,0xEA,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xA1,0xC0,0xF2,0xE0,0xFA,0x00,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xF2,0x61,0xBA,0x00,0xFB,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0x60,0xDA,0x81,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xBA, - 0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x00,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB9,0xA0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x80,0xF2,0x61,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x81,0xC0,0xF2,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA2,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x19,0x1A,0xAE,0xBD,0xBE,0xBD,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x7B,0xB6,0x9C,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x15,0x95,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x8C,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0x97,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x84,0xF5,0x84,0xC8,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x01,0x5B,0xB6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0x3A,0xB6,0x11,0x74,0x00,0x00,0x26,0x19,0x7B,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xB8,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0xF1,0x6B,0xBC,0xBE,0xBD,0xC6,0xDC,0xC6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x9C,0xBE,0x12,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x6F,0x5B,0x5A,0xB6,0xDC,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0x32,0x74,0x00,0x00,0x00,0x00,0xE9,0x31,0x19,0xAE,0xFD,0xCE,0xFD,0xC6,0xFD,0xC6,0xFD,0xCE,0x1D,0xCF,0xDC,0xC6,0x8C,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3A,0xB6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0x9B,0xBE,0x81,0xEA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0xA0,0xFA,0x80,0xFA,0x21,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x49,0x41,0xDA,0xC0,0xFA,0xC0,0xFA,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xC0,0xF2,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x00,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xB9,0x60,0xFA,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0xC0,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x58,0x40,0xEA,0x80,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x20,0xDA,0x61,0x99,0xE1,0x58,0x00,0x00,0x00,0x00,0xC2,0x48,0x81,0x89,0x60,0xDA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA, - 0x60,0xFA,0x00,0xDA,0x01,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x9D,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x7B,0xB6,0xF1,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x84,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xC6,0xDD,0xBE,0x77,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0xD1,0x63,0x1A,0xAE,0x9C,0xB6,0x98,0x9D,0x93,0x7C,0x0E,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x00,0x73,0x7C,0x9C,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xDD,0xBE,0x97,0x9D,0x09,0x32, - 0x00,0x00,0x05,0x19,0x3B,0xAE,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0xB8,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x3A,0xF9,0xA5,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x1A,0xAE,0x73,0x7C,0x6B,0x3A,0x00,0x00,0x00,0x00,0xE9,0x31,0xF1,0x6B,0xD8,0xA5,0x9C,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBD,0xBE,0x3A,0xAE,0x09,0x32,0x00,0x00,0x00,0x00,0x09,0x32,0xF9,0xAD,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0xFD,0xC6,0xBC,0xBE,0x4B,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x1A,0xAE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xC6,0xDD,0xBE,0x5B,0xB6,0x41,0xEA,0x60,0xFA, - 0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB1,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x41,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB9,0x20,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xA0,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xB9,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x40,0xF2,0x20,0xDA,0x41,0xDA,0x41,0xD2,0x41,0xE2,0x80,0xF2,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x20,0xFA,0x80,0xB9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0x84,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0xD9,0xA5,0xC8,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x84,0xBC,0xBE,0x9C,0xB6,0x9C,0xB6,0xBC,0xBE,0xBC,0xBE, - 0xBD,0xBE,0x56,0x95,0x00,0x00,0x00,0x00,0xD3,0x4B,0x98,0x9D,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7B,0xB6,0xD9,0xA5,0x77,0x95,0x57,0x95,0x52,0x74,0x52,0x74,0xF5,0x8C,0xB8,0xA5,0x5B,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x36,0x95,0x00,0x00,0x00,0x00,0x05,0x11,0x3A,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x98,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x84,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xB6,0xF9,0xA5,0xB8,0xA5,0xB8,0xA5,0xD9,0xA5,0x7B,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xBE,0x9C,0xB6,0x16,0x8D,0x00,0x00,0x00,0x00,0x00,0x00, - 0xE9,0x31,0xD9,0xA5,0xBD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0x9B,0xB6,0x2A,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xF9,0xA5,0xBC,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0x1A,0xAE,0x21,0xE2,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x79,0x40,0xEA,0x60,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA, - 0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x20,0xE2,0xC1,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xB9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0x80,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x69,0x01,0xE2,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0xC0,0xD9,0xA1,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x11,0xFA,0x9D, - 0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x37,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0x7C,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x36,0x8D,0x00,0x00,0x00,0x00,0x15,0x8D,0x7B,0xB6,0x7B,0xB6,0x7B,0xB6,0x7B,0xAE,0x5B,0xAE,0x7B,0xAE,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xBE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x1A,0xA6,0x90,0x63,0x00,0x00,0x00,0x00,0x26,0x11,0x1A,0xA6,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x78,0x95,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x68,0x09,0x98,0x9D,0x7C,0xAE,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0xD9,0x9D,0x8B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x29,0xB9,0x9D,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0xBC,0xB6,0xBC,0xBE,0x5B,0xAE,0x2A,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xF9,0xA5,0x9C,0xB6,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0xD9,0x9D,0xE1,0xE1,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x00,0xFA,0xE1,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,0x22,0x00,0xC1,0xD1,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0xC0,0xD1,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xB1,0xA0,0xF9,0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0xA0,0xF9,0x60,0xD1,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,0x91,0xE1,0xE1,0x00,0xFA,0x20,0xFA,0x20,0xFA, - 0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xA0,0xE1,0xE1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x8D,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x32,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x7C,0x7C,0xAE,0x5B,0xAE,0x5C,0xAE,0x5C,0xAE,0x7C,0xAE,0x7C,0xAE,0xF5,0x84,0x00,0x00,0x00,0x00,0x57,0x95,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE, - 0x5B,0xAE,0x7B,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x1A,0xA6,0x94,0x7C,0x84,0x00,0x00,0x00,0x00,0x00,0x4D,0x22,0xFA,0xA5,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x77,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x4B,0x98,0x95,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x98,0x95,0xB1,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x29,0x98,0x9D,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x3B,0xAE,0x2A,0x2A,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xD9,0x9D,0x7C,0xAE,0x7C,0xAE,0x5C,0xAE,0x5B,0xAE,0x5B,0xAE,0xB9,0x9D,0xA0,0xE1,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xE2,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xA1,0x00,0xFA,0x00,0xFA,0x20,0xFA,0x20,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x21,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x41,0xB9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xD1,0x00,0x00,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,0x81,0xC1,0xD9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA1,0xD9,0xE1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x6C,0xFA,0x9D,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0xFA,0x9D,0xFA,0x9D,0xB9,0x95,0x4B,0x32,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x7C,0x5B,0xAE,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x5B,0xA6,0x5B,0xAE,0xD5,0x84,0x00,0x00,0x00,0x00,0x6B,0x32,0xB5,0x7C,0xB9,0x9D,0x3B,0xA6,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x3B,0xAE,0x3B,0xA6,0x3B,0xA6,0xD9,0x9D,0x74,0x74,0x4B,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0x44,0xFA,0x9D,0x1B,0xA6,0x1B,0xA6,0x1B,0xA6,0x1B,0x9E,0x1B,0xA6,0x57,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xED,0x4A,0x37,0x8D,0x1B,0xA6,0x3B,0xA6,0x3B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE, - 0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x3B,0xAE,0x3B,0xA6,0x1B,0xA6,0x37,0x8D,0xD1,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE9,0x29,0x98,0x95,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x1A,0xA6,0xEA,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xB9,0x95,0x5B,0xA6,0x5B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0xB9,0x9D,0x60,0xE1,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0xC2,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x38,0x81,0xC9,0xE0,0xF9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xC0,0xF9,0xA0,0xE1,0xE2,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xB1,0x60,0xF1,0x40,0xF1,0x40,0xF1,0x20,0xF1,0x20,0xF9,0x40,0xF9,0x00,0xE1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x50,0x61,0xB9,0x81,0xD1,0xA0,0xF1,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA0,0xF1,0x61,0xD9,0x41,0xB1, - 0xA2,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x32,0x58,0x85,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xBA,0x95,0xB9,0x95,0xD5,0x7C,0xE9,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x74,0x3B,0xA6,0x1B,0x9E,0xFB,0x9D,0xFB,0x9D,0x1B,0x9E,0x1B,0xA6,0xD5,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x4B,0xD5,0x7C,0x98,0x95,0x1B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x1B,0xA6,0xB9,0x95,0xF6,0x84,0xB0,0x5B,0x06,0x09,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0x3C,0xD9,0x95,0xDA,0x9D,0xFA,0x9D,0xDA,0x9D,0xDA,0x9D,0xFA,0x9D,0x37,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0x42,0x12,0x6C,0x57,0x8D,0xFA,0xA5,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xAE,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x1B,0xA6,0xFA,0x9D,0x57,0x8D,0x53,0x74,0xCD,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE9,0x29,0x78,0x95,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0xF9,0x9D,0xA8,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x98,0x95,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0xA6,0x1B,0xA6,0xB8,0x95, - 0xE1,0xB0,0x21,0xC1,0x41,0xB9,0x41,0xC1,0x41,0xC9,0x41,0xD9,0x20,0xD9,0xC7,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x99,0xC0,0xF9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA0,0xF9,0x40,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x80,0x01,0xB9,0x21,0xC1,0x21,0xC1,0x01,0xC1,0x01,0xC1,0x01,0xD1,0xE2,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,0x62,0x30,0xE1,0x88,0x41,0xC1,0x60,0xC9,0x80,0xD9,0x80,0xE1,0x80,0xE1,0x80,0xD9,0x61,0xC9,0x41,0xC1,0xE1,0x90,0xC6,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x11,0xD1,0x5B,0x75,0x6C,0x33,0x6C,0x13,0x64,0x12,0x64,0x13,0x64,0x33,0x6C,0xF2,0x63,0xD1,0x63,0x6F,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x5B,0xD5,0x7C,0x94,0x74,0x94,0x74, - 0x94,0x74,0x94,0x7C,0x94,0x7C,0x6F,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x21,0x12,0x6C,0x16,0x85,0x16,0x8D,0x77,0x95,0x98,0x95,0x98,0x95,0x78,0x95,0x16,0x8D,0x37,0x8D,0x53,0x74,0xC9,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x6C,0x53,0x6C,0x33,0x6C,0x32,0x6C,0x12,0x6C,0x12,0x6C,0x90,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x5B,0xB5,0x7C,0xD9,0x9D,0x57,0x95,0x98,0x9D,0x98,0x9D,0x57,0x95,0x98,0x95,0xB4,0x7C,0x0E,0x4B,0x06,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x67,0x21,0x11,0x6C,0xB5,0x7C,0xB5,0x7C,0xF6,0x84,0x16,0x85,0x16,0x8D,0x94,0x7C,0x26,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0xF2,0x63,0x74,0x74,0x94,0x7C,0xB5,0x7C,0xB5,0x84,0xD5,0x84,0x94,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x81,0xA0,0xE1,0xC0,0xF9,0xA0,0xF9, - 0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF1,0xC1,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,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xA8,0xE0,0xC0,0xE0,0xB8,0xE1,0xB0,0x21,0xB1,0x61,0xC9,0xA0,0xE9,0xA0,0xF9,0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x01,0xC1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC1,0x40,0xF9,0x40,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xD9,0xA1,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD1,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xF9,0xE0,0xE0,0xC1,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0xE0,0xD8,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xF9,0x20,0xF9,0x00,0xF9,0x00,0xD1,0xA1,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x50,0xC0,0xD8,0x00,0xF9,0x20,0xF9,0x00,0xF9,0x00,0xF9,0x00,0xF9,0x20,0xF9,0x20,0xF1, - 0x00,0xF1,0xE0,0xD8,0xE1,0xB8,0xA2,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x60,0xA1,0xB0,0xC0,0xD0,0xC1,0xD0,0xC1,0xD0,0xC1,0xD0,0xC1,0xC8,0xE3,0xD0,0xE1,0xB8,0xA2,0x90,0x82,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xE1, 0x18, 0xE2, 0x10, 0x02, 0x19, 0x02, 0x11, 0xC1, 0x00, 0xA1, 0x00, 0xC1, 0x08, 0x02, 0x19, 0x22, 0x21, 0x22, 0x19, 0x22, 0x21, 0x22, 0x21, 0x42, 0x21, 0x42, 0x21, 0x02, 0x21, 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, 0xE6, 0x08, 0xE5, 0x10, 0xA4, 0x00, 0x23, 0x00, 0x23, 0x00, 0x84, 0x00, 0xC5, 0x10, 0x46, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x10, 0x26, 0x19, 0x46, 0x21, 0x46, 0x21, 0x67, 0x21, 0xA7, 0x29, 0xA8, 0x29, 0xE5, 0x10, 0x92, 0x94, 0x9A, 0xD6, 0xFB, 0xDE, 0xFB, 0xDE, + 0xFB, 0xDE, 0xFB, 0xDE, 0xDB, 0xDE, 0x14, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0x31, 0x79, 0xCE, 0x1C, 0xE7, 0x3C, 0xE7, 0x5D, 0xE7, 0x5D, 0xEF, 0x3D, 0xE7, 0x39, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xCD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x41, 0xDD, 0x41, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x62, 0xDD, 0x61, 0xDD, 0x02, 0xCD, 0xA3, 0xBC, 0xA2, 0x93, 0xA1, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xBE, 0xDB, 0xDE, 0xDB, 0xDE, 0xBB, 0xD6, 0xBB, 0xD6, 0xDB, 0xDE, 0xDB, 0xDE, 0x39, 0xC6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6B, 0x7A, 0xCE, 0xDB, 0xDE, 0xDB, 0xDE, 0xDB, 0xDE, 0xDB, 0xDE, 0xFB, 0xDE, 0xBA, 0xD6, 0xCC, 0x52, 0x38, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x73, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xED, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, + 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x21, 0xFE, 0x41, 0xFE, 0x21, 0xF6, 0xA1, 0xE5, 0x61, 0xB4, 0x21, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xEF, 0xF0, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xAD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDE, 0x93, 0x8C, 0x1C, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x7C, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x21, 0xFE, 0x21, 0xFE, 0x21, 0xFE, 0x41, 0xFE, 0x81, 0xE5, 0x21, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8C, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xD6, 0x00, 0x00, 0xFB, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x6B, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0xE1, 0xF5, 0x21, 0xBC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0x1C, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAF, 0x73, 0x3D, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xD3, 0x9C, 0x00, 0x00, 0xB7, 0xAD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x4A, 0x5D, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0x7A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0x61, 0xED, 0x61, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0x0C, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0xEC, 0x5A, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, + 0x39, 0xC6, 0xD3, 0x94, 0x76, 0xAD, 0x7A, 0xCE, 0xF4, 0x9C, 0x6A, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x8C, 0x7A, 0xCE, 0xDB, 0xD6, 0x7A, 0xC6, 0x5A, 0xC6, 0x76, 0xAD, 0x29, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0x21, 0xDD, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x01, 0xE5, 0x21, 0xE5, 0xA0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0x61, 0xCC, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7B, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x92, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0xF8, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0xCE, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xED, 0xA0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xA1, 0xFD, 0xC2, 0x82, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x41, 0x81, 0xA3, 0xE1, 0xD4, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x21, 0xED, 0x62, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x31, 0x41, 0x6A, 0xA2, 0xB3, 0x82, 0xAB, 0x61, 0x72, 0x01, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0xC3, 0x7A, 0x22, 0x93, 0x82, 0xA3, 0x81, 0xA3, 0x61, 0x9B, 0x41, 0x72, 0x81, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x3A, 0xFC, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0xE4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x6B, 0xDB, 0xDE, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x14, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x42, 0xCF, 0x73, 0xF3, 0x9C, 0xF4, 0x9C, 0x14, 0xA5, 0xD3, 0x9C, 0xB3, 0x94, 0x6A, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x08, 0x88, 0x31, 0x6E, 0x6B, 0xB3, 0x94, 0xF4, 0x9C, 0xF4, 0x9C, 0xB3, 0x94, 0x31, 0x84, 0x4A, 0x4A, 0xAC, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x8B, 0x01, 0x6B, 0x00, 0x8B, 0x01, 0x2B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xB3, 0x94, 0x14, 0x9D, 0x14, 0xA5, 0xB3, 0x94, 0x11, 0x7C, 0xC8, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xED, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0xC1, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x62, 0xE1, 0xD4, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x82, 0xA3, 0x22, 0xAC, 0xA0, 0xD4, 0xA0, 0xD4, 0xA0, 0xD4, 0xA1, 0xCC, 0xA1, 0xCC, 0xA1, 0xCC, 0x61, 0xC4, 0x03, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xC4, 0x81, 0xD4, 0x81, 0xCC, 0x60, 0xCC, + 0x60, 0xCC, 0x80, 0xCC, 0xA0, 0xCC, 0x22, 0xB4, 0x00, 0x00, 0x03, 0xAC, 0xA1, 0xCC, 0xA0, 0xCC, 0xA1, 0xCC, 0xA1, 0xD4, 0x80, 0xD4, 0xE1, 0xB3, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x72, 0x01, 0xB4, 0x01, 0xE5, 0x61, 0xF5, 0xA1, 0xFD, 0x81, 0xFD, 0x60, 0xF5, 0xA1, 0xD4, 0x62, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6A, 0xC1, 0xA3, 0xE1, 0xD4, 0x41, 0xED, 0xA1, 0xF5, 0xC1, 0xFD, 0xC1, 0xFD, 0xC1, 0xFD, 0xC1, 0xFD, 0xA1, 0xF5, 0x61, 0xED, 0xC1, 0xD4, 0xA1, 0xA3, 0x21, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDE, 0xEF, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x31, 0x84, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0x9A, 0xCE, 0x9A, 0xD6, 0x9A, 0xD6, 0xBA, 0xD6, 0xBA, 0xD6, 0x9A, 0xD6, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x6B, 0x96, 0xB5, 0xBA, 0xD6, 0x7D, 0xEF, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0xDB, 0xDE, 0x59, 0xCE, 0xB3, 0x94, 0x0D, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7C, 0x39, 0xC6, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7B, 0x55, 0xA5, 0x9A, 0xD6, + 0x3D, 0xE7, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x7D, 0xEF, 0xBA, 0xD6, 0x18, 0xC6, 0x52, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x4A, 0xB7, 0xB5, 0x9A, 0xCE, 0x9A, 0xD6, 0x9A, 0xD6, 0x9A, 0xD6, 0x7A, 0xCE, 0x14, 0xA5, 0x00, 0x00, 0xF0, 0x7B, 0x76, 0xAD, 0xDB, 0xDE, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x5D, 0xE7, 0xBB, 0xD6, 0x35, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xED, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0xA1, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x7A, 0x61, 0xF5, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, + 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x42, 0xCC, 0xE1, 0x8A, 0x80, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x60, 0xF5, 0x42, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xDC, 0x80, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x81, 0xA3, 0x00, 0x00, 0x62, 0xC4, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x00, 0xED, 0x81, 0x08, 0xC2, 0xAB, 0x01, 0xE5, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0xC1, 0xE4, 0x81, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x92, 0xE1, 0xB3, 0x01, 0xE5, 0x80, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, + 0xC1, 0xFD, 0xC1, 0xFD, 0xA1, 0xFD, 0x01, 0xDD, 0x81, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x84, 0x7E, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x71, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xC6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xBD, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x35, 0xA5, 0xFC, 0xDE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x9E, 0xF7, 0xDB, 0xDE, 0x51, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x31, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0x3C, 0xE7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xEF, 0xF8, 0xBD, 0x30, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x4A, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x92, 0x8C, 0xBB, 0xD6, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBE, 0xF7, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x21, 0xED, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0xA2, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x62, 0xA1, 0xDC, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x41, 0xCC, 0xE1, 0x9A, 0xC1, 0xDC, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x21, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x93, 0x40, 0xF5, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0xE1, 0xE4, 0x41, 0x39, 0x00, 0x00, 0x22, 0xC4, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0xE1, 0xEC, + 0xE1, 0x8A, 0x20, 0xF5, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x61, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x49, 0x01, 0xC4, 0x20, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x81, 0xFD, 0xA1, 0xFD, 0x61, 0xF5, 0xE1, 0xBB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBA, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xF7, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x29, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x55, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xD7, 0xB5, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x76, 0xAD, 0x9E, 0xEF, 0xDF, 0xFF, 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, 0x5D, 0xEF, 0x71, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x46, 0x21, 0x7E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF8, 0xBD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, + 0xFC, 0xDE, 0x55, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x4A, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0xD6, 0xFC, 0xDE, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xF7, 0xB6, 0xB5, 0x00, 0x00, 0x01, 0xED, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0xA2, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x41, 0x61, 0xD4, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x41, 0xD4, 0x00, 0x00, 0xA1, 0xB3, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, + 0x81, 0xDC, 0x61, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xC4, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x41, 0xCC, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xC3, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x01, 0xFD, 0xA1, 0xE4, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0xC1, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x61, 0x49, 0x01, 0xC4, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x61, 0xFD, 0x61, 0xFD, 0x41, 0xFD, 0xC1, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB6, 0xB5, + 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDB, 0xD6, 0x31, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x5B, 0x9E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x3D, 0xE7, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xB5, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xA5, 0x7D, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0xDE, 0xAB, 0x52, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, + 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xBD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x9A, 0xD6, 0x2A, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0x2D, 0x63, 0xE0, 0xEC, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x20, 0xFD, 0x81, 0x82, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x72, 0x61, 0xDC, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0x01, 0xCC, 0x00, 0x00, 0x01, 0x62, 0xA0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0xE0, 0xF4, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xDC, 0x20, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x22, 0x9B, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBB, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x81, 0xB3, 0x00, 0x00, 0x00, 0x00, + 0x82, 0xAB, 0x00, 0xF5, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0xE0, 0xF4, 0x81, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x7C, 0x7D, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xEF, 0x8E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xCE, 0xBF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x7A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xBD, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xD6, + 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0xBA, 0xD6, 0xFB, 0xDE, 0x1C, 0xDF, 0x9A, 0xD6, 0xDB, 0xDE, 0x9E, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0xD3, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0x7E, 0xEF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x7D, 0xEF, 0x7D, 0xEF, 0xDF, 0xF7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xF7, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, + 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x96, 0xAD, 0xA0, 0xEC, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x59, 0xA0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0xA1, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x41, 0xD4, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0x81, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x82, 0xE0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, + 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x81, 0xE4, 0x62, 0x82, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xBB, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC1, 0xF4, 0xC1, 0xEC, 0xA1, 0xEC, 0xA0, 0xF4, 0xA0, 0xF4, 0xA1, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x81, 0xE4, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0xE0, 0xFC, 0x21, 0xD4, 0x62, 0xAB, 0x02, 0x9B, 0xE2, 0x92, 0xA1, 0xBB, 0x81, 0xDC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x01, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xD6, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xBD, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x3C, 0xE7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0x14, 0xA5, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x88, 0x29, 0x8C, 0x52, 0xAF, 0x73, 0x7A, 0xCE, 0x3C, 0xE7, 0xDF, 0xF7, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x21, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, + 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xF7, 0x39, 0xC6, 0xB3, 0x94, 0x8A, 0x52, 0x6A, 0x4A, 0x72, 0x8C, 0xF8, 0xBD, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFB, 0xDE, 0xEC, 0x5A, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xDB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xBE, 0xF7, 0xBB, 0xD6, 0xD7, 0xB5, 0xB7, 0xB5, 0x18, 0xBE, 0x38, 0xC6, 0x1C, 0xDF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x59, 0xC6, 0xA1, 0xEC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC3, 0xC0, 0xFC, 0xC0, 0xFC, + 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x01, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x62, 0xA3, 0xC0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE0, 0xD3, 0x81, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xAB, 0x00, 0xFD, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x21, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xBB, 0xA0, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE1, 0xD3, 0x63, 0xB3, 0x83, 0x72, 0x62, 0x39, 0x61, 0x41, 0x81, 0x82, 0x20, 0xA3, 0xE1, 0x51, 0x00, 0x00, 0xC1, 0x9A, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x61, 0xB3, 0x22, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x31, 0xA1, 0xC3, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0x80, 0xF4, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xAD, 0xBE, 0xEF, 0xBE, 0xF7, 0xBE, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBA, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x52, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0x7D, 0xEF, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xBD, 0xDF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x08, 0x9E, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFB, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0xD7, 0xB5, 0x0C, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0xBA, 0xD6, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xF7, 0x96, 0xB5, 0x49, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA5, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x92, 0x8C, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xBB, 0xD6, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xEF, 0x76, 0xAD, 0x4E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0xDB, 0xD6, 0xDF, 0xF7, + 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9A, 0xCE, 0x81, 0xEC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x49, 0x60, 0xBB, 0x60, 0xF4, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x20, 0xEC, 0x01, 0x7A, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x51, 0x20, 0xE4, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xF4, 0x20, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xE1, 0xCB, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xE1, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xBB, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, + 0x40, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0xA0, 0xCB, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xC3, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x00, 0xE4, 0x21, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x69, 0x21, 0xE4, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x41, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x84, 0x7E, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x5D, 0xE7, 0xCC, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xB5, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xD7, 0xB5, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDB, 0xD6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBF, 0xF7, 0xBA, 0xD6, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xF7, 0xBF, 0xF7, 0xFC, 0xDE, 0x8F, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xCE, 0xDF, 0xF7, + 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xBB, 0xD6, 0xBF, 0xF7, 0xDF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x3D, 0xE7, 0x41, 0xEC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x62, 0xBB, 0xC1, 0xC3, 0xA1, 0xC3, 0xA0, 0xC3, 0x81, 0xC3, 0x80, 0xC3, 0x80, 0xC3, 0x61, 0xCB, 0xE0, 0xE3, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x40, 0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBB, 0x60, 0xFC, 0x60, 0xFC, + 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x7A, 0x20, 0xE4, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x00, 0xE4, 0xC1, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBB, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0xC0, 0xE3, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xDB, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC3, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x61, 0xFC, 0x81, 0xCB, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xCE, 0x9E, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0xBF, 0xF7, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xEF, 0x9A, 0xCE, 0x35, 0xA5, 0x0C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x21, 0x5D, 0xE7, 0xBE, 0xEF, + 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBA, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xC6, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xB5, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x4A, 0xBB, 0xCE, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xF7, 0x7E, 0xEF, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x4A, 0x3C, 0xDF, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xEF, 0x3D, 0xE7, 0x01, 0xEC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, + 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xC0, 0xF3, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x82, 0x20, 0xF4, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0xA0, 0xD3, 0x81, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x92, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xFC, 0x61, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xBB, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x40, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC1, 0xE3, 0x20, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x01, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB3, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0xA1, 0xDB, 0x82, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x32, 0xFC, 0xD6, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x5D, 0xDF, 0xF0, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xAD, 0xBE, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x9A, 0xCE, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x9E, 0xEF, 0x5D, 0xE7, 0xBB, 0xD6, 0x18, 0xBE, 0xB3, 0x94, 0x33, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x21, 0x5D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBA, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x87, 0x21, 0xDB, 0xD6, 0x7E, 0xEF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xEF, 0x14, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x9D, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x1C, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x42, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, + 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0x3D, 0xE7, 0xAB, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xBF, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x1C, 0xDF, 0xC1, 0xEB, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC1, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x10, 0x81, 0xD3, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xF4, 0xC1, 0x79, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x28, 0x81, 0xCB, 0x60, 0xFC, 0x60, 0xFC, + 0x60, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x40, 0xF4, 0x61, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xBA, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0x60, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xEB, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x81, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xA2, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x81, 0xDB, 0xC2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x73, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x1C, 0xD7, 0x0A, 0x2A, + 0x00, 0x00, 0x00, 0x00, 0x93, 0x8C, 0x5E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9B, 0xCE, 0xAB, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xA5, 0x9E, 0xEF, 0x9E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x84, 0x7D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0x9E, 0xEF, 0xDB, 0xD6, 0x59, 0xC6, 0x72, 0x8C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x64, 0x5E, 0xE7, 0x9E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xBB, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x21, 0x9A, 0xCE, 0x5D, 0xE7, 0x5E, 0xE7, 0x7E, 0xE7, + 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x76, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x42, 0x5D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x1C, 0xDF, 0xC5, 0x08, 0x00, 0x00, 0x4A, 0x42, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x3D, 0xDF, 0x4A, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xD6, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x1C, 0xDF, 0xA1, 0xE3, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, + 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xF3, 0xA1, 0xBA, 0xE1, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xBA, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x01, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x42, 0x51, 0xC1, 0xDB, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0xA1, 0xDB, 0x21, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x41, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x39, 0xA1, 0xF3, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x92, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xA1, 0xE3, 0xA2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x5B, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB5, 0x7E, 0xE7, 0x7E, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xA5, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x42, 0xD7, 0xB5, 0x5D, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, + 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x5D, 0xE7, 0x7A, 0xCE, 0x31, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0x4B, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x42, 0x7A, 0xC6, 0x5D, 0xDF, 0x5D, 0xDF, 0x5D, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x3D, 0xDF, 0x39, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x21, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x3D, 0xDF, 0xA8, 0x29, 0x00, 0x00, 0x4A, 0x42, 0x9A, 0xCE, 0x9E, 0xE7, 0x9E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x1D, 0xDF, 0x6B, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xDB, 0xD6, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0xFC, 0xD6, 0x81, 0xEB, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x01, 0xE3, 0x61, 0xB2, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x69, 0xC0, 0xEB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x41, 0xD3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x00, 0xF4, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x01, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0x80, 0xFB, 0x80, 0xFB, + 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x00, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0xEB, 0xA0, 0xFB, 0xA0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xE1, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x92, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x81, 0xE3, 0xA2, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB6, 0x3E, 0xDF, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0xB7, 0xAD, 0x00, 0x00, 0x29, 0x3A, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x3D, 0xDF, 0x72, 0x84, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xA5, 0x7E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7E, 0xDF, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x42, 0x15, 0x9D, 0xDB, 0xCE, 0x5E, 0xE7, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xFC, 0xD6, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x19, 0xFC, 0xD6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7A, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x42, 0x7A, 0xC6, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xD7, 0x18, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x21, 0x1D, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x1D, 0xD7, 0x09, 0x32, 0x00, 0x00, 0x8B, 0x4A, 0x7A, 0xC6, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x1D, 0xD7, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xCE, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xFC, 0xD6, 0x61, 0xEB, 0xA0, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0xE0, 0xF2, 0xA0, 0xDA, 0xA1, 0xD2, 0x22, 0xAA, 0xA2, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x21, 0xD3, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0x80, 0xEB, 0x01, 0x51, 0x00, 0x00, 0xE2, 0xBA, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xF3, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0xE0, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xEB, 0x80, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x92, 0x80, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, + 0x21, 0xDB, 0x42, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x74, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x39, 0xB6, 0x46, 0x19, 0xD0, 0x6B, 0xFD, 0xCE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x5E, 0xD7, 0x9B, 0xC6, 0xEB, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xA5, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xD8, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x63, 0x76, 0xA5, 0x7A, 0xC6, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xDC, 0xCE, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x26, 0x19, + 0xDC, 0xCE, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x5D, 0xDF, 0x5E, 0xDF, 0x5A, 0xBE, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x31, 0x39, 0xBE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x1D, 0xD7, 0x19, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x29, 0x1D, 0xD7, 0x5E, 0xDF, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0xFC, 0xCE, 0x87, 0x21, 0x00, 0x00, 0x8B, 0x4A, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x1C, 0xD7, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xDB, 0xCE, 0x41, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, + 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0xA2, 0x89, 0x82, 0x79, 0xA2, 0x89, 0xC1, 0x99, 0xC1, 0x99, 0xA1, 0x91, 0xA1, 0x91, 0xA2, 0x91, 0x42, 0x69, 0x03, 0x59, 0xE2, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAA, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x41, 0xB2, 0x00, 0x00, 0x21, 0xD3, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0x40, 0xE3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xBA, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xC0, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0xC1, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xA2, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0xE1, 0xDA, 0xA2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x29, 0x7B, 0xBE, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xBC, 0xC6, 0xD0, 0x6B, 0x56, 0x9D, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xD7, 0x3D, 0xD7, 0xB7, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x9D, 0x5E, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0xD8, 0xAD, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x4A, 0xAF, 0x63, 0xB7, 0xA5, 0x7A, 0xBE, 0xBB, 0xCE, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xDF, 0x56, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x26, 0x19, 0xBC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x3D, 0xD7, 0x39, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xD7, 0x1D, 0xD7, 0x15, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x8C, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0xBB, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x4A, 0x5A, 0xBE, + 0x5E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x1C, 0xD7, 0x8C, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xC6, 0x3E, 0xD7, 0x3E, 0xD7, 0x3D, 0xD7, 0x3D, 0xDF, 0x5D, 0xDF, 0xBB, 0xCE, 0x21, 0xEB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x82, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x71, 0x20, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0xA0, 0xCA, 0x63, 0x51, 0x40, 0xF3, 0x60, 0xFB, + 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x60, 0xFB, 0xA1, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xBA, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0x80, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xD2, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAA, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xA1, 0xDA, 0x82, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xA5, 0xFD, 0xCE, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, + 0xFD, 0xC6, 0xFD, 0xC6, 0x15, 0x95, 0xF9, 0xAD, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xDC, 0xC6, 0x11, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x9D, 0x3E, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x7C, 0xB4, 0x8C, 0x19, 0xB6, 0xFC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x39, 0xB6, 0x09, 0x3A, 0x00, 0x00, 0x05, 0x19, 0x9C, 0xC6, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0x19, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB6, 0xFD, 0xCE, + 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0xB7, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x94, 0x1D, 0xD7, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x3A, 0x3A, 0xBE, 0x3E, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0xFC, 0xCE, 0xED, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7B, 0xBE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0xBB, 0xC6, 0x01, 0xE3, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xFA, 0x62, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xD2, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xC0, 0xE2, 0x41, 0x9A, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xF3, 0x81, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0x40, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xCA, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x80, 0xDA, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x28, 0x81, 0xCA, 0x00, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x42, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x74, 0xBC, 0xBE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xB8, 0x9D, 0x1A, 0xAE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDC, 0xC6, 0x19, 0xAE, 0xC8, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x95, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x97, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x8C, 0xDC, 0xC6, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0x3A, 0xB6, 0xF1, 0x73, 0x00, 0x00, 0x26, 0x19, 0x7B, 0xBE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x9D, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xA5, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3A, 0x19, 0xB6, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xFC, 0xCE, 0xED, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xBE, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xBB, 0xC6, 0xC1, 0xEA, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x42, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xA1, 0xC0, 0xF2, 0xE0, 0xFA, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xF2, 0x61, 0xBA, 0x00, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0x60, 0xDA, 0x81, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xBA, + 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB9, 0xA0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x80, 0xF2, 0x61, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0xC0, 0xF2, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA2, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x19, 0x1A, 0xAE, 0xBD, 0xBE, 0xBD, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x7B, 0xB6, 0x9C, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x15, 0x95, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x8C, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0x97, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x84, 0xF5, 0x84, 0xC8, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x5B, 0xB6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0x3A, 0xB6, 0x11, 0x74, 0x00, 0x00, 0x26, 0x19, 0x7B, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0x6B, 0xBC, 0xBE, 0xBD, 0xC6, 0xDC, 0xC6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x9C, 0xBE, 0x12, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6F, 0x5B, 0x5A, 0xB6, 0xDC, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0x32, 0x74, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x31, 0x19, 0xAE, 0xFD, 0xCE, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xCE, 0x1D, 0xCF, 0xDC, 0xC6, 0x8C, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xB6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0x9B, 0xBE, 0x81, 0xEA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x21, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x49, 0x41, 0xDA, 0xC0, 0xFA, 0xC0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xF2, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x00, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xB9, 0x60, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0xC0, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x58, 0x40, 0xEA, 0x80, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x20, 0xDA, 0x61, 0x99, 0xE1, 0x58, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x48, 0x81, 0x89, 0x60, 0xDA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, + 0x60, 0xFA, 0x00, 0xDA, 0x01, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x9D, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x7B, 0xB6, 0xF1, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x84, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xC6, 0xDD, 0xBE, 0x77, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x63, 0x1A, 0xAE, 0x9C, 0xB6, 0x98, 0x9D, 0x93, 0x7C, 0x0E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x73, 0x7C, 0x9C, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xDD, 0xBE, 0x97, 0x9D, 0x09, 0x32, + 0x00, 0x00, 0x05, 0x19, 0x3B, 0xAE, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0xB8, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x3A, 0xF9, 0xA5, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x1A, 0xAE, 0x73, 0x7C, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x31, 0xF1, 0x6B, 0xD8, 0xA5, 0x9C, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBD, 0xBE, 0x3A, 0xAE, 0x09, 0x32, 0x00, 0x00, 0x00, 0x00, 0x09, 0x32, 0xF9, 0xAD, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xBC, 0xBE, 0x4B, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0xAE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xC6, 0xDD, 0xBE, 0x5B, 0xB6, 0x41, 0xEA, 0x60, 0xFA, + 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB1, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x41, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB9, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xA0, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xB9, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x40, 0xF2, 0x20, 0xDA, 0x41, 0xDA, 0x41, 0xD2, 0x41, 0xE2, 0x80, 0xF2, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x20, 0xFA, 0x80, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x84, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0xD9, 0xA5, 0xC8, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x84, 0xBC, 0xBE, 0x9C, 0xB6, 0x9C, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, + 0xBD, 0xBE, 0x56, 0x95, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x4B, 0x98, 0x9D, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7B, 0xB6, 0xD9, 0xA5, 0x77, 0x95, 0x57, 0x95, 0x52, 0x74, 0x52, 0x74, 0xF5, 0x8C, 0xB8, 0xA5, 0x5B, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x36, 0x95, 0x00, 0x00, 0x00, 0x00, 0x05, 0x11, 0x3A, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x98, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x84, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xB6, 0xF9, 0xA5, 0xB8, 0xA5, 0xB8, 0xA5, 0xD9, 0xA5, 0x7B, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xBE, 0x9C, 0xB6, 0x16, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE9, 0x31, 0xD9, 0xA5, 0xBD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0x9B, 0xB6, 0x2A, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF9, 0xA5, 0xBC, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0x1A, 0xAE, 0x21, 0xE2, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x79, 0x40, 0xEA, 0x60, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, + 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x20, 0xE2, 0xC1, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xB9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0x80, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x69, 0x01, 0xE2, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0xC0, 0xD9, 0xA1, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x11, 0xFA, 0x9D, + 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x37, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x7C, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x36, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x15, 0x8D, 0x7B, 0xB6, 0x7B, 0xB6, 0x7B, 0xB6, 0x7B, 0xAE, 0x5B, 0xAE, 0x7B, 0xAE, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xBE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x1A, 0xA6, 0x90, 0x63, 0x00, 0x00, 0x00, 0x00, 0x26, 0x11, 0x1A, 0xA6, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x78, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x68, 0x09, 0x98, 0x9D, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0xD9, 0x9D, 0x8B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x29, 0xB9, 0x9D, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0xBC, 0xB6, 0xBC, 0xBE, 0x5B, 0xAE, 0x2A, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xF9, 0xA5, 0x9C, 0xB6, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0xD9, 0x9D, 0xE1, 0xE1, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x00, 0xFA, 0xE1, 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, 0x22, 0x00, 0xC1, 0xD1, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0xC0, 0xD1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xB1, 0xA0, 0xF9, 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0x60, 0xD1, 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, 0x91, 0xE1, 0xE1, 0x00, 0xFA, 0x20, 0xFA, 0x20, 0xFA, + 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xA0, 0xE1, 0xE1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x8D, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x32, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x7C, 0x7C, 0xAE, 0x5B, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0xF5, 0x84, 0x00, 0x00, 0x00, 0x00, 0x57, 0x95, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, + 0x5B, 0xAE, 0x7B, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x1A, 0xA6, 0x94, 0x7C, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x22, 0xFA, 0xA5, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x77, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x4B, 0x98, 0x95, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x98, 0x95, 0xB1, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x29, 0x98, 0x9D, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x3B, 0xAE, 0x2A, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xD9, 0x9D, 0x7C, 0xAE, 0x7C, 0xAE, 0x5C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0xB9, 0x9D, 0xA0, 0xE1, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xE2, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xA1, 0x00, 0xFA, 0x00, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x21, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x41, 0xB9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xD1, 0x00, 0x00, 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, 0x81, 0xC1, 0xD9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA1, 0xD9, 0xE1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x6C, 0xFA, 0x9D, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0xFA, 0x9D, 0xFA, 0x9D, 0xB9, 0x95, 0x4B, 0x32, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x7C, 0x5B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x5B, 0xA6, 0x5B, 0xAE, 0xD5, 0x84, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x32, 0xB5, 0x7C, 0xB9, 0x9D, 0x3B, 0xA6, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x3B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0xD9, 0x9D, 0x74, 0x74, 0x4B, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x44, 0xFA, 0x9D, 0x1B, 0xA6, 0x1B, 0xA6, 0x1B, 0xA6, 0x1B, 0x9E, 0x1B, 0xA6, 0x57, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0x4A, 0x37, 0x8D, 0x1B, 0xA6, 0x3B, 0xA6, 0x3B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, + 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x3B, 0xAE, 0x3B, 0xA6, 0x1B, 0xA6, 0x37, 0x8D, 0xD1, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x29, 0x98, 0x95, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x1A, 0xA6, 0xEA, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB9, 0x95, 0x5B, 0xA6, 0x5B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0xB9, 0x9D, 0x60, 0xE1, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xC2, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x38, 0x81, 0xC9, 0xE0, 0xF9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xA0, 0xE1, 0xE2, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xB1, 0x60, 0xF1, 0x40, 0xF1, 0x40, 0xF1, 0x20, 0xF1, 0x20, 0xF9, 0x40, 0xF9, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x50, 0x61, 0xB9, 0x81, 0xD1, 0xA0, 0xF1, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF1, 0x61, 0xD9, 0x41, 0xB1, + 0xA2, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x32, 0x58, 0x85, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xBA, 0x95, 0xB9, 0x95, 0xD5, 0x7C, 0xE9, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x74, 0x3B, 0xA6, 0x1B, 0x9E, 0xFB, 0x9D, 0xFB, 0x9D, 0x1B, 0x9E, 0x1B, 0xA6, 0xD5, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x4B, 0xD5, 0x7C, 0x98, 0x95, 0x1B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x1B, 0xA6, 0xB9, 0x95, 0xF6, 0x84, 0xB0, 0x5B, 0x06, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x3C, 0xD9, 0x95, 0xDA, 0x9D, 0xFA, 0x9D, 0xDA, 0x9D, 0xDA, 0x9D, 0xFA, 0x9D, 0x37, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x42, 0x12, 0x6C, 0x57, 0x8D, 0xFA, 0xA5, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x1B, 0xA6, 0xFA, 0x9D, 0x57, 0x8D, 0x53, 0x74, 0xCD, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x29, 0x78, 0x95, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0xF9, 0x9D, 0xA8, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x98, 0x95, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0xA6, 0x1B, 0xA6, 0xB8, 0x95, + 0xE1, 0xB0, 0x21, 0xC1, 0x41, 0xB9, 0x41, 0xC1, 0x41, 0xC9, 0x41, 0xD9, 0x20, 0xD9, 0xC7, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x99, 0xC0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF9, 0x40, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x80, 0x01, 0xB9, 0x21, 0xC1, 0x21, 0xC1, 0x01, 0xC1, 0x01, 0xC1, 0x01, 0xD1, 0xE2, 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, 0x62, 0x30, 0xE1, 0x88, 0x41, 0xC1, 0x60, 0xC9, 0x80, 0xD9, 0x80, 0xE1, 0x80, 0xE1, 0x80, 0xD9, 0x61, 0xC9, 0x41, 0xC1, 0xE1, 0x90, 0xC6, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0xD1, 0x5B, 0x75, 0x6C, 0x33, 0x6C, 0x13, 0x64, 0x12, 0x64, 0x13, 0x64, 0x33, 0x6C, 0xF2, 0x63, 0xD1, 0x63, 0x6F, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x5B, 0xD5, 0x7C, 0x94, 0x74, 0x94, 0x74, + 0x94, 0x74, 0x94, 0x7C, 0x94, 0x7C, 0x6F, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x21, 0x12, 0x6C, 0x16, 0x85, 0x16, 0x8D, 0x77, 0x95, 0x98, 0x95, 0x98, 0x95, 0x78, 0x95, 0x16, 0x8D, 0x37, 0x8D, 0x53, 0x74, 0xC9, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x6C, 0x53, 0x6C, 0x33, 0x6C, 0x32, 0x6C, 0x12, 0x6C, 0x12, 0x6C, 0x90, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x5B, 0xB5, 0x7C, 0xD9, 0x9D, 0x57, 0x95, 0x98, 0x9D, 0x98, 0x9D, 0x57, 0x95, 0x98, 0x95, 0xB4, 0x7C, 0x0E, 0x4B, 0x06, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x67, 0x21, 0x11, 0x6C, 0xB5, 0x7C, 0xB5, 0x7C, 0xF6, 0x84, 0x16, 0x85, 0x16, 0x8D, 0x94, 0x7C, 0x26, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0xF2, 0x63, 0x74, 0x74, 0x94, 0x7C, 0xB5, 0x7C, 0xB5, 0x84, 0xD5, 0x84, 0x94, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x81, 0xA0, 0xE1, 0xC0, 0xF9, 0xA0, 0xF9, + 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF1, 0xC1, 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, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xA8, 0xE0, 0xC0, 0xE0, 0xB8, 0xE1, 0xB0, 0x21, 0xB1, 0x61, 0xC9, 0xA0, 0xE9, 0xA0, 0xF9, 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x01, 0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC1, 0x40, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xD9, 0xA1, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xF9, 0xE0, 0xE0, 0xC1, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0xE0, 0xD8, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x00, 0xF9, 0x00, 0xD1, 0xA1, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x50, 0xC0, 0xD8, 0x00, 0xF9, 0x20, 0xF9, 0x00, 0xF9, 0x00, 0xF9, 0x00, 0xF9, 0x20, 0xF9, 0x20, 0xF1, + 0x00, 0xF1, 0xE0, 0xD8, 0xE1, 0xB8, 0xA2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x60, 0xA1, 0xB0, 0xC0, 0xD0, 0xC1, 0xD0, 0xC1, 0xD0, 0xC1, 0xD0, 0xC1, 0xC8, 0xE3, 0xD0, 0xE1, 0xB8, 0xA2, 0x90, 0x82, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //alpha channel data: - 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x11,0x11,0x11,0x11,0x11,0x11,0x05,0x47,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xDC,0xFF,0xFF,0xFF,0xFF,0xFF,0xB4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0xC2,0x96,0x56,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x40,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xAD,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x02,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB1,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x5A, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x00,0x5D,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x16,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xAE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x21,0x00,0x00,0x3C, - 0x4C,0x93,0x73,0x4B,0x45,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x45,0x4D,0x55,0x4E,0x45,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xE7,0xD3,0xD3,0xD3,0xD3,0xD3,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFE,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00, - 0x00,0x00,0x00,0x00,0x1F,0x5F,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0x3F,0x3F,0x3F,0x3F,0x10,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x33,0x43,0x76,0x8E,0x8E,0x69,0x3F,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x2D,0x52,0x8F,0x97,0x8F,0x86,0x46,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x2C,0x49,0x7F,0x8E,0x8E,0x8C,0x40,0x35,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x0C,0x0C,0x03, - 0x00,0x00,0x00,0x00,0x3C,0x52,0x8F,0x8E,0x84,0x43,0x1A,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x85,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xDA,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xEF,0xEF,0xEF, - 0xEF,0xEF,0xEF,0x6C,0x00,0x78,0xEF,0xEF,0xEF,0xEF,0xEF,0xD8,0x00,0x00,0x1E,0xB7,0xF6,0xFF,0xFF,0xFF,0xFF,0xF5,0x2A,0x00,0x00,0x00,0x00,0x00,0x1C,0x87,0xDE,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xD4,0x79,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x52,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x5B,0xF0,0xEF,0xEF,0xEF,0xEF,0xEF,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x7F,0xE4,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xED,0x9C,0x2F,0x01,0x00,0x00,0x00,0x00,0x01,0xE0,0xEF,0xEF,0xEF,0xEF,0xEF,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x7A,0xDF, - 0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF0,0x8F,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xD0,0xEF,0xF1,0xF2,0xF2,0xF2,0x9C,0x00,0x05,0x7C,0xDA,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xBB,0x34,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xFC,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0x95,0x50,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x05,0x58,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x2A,0x00,0x00,0x00,0x02,0x82,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xE8,0x4D,0x00,0x00,0x00,0x00,0x00,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x01,0x57,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFD,0xAD,0x2E,0x00,0x00,0x00,0x27,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x87,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0x19,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xF7,0x80,0x02,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x01,0xD4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x0E,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x8A,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x15,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xA0,0x07,0x00,0x00,0x00,0x05,0xDA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x71,0x00,0x00,0x00, - 0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x01,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x2B,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x06,0x9B,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x98,0x03,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x00,0x82,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xED,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0x00,0x00,0x02,0xB9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00,0x00,0x00,0x8A, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x22,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x29,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x11,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x99,0x03,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x00,0x2D,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00, - 0x4E,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x55,0x00,0x00,0x00,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x5D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0xAA, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBC,0xB6,0xEB,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x35,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xF6,0x08,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0x00,0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xA2,0x56,0x54,0x98,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x00,0x00,0x00,0x00,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8B,0x00,0x00,0x00,0x00, - 0x00,0x00,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x72,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x0C,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x5C,0x08,0x01,0x00,0x07,0x0D,0x4C,0x8B,0xF6,0xFF,0x92,0x01,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x00,0x00,0x00,0x01,0xA9,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xCE,0x69,0x55,0x55,0x58,0xC2,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDE,0x06,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xA5,0x64,0x55,0xA1,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0x00,0x00,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0x06,0x00,0x00,0x00,0x00,0x00,0x7D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x80,0x43,0x43,0x43,0x45,0x8C,0x14,0x00,0x3B,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB2,0x08,0x00,0x00,0x00, - 0x00,0x14,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x00,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x00,0x00,0x00,0x00,0x00,0x15,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x24,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x38,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x21,0x89,0x0A,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x08,0x00,0x00,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x02,0x00,0x00,0x00,0x00,0x00,0x6B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4B,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9E,0x03,0x00,0x00,0x00,0x00,0x20,0xDD,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x85,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x35,0x00,0x00,0x17,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x46,0x00,0x00,0x00,0x00,0x03,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x51,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xAF,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x00,0x00,0x00,0x36,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x29,0x00,0x00,0x00,0x00,0x5B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00, - 0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x1E,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x07,0x00,0x00,0x6E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xD3,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x90,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x4D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC2,0x90,0x90,0x90,0x90,0x90,0x90,0xC8,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0x03,0x00,0x00,0x00,0xBB,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x00,0x00,0x13,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x0C,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7,0x00, - 0x00,0x00,0x00,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x61,0x00,0x00,0x00,0x00,0xB1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x4D,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x71,0x00,0x00,0x00,0x00,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x02,0x00,0x00,0x00,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x06,0x00,0x00,0x00,0xA2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7,0x00,0x00,0x00,0x14,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x21,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00, - 0x00,0xB7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0xD5,0x9A,0x46,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x02,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x00,0x00,0x03,0xF7,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC4,0x00,0x00,0x00,0x00,0x00,0x0D,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x37,0x00,0x00,0x01,0xB8,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x5C,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x13, - 0x00,0x00,0x5A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0x04,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x5D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFB,0x9F,0x46,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x09,0xE4,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x16,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xBE,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x97,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x86,0x00,0x00,0x12,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x18,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x05,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x47,0x00,0x00,0x97,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x01,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x43,0x00,0x00,0x00,0x00,0x09,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x08,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x6A,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xD8,0x00,0x00,0x53,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA8,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9D,0x00,0x09,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x37,0x00,0x00, - 0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x01,0x84,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x50,0x00,0x00,0x00,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x0C,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFA,0xB1,0x5C,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x2D,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x52,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFC,0x09,0x00,0x00,0x00,0x00,0x49,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x0A,0x41,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x92,0xE1,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x1D,0x00,0x00,0x3E, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x0A,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x28,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xA1,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x54,0x40,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x67,0x00,0xED,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x0F,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x00,0x0B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2E,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x3D,0x78,0xB3,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xB5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x00,0x00,0x03,0xF7, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x2F,0xFB,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x02,0x00,0x00,0x00,0x00,0x00,0xA1,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0x83,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x47,0xB2,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0x01,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xAF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x7A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB9,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDA,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x63,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x02,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x96, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x4F,0x91,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x02,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x56,0x00,0x00,0x00,0x00,0x00, - 0x00,0x38,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6D,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x08,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x4A,0x06,0x00,0x00,0x04,0x67,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFE,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x29,0xF7,0xFF,0xE6,0x4A,0x07,0x00,0x00,0x00,0x00,0x00,0x01,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1,0x02, - 0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x0B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x54,0x05,0x00,0x00,0x06,0x46,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x1D,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE5,0xB6,0xB6,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xAB,0x00,0x00,0x05,0xD5,0xFF,0xFF,0xFF,0xFE,0xEF,0xB0,0x69,0x69,0x67,0x67,0xA8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE0,0xB6,0xB6,0xE3,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8D,0x00,0x00,0x00, - 0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFD,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xF4, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x9E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x32,0x00,0x00,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00, - 0x00,0x06,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD3,0x18,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xF3,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x9B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0x01,0x00,0x00,0x22,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x22,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x2D,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE5,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x32,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x04,0x77,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x83,0x01,0x00,0x00,0x00,0x08,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xC9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD2,0x1E,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xD2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x83,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x96, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x25,0xA8,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xB2,0x2F,0x01,0x00, - 0x00,0x00,0x00,0x04,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x70,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x67,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x46,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,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,0x00,0x00,0xA3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x3F,0x3F,0x3F,0x3F,0x3F,0x40,0x26,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x61,0x9D,0xE0,0xDF,0xDF,0xDF,0xDF,0xDE,0x91,0x54,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3C,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x3F,0x3F,0x3F, - 0x3F,0x3F,0x3F,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x53,0x8F,0xC7,0xDF,0xDF,0xE5,0xE3,0xD7,0x8E,0x62,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x3F,0x3F,0x3F,0x3F,0x3F,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x89,0x93,0xDF,0xDF,0xDF,0xDC,0x8F,0x82,0x3F,0x05,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x01,0x3D,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xFC,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0xBD,0x94,0x94,0x94,0xB9,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xF9,0x9B,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xA9,0xB0,0xDD,0xFF,0xFF,0xFF,0xBD,0xAF,0x5F,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x05, 0x47, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xC2, 0x96, 0x56, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x40, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xAD, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x02, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB1, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x5A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x5D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x21, 0x00, 0x00, 0x3C, + 0x4C, 0x93, 0x73, 0x4B, 0x45, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x45, 0x4D, 0x55, 0x4E, 0x45, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xE7, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x5F, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x3F, 0x3F, 0x3F, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x43, 0x76, 0x8E, 0x8E, 0x69, 0x3F, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2D, 0x52, 0x8F, 0x97, 0x8F, 0x86, 0x46, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2C, 0x49, 0x7F, 0x8E, 0x8E, 0x8C, 0x40, 0x35, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0C, 0x0C, 0x0C, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x3C, 0x52, 0x8F, 0x8E, 0x84, 0x43, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x85, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xDA, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xEF, 0xEF, 0xEF, + 0xEF, 0xEF, 0xEF, 0x6C, 0x00, 0x78, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xD8, 0x00, 0x00, 0x1E, 0xB7, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x87, 0xDE, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xD4, 0x79, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x5B, 0xF0, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x7F, 0xE4, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xED, 0x9C, 0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x7A, 0xDF, + 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF0, 0x8F, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0xEF, 0xF1, 0xF2, 0xF2, 0xF2, 0x9C, 0x00, 0x05, 0x7C, 0xDA, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xBB, 0x34, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x95, 0x50, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x05, 0x58, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x2A, 0x00, 0x00, 0x00, 0x02, 0x82, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xE8, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x01, 0x57, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xAD, 0x2E, 0x00, 0x00, 0x00, 0x27, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xE6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0x19, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF7, 0x80, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x01, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x0E, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x8A, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x15, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xA0, 0x07, 0x00, 0x00, 0x00, 0x05, 0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, + 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x01, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x2B, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x9B, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x98, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x00, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0x00, 0x00, 0x02, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x8A, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x22, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x29, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x11, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x03, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x00, 0x2D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x00, 0x00, + 0x4E, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x55, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0xAA, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBC, 0xB6, 0xEB, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x35, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF6, 0x08, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xA2, 0x56, 0x54, 0x98, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8B, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x72, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x0C, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x5C, 0x08, 0x01, 0x00, 0x07, 0x0D, 0x4C, 0x8B, 0xF6, 0xFF, 0x92, 0x01, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x01, 0xA9, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCE, 0x69, 0x55, 0x55, 0x58, 0xC2, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0x06, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xA5, 0x64, 0x55, 0xA1, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x80, 0x43, 0x43, 0x43, 0x45, 0x8C, 0x14, 0x00, 0x3B, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x14, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x24, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x21, 0x89, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x08, 0x00, 0x00, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4B, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0xDD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x85, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x35, 0x00, 0x00, 0x17, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x46, 0x00, 0x00, 0x00, 0x00, 0x03, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xAF, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x00, 0x00, 0x36, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x29, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x1E, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x07, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE2, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xD3, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC2, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xC8, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x03, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x0C, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x00, + 0x00, 0x00, 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x00, 0x00, 0x00, 0x00, 0xB1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x4D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x02, 0x00, 0x00, 0x00, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x06, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x00, 0x00, 0x00, 0x14, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, + 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0xD5, 0x9A, 0x46, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x02, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x37, 0x00, 0x00, 0x01, 0xB8, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x13, + 0x00, 0x00, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFB, 0x9F, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x09, 0xE4, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x16, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x86, 0x00, 0x00, 0x12, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x18, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x05, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0x00, 0x00, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x01, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x43, 0x00, 0x00, 0x00, 0x00, 0x09, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x08, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x6A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD8, 0x00, 0x00, 0x53, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0x00, 0x09, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x01, 0x84, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x50, 0x00, 0x00, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x0C, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFA, 0xB1, 0x5C, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x2D, 0x00, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x49, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x0A, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x92, 0xE1, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x1D, 0x00, 0x00, 0x3E, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x0A, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x28, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xA1, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x40, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3D, 0x78, 0xB3, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x03, 0xF7, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0x2F, 0xFB, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x83, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x47, 0xB2, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x01, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xAF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE2, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDA, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x02, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x91, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x02, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6D, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x4A, 0x06, 0x00, 0x00, 0x04, 0x67, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x29, 0xF7, 0xFF, 0xE6, 0x4A, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x02, + 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x0B, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x54, 0x05, 0x00, 0x00, 0x06, 0x46, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x1D, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE5, 0xB6, 0xB6, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xAB, 0x00, 0x00, 0x05, 0xD5, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0xB0, 0x69, 0x69, 0x67, 0x67, 0xA8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0, 0xB6, 0xB6, 0xE3, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0x00, 0x00, 0x00, + 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xF4, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x32, 0x00, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, + 0x00, 0x06, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD3, 0x18, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xCB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xF3, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x01, 0x00, 0x00, 0x22, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE5, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x32, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x04, 0x77, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x83, 0x01, 0x00, 0x00, 0x00, 0x08, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xC9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x83, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x96, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x25, 0xA8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xB2, 0x2F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x04, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x70, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x67, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x46, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 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, 0x00, 0x00, 0xA3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x26, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x61, 0x9D, 0xE0, 0xDF, 0xDF, 0xDF, 0xDF, 0xDE, 0x91, 0x54, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3C, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x53, 0x8F, 0xC7, 0xDF, 0xDF, 0xE5, 0xE3, 0xD7, 0x8E, 0x62, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x89, 0x93, 0xDF, 0xDF, 0xDF, 0xDC, 0x8F, 0x82, 0x3F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x3D, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xFC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xBD, 0x94, 0x94, 0x94, 0xB9, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF9, 0x9B, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xA9, 0xB0, 0xDD, 0xFF, 0xFF, 0xFF, 0xBD, 0xAF, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const lv_image_dsc_t ui_img_text_218x40_png = { .header.w = 218, diff --git a/main/Application/Tasks/GUI/Export/project.info b/main/Application/Tasks/GUI/Export/project.info index 8be9eb8..62525e8 100644 --- a/main/Application/Tasks/GUI/Export/project.info +++ b/main/Application/Tasks/GUI/Export/project.info @@ -1,9 +1,9 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-01-05T13:41:48.0249747+01:00", + "datetime": "2026-01-16T11:44:08.7236698+01:00", "editor_version": "1.5.4", - "project_version": 92, + "project_version": 93, "user": "Kampert Daniel", - "export_datetime": "2026-01-05T19:30:10.2287361+01:00", + "export_datetime": "2026-01-16T13:13:27.6266397+01:00", "export_user": "Kampert Daniel" } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.c b/main/Application/Tasks/GUI/Export/screens/ui_Info.c index 3d1bf7c..ff59aec 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.c @@ -5,61 +5,61 @@ #include "../ui.h" -lv_obj_t * ui_Info = NULL; -lv_obj_t * ui_Panel_Info_Header = NULL; -lv_obj_t * ui_Label_Info_Header = NULL; -lv_obj_t * ui_Panel_Info_Content = NULL; -lv_obj_t * ui_Panel_Device = NULL; -lv_obj_t * ui_Label_Info_Device = NULL; -lv_obj_t * ui_Container_Info_Device = NULL; -lv_obj_t * ui_Info_Container4 = NULL; -lv_obj_t * ui_Label_Info_MAC_Name = NULL; -lv_obj_t * ui_Label_Info_IP_Name = NULL; -lv_obj_t * ui_Info_Container5 = NULL; -lv_obj_t * ui_Label_Info_MAC = NULL; -lv_obj_t * ui_Label_Info_IP = NULL; -lv_obj_t * ui_Panel_Battery = NULL; -lv_obj_t * ui_Label_Info_Battery = NULL; -lv_obj_t * ui_Container_Battery = NULL; -lv_obj_t * ui_Info_Container2 = NULL; -lv_obj_t * ui_Label_Info_Battery_Status_Name = NULL; -lv_obj_t * ui_Label_Info_Battery_Voltage_Name = NULL; -lv_obj_t * ui_Label_Info_Battery_Remaining_Name = NULL; -lv_obj_t * ui_Info_Container3 = NULL; -lv_obj_t * ui_Label_Info_Battery_Status = NULL; -lv_obj_t * ui_Label_Info_Battery_Voltage = NULL; -lv_obj_t * ui_Label_Info_Battery_Remaining = NULL; -lv_obj_t * ui_Info_Bar2 = NULL; -lv_obj_t * ui_Panel_Lepton = NULL; -lv_obj_t * ui_Label_Info_Lepton = NULL; -lv_obj_t * ui_Container_Lepton = NULL; -lv_obj_t * ui_Info_Container1 = NULL; -lv_obj_t * ui_Label_Info_Lepton_Serial_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_Part_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_Revision_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_Uptime_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_FPA_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_AUX_Name = NULL; -lv_obj_t * ui_Info_Container7 = NULL; -lv_obj_t * ui_Label_Info_Lepton_Serial = NULL; -lv_obj_t * ui_Label_Info_Lepton_Part = NULL; -lv_obj_t * ui_Label_Info_Lepton_Revision = NULL; -lv_obj_t * ui_Label_Info_Lepton_Uptime = NULL; -lv_obj_t * ui_Label_Info_Lepton_FPA = NULL; -lv_obj_t * ui_Label_Info_Lepton_AUX = NULL; -lv_obj_t * ui_Container_Info_Buttons = NULL; -lv_obj_t * ui_Button_Info_Back = NULL; -lv_obj_t * ui_Label_Info_Back = NULL; +lv_obj_t *ui_Info = NULL; +lv_obj_t *ui_Panel_Info_Header = NULL; +lv_obj_t *ui_Label_Info_Header = NULL; +lv_obj_t *ui_Panel_Info_Content = NULL; +lv_obj_t *ui_Panel_Device = NULL; +lv_obj_t *ui_Label_Info_Device = NULL; +lv_obj_t *ui_Container_Info_Device = NULL; +lv_obj_t *ui_Info_Container4 = NULL; +lv_obj_t *ui_Label_Info_MAC_Name = NULL; +lv_obj_t *ui_Label_Info_IP_Name = NULL; +lv_obj_t *ui_Info_Container5 = NULL; +lv_obj_t *ui_Label_Info_MAC = NULL; +lv_obj_t *ui_Label_Info_IP = NULL; +lv_obj_t *ui_Panel_Battery = NULL; +lv_obj_t *ui_Label_Info_Battery = NULL; +lv_obj_t *ui_Container_Battery = NULL; +lv_obj_t *ui_Info_Container2 = NULL; +lv_obj_t *ui_Label_Info_Battery_Status_Name = NULL; +lv_obj_t *ui_Label_Info_Battery_Voltage_Name = NULL; +lv_obj_t *ui_Label_Info_Battery_Remaining_Name = NULL; +lv_obj_t *ui_Info_Container3 = NULL; +lv_obj_t *ui_Label_Info_Battery_Status = NULL; +lv_obj_t *ui_Label_Info_Battery_Voltage = NULL; +lv_obj_t *ui_Label_Info_Battery_Remaining = NULL; +lv_obj_t *ui_Info_Bar2 = NULL; +lv_obj_t *ui_Panel_Lepton = NULL; +lv_obj_t *ui_Label_Info_Lepton = NULL; +lv_obj_t *ui_Container_Lepton = NULL; +lv_obj_t *ui_Info_Container1 = NULL; +lv_obj_t *ui_Label_Info_Lepton_Serial_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_Part_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_Revision_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_Uptime_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_FPA_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_AUX_Name = NULL; +lv_obj_t *ui_Info_Container7 = NULL; +lv_obj_t *ui_Label_Info_Lepton_Serial = NULL; +lv_obj_t *ui_Label_Info_Lepton_Part = NULL; +lv_obj_t *ui_Label_Info_Lepton_Revision = NULL; +lv_obj_t *ui_Label_Info_Lepton_Uptime = NULL; +lv_obj_t *ui_Label_Info_Lepton_FPA = NULL; +lv_obj_t *ui_Label_Info_Lepton_AUX = NULL; +lv_obj_t *ui_Container_Info_Buttons = NULL; +lv_obj_t *ui_Button_Info_Back = NULL; +lv_obj_t *ui_Label_Info_Back = NULL; // event funtions void ui_event_Info(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { + if (event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { lv_indev_wait_release(lv_indev_active()); _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } - if(event_code == LV_EVENT_SCREEN_LOADED) { + if (event_code == LV_EVENT_SCREEN_LOADED) { ScreenInfoLoaded(e); } } @@ -68,7 +68,7 @@ void ui_event_Button_Info_Back(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } } @@ -453,8 +453,8 @@ void ui_Info_screen_init(void) lv_obj_set_style_bg_grad_dir(ui_Info_Bar2, LV_GRAD_DIR_HOR, LV_PART_INDICATOR | LV_STATE_DEFAULT); //Compensating for LVGL9.1 draw crash with bar/slider max value when top-padding is nonzero and right-padding is 0 - if(lv_obj_get_style_pad_top(ui_Info_Bar2, LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_Info_Bar2, - lv_obj_get_style_pad_right(ui_Info_Bar2, LV_PART_MAIN) + 1, LV_PART_MAIN); + if (lv_obj_get_style_pad_top(ui_Info_Bar2, LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_Info_Bar2, + lv_obj_get_style_pad_right(ui_Info_Bar2, LV_PART_MAIN) + 1, LV_PART_MAIN); ui_Panel_Lepton = lv_obj_create(ui_Panel_Info_Content); lv_obj_set_width(ui_Panel_Lepton, 300); lv_obj_set_height(ui_Panel_Lepton, 140); @@ -754,7 +754,9 @@ void ui_Info_screen_init(void) void ui_Info_screen_destroy(void) { - if(ui_Info) lv_obj_del(ui_Info); + if (ui_Info) { + lv_obj_del(ui_Info); + } // NULL screen variables ui_Info = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.h b/main/Application/Tasks/GUI/Export/screens/ui_Info.h index e752ce7..0ddd077 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.h @@ -14,52 +14,52 @@ extern "C" { extern void ui_Info_screen_init(void); extern void ui_Info_screen_destroy(void); extern void ui_event_Info(lv_event_t * e); -extern lv_obj_t * ui_Info; -extern lv_obj_t * ui_Panel_Info_Header; -extern lv_obj_t * ui_Label_Info_Header; -extern lv_obj_t * ui_Panel_Info_Content; -extern lv_obj_t * ui_Panel_Device; -extern lv_obj_t * ui_Label_Info_Device; -extern lv_obj_t * ui_Container_Info_Device; -extern lv_obj_t * ui_Info_Container4; -extern lv_obj_t * ui_Label_Info_MAC_Name; -extern lv_obj_t * ui_Label_Info_IP_Name; -extern lv_obj_t * ui_Info_Container5; -extern lv_obj_t * ui_Label_Info_MAC; -extern lv_obj_t * ui_Label_Info_IP; -extern lv_obj_t * ui_Panel_Battery; -extern lv_obj_t * ui_Label_Info_Battery; -extern lv_obj_t * ui_Container_Battery; -extern lv_obj_t * ui_Info_Container2; -extern lv_obj_t * ui_Label_Info_Battery_Status_Name; -extern lv_obj_t * ui_Label_Info_Battery_Voltage_Name; -extern lv_obj_t * ui_Label_Info_Battery_Remaining_Name; -extern lv_obj_t * ui_Info_Container3; -extern lv_obj_t * ui_Label_Info_Battery_Status; -extern lv_obj_t * ui_Label_Info_Battery_Voltage; -extern lv_obj_t * ui_Label_Info_Battery_Remaining; -extern lv_obj_t * ui_Info_Bar2; -extern lv_obj_t * ui_Panel_Lepton; -extern lv_obj_t * ui_Label_Info_Lepton; -extern lv_obj_t * ui_Container_Lepton; -extern lv_obj_t * ui_Info_Container1; -extern lv_obj_t * ui_Label_Info_Lepton_Serial_Name; -extern lv_obj_t * ui_Label_Info_Lepton_Part_Name; -extern lv_obj_t * ui_Label_Info_Lepton_Revision_Name; -extern lv_obj_t * ui_Label_Info_Lepton_Uptime_Name; -extern lv_obj_t * ui_Label_Info_Lepton_FPA_Name; -extern lv_obj_t * ui_Label_Info_Lepton_AUX_Name; -extern lv_obj_t * ui_Info_Container7; -extern lv_obj_t * ui_Label_Info_Lepton_Serial; -extern lv_obj_t * ui_Label_Info_Lepton_Part; -extern lv_obj_t * ui_Label_Info_Lepton_Revision; -extern lv_obj_t * ui_Label_Info_Lepton_Uptime; -extern lv_obj_t * ui_Label_Info_Lepton_FPA; -extern lv_obj_t * ui_Label_Info_Lepton_AUX; -extern lv_obj_t * ui_Container_Info_Buttons; +extern lv_obj_t *ui_Info; +extern lv_obj_t *ui_Panel_Info_Header; +extern lv_obj_t *ui_Label_Info_Header; +extern lv_obj_t *ui_Panel_Info_Content; +extern lv_obj_t *ui_Panel_Device; +extern lv_obj_t *ui_Label_Info_Device; +extern lv_obj_t *ui_Container_Info_Device; +extern lv_obj_t *ui_Info_Container4; +extern lv_obj_t *ui_Label_Info_MAC_Name; +extern lv_obj_t *ui_Label_Info_IP_Name; +extern lv_obj_t *ui_Info_Container5; +extern lv_obj_t *ui_Label_Info_MAC; +extern lv_obj_t *ui_Label_Info_IP; +extern lv_obj_t *ui_Panel_Battery; +extern lv_obj_t *ui_Label_Info_Battery; +extern lv_obj_t *ui_Container_Battery; +extern lv_obj_t *ui_Info_Container2; +extern lv_obj_t *ui_Label_Info_Battery_Status_Name; +extern lv_obj_t *ui_Label_Info_Battery_Voltage_Name; +extern lv_obj_t *ui_Label_Info_Battery_Remaining_Name; +extern lv_obj_t *ui_Info_Container3; +extern lv_obj_t *ui_Label_Info_Battery_Status; +extern lv_obj_t *ui_Label_Info_Battery_Voltage; +extern lv_obj_t *ui_Label_Info_Battery_Remaining; +extern lv_obj_t *ui_Info_Bar2; +extern lv_obj_t *ui_Panel_Lepton; +extern lv_obj_t *ui_Label_Info_Lepton; +extern lv_obj_t *ui_Container_Lepton; +extern lv_obj_t *ui_Info_Container1; +extern lv_obj_t *ui_Label_Info_Lepton_Serial_Name; +extern lv_obj_t *ui_Label_Info_Lepton_Part_Name; +extern lv_obj_t *ui_Label_Info_Lepton_Revision_Name; +extern lv_obj_t *ui_Label_Info_Lepton_Uptime_Name; +extern lv_obj_t *ui_Label_Info_Lepton_FPA_Name; +extern lv_obj_t *ui_Label_Info_Lepton_AUX_Name; +extern lv_obj_t *ui_Info_Container7; +extern lv_obj_t *ui_Label_Info_Lepton_Serial; +extern lv_obj_t *ui_Label_Info_Lepton_Part; +extern lv_obj_t *ui_Label_Info_Lepton_Revision; +extern lv_obj_t *ui_Label_Info_Lepton_Uptime; +extern lv_obj_t *ui_Label_Info_Lepton_FPA; +extern lv_obj_t *ui_Label_Info_Lepton_AUX; +extern lv_obj_t *ui_Container_Info_Buttons; extern void ui_event_Button_Info_Back(lv_event_t * e); -extern lv_obj_t * ui_Button_Info_Back; -extern lv_obj_t * ui_Label_Info_Back; +extern lv_obj_t *ui_Button_Info_Back; +extern lv_obj_t *ui_Label_Info_Back; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.c b/main/Application/Tasks/GUI/Export/screens/ui_Main.c index 17ad764..6768e31 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.c @@ -5,45 +5,44 @@ #include "../ui.h" -lv_obj_t * ui_Main = NULL; -lv_obj_t * ui_Container_Main_StatusBar = NULL; -lv_obj_t * ui_Image_Main_WiFi = NULL; -lv_obj_t * ui_Image_Main_Bluetooth = NULL; -lv_obj_t * ui_Image_Main_SDCard = NULL; -lv_obj_t * ui_Label_Main_Time = NULL; -lv_obj_t * ui_Image_Main_Battery = NULL; -lv_obj_t * ui_Label_Main_Battery_Remaining = NULL; -lv_obj_t * ui_Container_Main_Thermal = NULL; -lv_obj_t * ui_Image_Thermal = NULL; -lv_obj_t * ui_Image_Main_Thermal_Scene_ROI = NULL; -lv_obj_t * ui_Image_Main_Thermal_Spotmeter_ROI = NULL; -lv_obj_t * ui_Image_Main_Thermal_Video_Focus_ROI = NULL; -lv_obj_t * ui_Image_Main_Thermal_AGC_ROI = NULL; -lv_obj_t * ui_Label_Main_Thermal_Crosshair = NULL; -lv_obj_t * ui_Label_Main_Thermal_PixelTemperature = NULL; -lv_obj_t * ui_Container_Main_Thermal_Scene_Statistics = NULL; -lv_obj_t * ui_Label_Main_Thermal_Scene_Max = NULL; -lv_obj_t * ui_Label_Main_Thermal_Scene_Min = NULL; -lv_obj_t * ui_Label_Main_Thermal_Scene_Mean = NULL; -lv_obj_t * ui_Container_Gradient = NULL; -lv_obj_t * ui_Label_TempScaleMax = NULL; -lv_obj_t * ui_Image_Gradient = NULL; -lv_obj_t * ui_Label_TempScaleMin = NULL; -lv_obj_t * ui_Container_Main_Buttons = NULL; -lv_obj_t * ui_Button_Main_WiFi = NULL; -lv_obj_t * ui_Label_Main_Button_WiFi = NULL; -lv_obj_t * ui_Button_Main_ROI = NULL; -lv_obj_t * ui_Label_Main_Button_ROI = NULL; -lv_obj_t * ui_Button_Main_Info = NULL; -lv_obj_t * ui_Label_Main_Button_Info = NULL; -lv_obj_t * ui_Button_Main_Menu = NULL; -lv_obj_t * ui_Label_Main_Button_Menu = NULL; +lv_obj_t *ui_Main = NULL; +lv_obj_t *ui_Container_Main_StatusBar = NULL; +lv_obj_t *ui_Image_Main_WiFi = NULL; +lv_obj_t *ui_Image_Main_SDCard = NULL; +lv_obj_t *ui_Label_Main_Time = NULL; +lv_obj_t *ui_Image_Main_Battery = NULL; +lv_obj_t *ui_Label_Main_Battery_Remaining = NULL; +lv_obj_t *ui_Container_Main_Thermal = NULL; +lv_obj_t *ui_Image_Thermal = NULL; +lv_obj_t *ui_Image_Main_Thermal_Scene_ROI = NULL; +lv_obj_t *ui_Image_Main_Thermal_Spotmeter_ROI = NULL; +lv_obj_t *ui_Image_Main_Thermal_Video_Focus_ROI = NULL; +lv_obj_t *ui_Image_Main_Thermal_AGC_ROI = NULL; +lv_obj_t *ui_Label_Main_Thermal_Crosshair = NULL; +lv_obj_t *ui_Label_Main_Thermal_PixelTemperature = NULL; +lv_obj_t *ui_Container_Main_Thermal_Scene_Statistics = NULL; +lv_obj_t *ui_Label_Main_Thermal_Scene_Max = NULL; +lv_obj_t *ui_Label_Main_Thermal_Scene_Min = NULL; +lv_obj_t *ui_Label_Main_Thermal_Scene_Mean = NULL; +lv_obj_t *ui_Container_Gradient = NULL; +lv_obj_t *ui_Label_TempScaleMax = NULL; +lv_obj_t *ui_Image_Gradient = NULL; +lv_obj_t *ui_Label_TempScaleMin = NULL; +lv_obj_t *ui_Container_Main_Buttons = NULL; +lv_obj_t *ui_Button_Main_WiFi = NULL; +lv_obj_t *ui_Label_Main_Button_WiFi = NULL; +lv_obj_t *ui_Button_Main_ROI = NULL; +lv_obj_t *ui_Label_Main_Button_ROI = NULL; +lv_obj_t *ui_Button_Main_Info = NULL; +lv_obj_t *ui_Label_Main_Button_Info = NULL; +lv_obj_t *ui_Button_Main_Menu = NULL; +lv_obj_t *ui_Label_Main_Button_Menu = NULL; // event funtions void ui_event_Main(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_SCREEN_LOADED) { + if (event_code == LV_EVENT_SCREEN_LOADED) { ScreenMainLoaded(e); } } @@ -52,7 +51,7 @@ void ui_event_Button_Main_WiFi(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { ButtonMainWiFiClicked(e); } } @@ -61,7 +60,7 @@ void ui_event_Button_Main_Info(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Info, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Info_screen_init); } } @@ -70,7 +69,7 @@ void ui_event_Button_Main_Menu(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Menu, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Menu_screen_init); } } @@ -111,23 +110,10 @@ void ui_Main_screen_init(void) lv_obj_set_style_text_opa(ui_Image_Main_WiFi, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_Image_Main_WiFi, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Image_Main_Bluetooth = lv_label_create(ui_Container_Main_StatusBar); - lv_obj_set_width(ui_Image_Main_Bluetooth, LV_SIZE_CONTENT); /// 1 - lv_obj_set_height(ui_Image_Main_Bluetooth, LV_SIZE_CONTENT); /// 1 - lv_obj_set_x(ui_Image_Main_Bluetooth, 25); - lv_obj_set_y(ui_Image_Main_Bluetooth, 0); - lv_label_set_text(ui_Image_Main_Bluetooth, "B"); - lv_obj_remove_flag(ui_Image_Main_Bluetooth, - LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | - LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Image_Main_Bluetooth, lv_color_hex(0xFF0000), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_opa(ui_Image_Main_Bluetooth, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Image_Main_Bluetooth, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Image_Main_SDCard = lv_label_create(ui_Container_Main_StatusBar); lv_obj_set_width(ui_Image_Main_SDCard, LV_SIZE_CONTENT); /// 1 lv_obj_set_height(ui_Image_Main_SDCard, LV_SIZE_CONTENT); /// 1 - lv_obj_set_x(ui_Image_Main_SDCard, 45); + lv_obj_set_x(ui_Image_Main_SDCard, 25); lv_obj_set_y(ui_Image_Main_SDCard, 0); lv_label_set_text(ui_Image_Main_SDCard, "C"); lv_obj_remove_flag(ui_Image_Main_SDCard, @@ -480,13 +466,14 @@ void ui_Main_screen_init(void) void ui_Main_screen_destroy(void) { - if(ui_Main) lv_obj_del(ui_Main); + if (ui_Main) { + lv_obj_del(ui_Main); + } // NULL screen variables ui_Main = NULL; ui_Container_Main_StatusBar = NULL; ui_Image_Main_WiFi = NULL; - ui_Image_Main_Bluetooth = NULL; ui_Image_Main_SDCard = NULL; ui_Label_Main_Time = NULL; ui_Image_Main_Battery = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.h b/main/Application/Tasks/GUI/Export/screens/ui_Main.h index 6306c52..16a90ad 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.h @@ -14,42 +14,41 @@ extern "C" { extern void ui_Main_screen_init(void); extern void ui_Main_screen_destroy(void); extern void ui_event_Main(lv_event_t * e); -extern lv_obj_t * ui_Main; -extern lv_obj_t * ui_Container_Main_StatusBar; -extern lv_obj_t * ui_Image_Main_WiFi; -extern lv_obj_t * ui_Image_Main_Bluetooth; -extern lv_obj_t * ui_Image_Main_SDCard; -extern lv_obj_t * ui_Label_Main_Time; -extern lv_obj_t * ui_Image_Main_Battery; -extern lv_obj_t * ui_Label_Main_Battery_Remaining; -extern lv_obj_t * ui_Container_Main_Thermal; -extern lv_obj_t * ui_Image_Thermal; -extern lv_obj_t * ui_Image_Main_Thermal_Scene_ROI; -extern lv_obj_t * ui_Image_Main_Thermal_Spotmeter_ROI; -extern lv_obj_t * ui_Image_Main_Thermal_Video_Focus_ROI; -extern lv_obj_t * ui_Image_Main_Thermal_AGC_ROI; -extern lv_obj_t * ui_Label_Main_Thermal_Crosshair; -extern lv_obj_t * ui_Label_Main_Thermal_PixelTemperature; -extern lv_obj_t * ui_Container_Main_Thermal_Scene_Statistics; -extern lv_obj_t * ui_Label_Main_Thermal_Scene_Max; -extern lv_obj_t * ui_Label_Main_Thermal_Scene_Min; -extern lv_obj_t * ui_Label_Main_Thermal_Scene_Mean; -extern lv_obj_t * ui_Container_Gradient; -extern lv_obj_t * ui_Label_TempScaleMax; -extern lv_obj_t * ui_Image_Gradient; -extern lv_obj_t * ui_Label_TempScaleMin; -extern lv_obj_t * ui_Container_Main_Buttons; +extern lv_obj_t *ui_Main; +extern lv_obj_t *ui_Container_Main_StatusBar; +extern lv_obj_t *ui_Image_Main_WiFi; +extern lv_obj_t *ui_Image_Main_SDCard; +extern lv_obj_t *ui_Label_Main_Time; +extern lv_obj_t *ui_Image_Main_Battery; +extern lv_obj_t *ui_Label_Main_Battery_Remaining; +extern lv_obj_t *ui_Container_Main_Thermal; +extern lv_obj_t *ui_Image_Thermal; +extern lv_obj_t *ui_Image_Main_Thermal_Scene_ROI; +extern lv_obj_t *ui_Image_Main_Thermal_Spotmeter_ROI; +extern lv_obj_t *ui_Image_Main_Thermal_Video_Focus_ROI; +extern lv_obj_t *ui_Image_Main_Thermal_AGC_ROI; +extern lv_obj_t *ui_Label_Main_Thermal_Crosshair; +extern lv_obj_t *ui_Label_Main_Thermal_PixelTemperature; +extern lv_obj_t *ui_Container_Main_Thermal_Scene_Statistics; +extern lv_obj_t *ui_Label_Main_Thermal_Scene_Max; +extern lv_obj_t *ui_Label_Main_Thermal_Scene_Min; +extern lv_obj_t *ui_Label_Main_Thermal_Scene_Mean; +extern lv_obj_t *ui_Container_Gradient; +extern lv_obj_t *ui_Label_TempScaleMax; +extern lv_obj_t *ui_Image_Gradient; +extern lv_obj_t *ui_Label_TempScaleMin; +extern lv_obj_t *ui_Container_Main_Buttons; extern void ui_event_Button_Main_WiFi(lv_event_t * e); -extern lv_obj_t * ui_Button_Main_WiFi; -extern lv_obj_t * ui_Label_Main_Button_WiFi; -extern lv_obj_t * ui_Button_Main_ROI; -extern lv_obj_t * ui_Label_Main_Button_ROI; +extern lv_obj_t *ui_Button_Main_WiFi; +extern lv_obj_t *ui_Label_Main_Button_WiFi; +extern lv_obj_t *ui_Button_Main_ROI; +extern lv_obj_t *ui_Label_Main_Button_ROI; extern void ui_event_Button_Main_Info(lv_event_t * e); -extern lv_obj_t * ui_Button_Main_Info; -extern lv_obj_t * ui_Label_Main_Button_Info; +extern lv_obj_t *ui_Button_Main_Info; +extern lv_obj_t *ui_Label_Main_Button_Info; extern void ui_event_Button_Main_Menu(lv_event_t * e); -extern lv_obj_t * ui_Button_Main_Menu; -extern lv_obj_t * ui_Label_Main_Button_Menu; +extern lv_obj_t *ui_Button_Main_Menu; +extern lv_obj_t *ui_Label_Main_Button_Menu; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c index f540c27..99fbf8b 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c @@ -5,23 +5,23 @@ #include "../ui.h" -lv_obj_t * ui_Menu = NULL; -lv_obj_t * ui_Panel_Menu_Header = NULL; -lv_obj_t * ui_Label_Menu_Header = NULL; -lv_obj_t * ui_Container_Menu = NULL; -lv_obj_t * ui_Container_Menu_Buttons = NULL; -lv_obj_t * ui_Button_Menu_Back = NULL; -lv_obj_t * ui_Label_Menu_Back = NULL; +lv_obj_t *ui_Menu = NULL; +lv_obj_t *ui_Panel_Menu_Header = NULL; +lv_obj_t *ui_Label_Menu_Header = NULL; +lv_obj_t *ui_Container_Menu = NULL; +lv_obj_t *ui_Container_Menu_Buttons = NULL; +lv_obj_t *ui_Button_Menu_Back = NULL; +lv_obj_t *ui_Label_Menu_Back = NULL; // event funtions void ui_event_Menu(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { + if (event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { lv_indev_wait_release(lv_indev_active()); _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } - if(event_code == LV_EVENT_SCREEN_LOADED) { + if (event_code == LV_EVENT_SCREEN_LOADED) { ScreenMenuLoaded(e); } } @@ -30,7 +30,7 @@ void ui_event_Button_Menu_Back(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } } @@ -120,7 +120,9 @@ void ui_Menu_screen_init(void) void ui_Menu_screen_destroy(void) { - if(ui_Menu) lv_obj_del(ui_Menu); + if (ui_Menu) { + lv_obj_del(ui_Menu); + } // NULL screen variables ui_Menu = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h index 1e46a28..792175c 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h @@ -14,14 +14,14 @@ extern "C" { extern void ui_Menu_screen_init(void); extern void ui_Menu_screen_destroy(void); extern void ui_event_Menu(lv_event_t * e); -extern lv_obj_t * ui_Menu; -extern lv_obj_t * ui_Panel_Menu_Header; -extern lv_obj_t * ui_Label_Menu_Header; -extern lv_obj_t * ui_Container_Menu; -extern lv_obj_t * ui_Container_Menu_Buttons; +extern lv_obj_t *ui_Menu; +extern lv_obj_t *ui_Panel_Menu_Header; +extern lv_obj_t *ui_Label_Menu_Header; +extern lv_obj_t *ui_Container_Menu; +extern lv_obj_t *ui_Container_Menu_Buttons; extern void ui_event_Button_Menu_Back(lv_event_t * e); -extern lv_obj_t * ui_Button_Menu_Back; -extern lv_obj_t * ui_Label_Menu_Back; +extern lv_obj_t *ui_Button_Menu_Back; +extern lv_obj_t *ui_Label_Menu_Back; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c index 2714406..905944e 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c @@ -5,13 +5,13 @@ #include "../ui.h" -lv_obj_t * ui_Splash = NULL; -lv_obj_t * ui_SplashScreen_Logo = NULL; -lv_obj_t * ui_SplashScreen_LogoText = NULL; -lv_obj_t * ui_SplashScreen_Subtext = NULL; -lv_obj_t * ui_SplashScreen_LoadingBar = NULL; -lv_obj_t * ui_SplashScreen_StatusText = NULL; -lv_obj_t * ui_SplashScreen_FirmwareVersion = NULL; +lv_obj_t *ui_Splash = NULL; +lv_obj_t *ui_SplashScreen_Logo = NULL; +lv_obj_t *ui_SplashScreen_LogoText = NULL; +lv_obj_t *ui_SplashScreen_Subtext = NULL; +lv_obj_t *ui_SplashScreen_LoadingBar = NULL; +lv_obj_t *ui_SplashScreen_StatusText = NULL; +lv_obj_t *ui_SplashScreen_FirmwareVersion = NULL; // event funtions // build funtions @@ -77,9 +77,9 @@ void ui_Splash_screen_init(void) lv_obj_set_style_bg_opa(ui_SplashScreen_LoadingBar, 255, LV_PART_INDICATOR | LV_STATE_DEFAULT); //Compensating for LVGL9.1 draw crash with bar/slider max value when top-padding is nonzero and right-padding is 0 - if(lv_obj_get_style_pad_top(ui_SplashScreen_LoadingBar, - LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_SplashScreen_LoadingBar, - lv_obj_get_style_pad_right(ui_SplashScreen_LoadingBar, LV_PART_MAIN) + 1, LV_PART_MAIN); + if (lv_obj_get_style_pad_top(ui_SplashScreen_LoadingBar, + LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_SplashScreen_LoadingBar, + lv_obj_get_style_pad_right(ui_SplashScreen_LoadingBar, LV_PART_MAIN) + 1, LV_PART_MAIN); ui_SplashScreen_StatusText = lv_label_create(ui_Splash); lv_obj_set_width(ui_SplashScreen_StatusText, LV_SIZE_CONTENT); /// 1 lv_obj_set_height(ui_SplashScreen_StatusText, LV_SIZE_CONTENT); /// 1 @@ -113,7 +113,9 @@ void ui_Splash_screen_init(void) void ui_Splash_screen_destroy(void) { - if(ui_Splash) lv_obj_del(ui_Splash); + if (ui_Splash) { + lv_obj_del(ui_Splash); + } // NULL screen variables ui_Splash = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h index 6bd4ce1..6df951c 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h @@ -13,13 +13,13 @@ extern "C" { // SCREEN: ui_Splash extern void ui_Splash_screen_init(void); extern void ui_Splash_screen_destroy(void); -extern lv_obj_t * ui_Splash; -extern lv_obj_t * ui_SplashScreen_Logo; -extern lv_obj_t * ui_SplashScreen_LogoText; -extern lv_obj_t * ui_SplashScreen_Subtext; -extern lv_obj_t * ui_SplashScreen_LoadingBar; -extern lv_obj_t * ui_SplashScreen_StatusText; -extern lv_obj_t * ui_SplashScreen_FirmwareVersion; +extern lv_obj_t *ui_Splash; +extern lv_obj_t *ui_SplashScreen_Logo; +extern lv_obj_t *ui_SplashScreen_LogoText; +extern lv_obj_t *ui_SplashScreen_Subtext; +extern lv_obj_t *ui_SplashScreen_LoadingBar; +extern lv_obj_t *ui_SplashScreen_StatusText; +extern lv_obj_t *ui_SplashScreen_FirmwareVersion; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/ui.c b/main/Application/Tasks/GUI/Export/ui.c index f2ce471..a1552e5 100644 --- a/main/Application/Tasks/GUI/Export/ui.c +++ b/main/Application/Tasks/GUI/Export/ui.c @@ -9,13 +9,13 @@ ///////////////////// VARIABLES //////////////////// // EVENTS -lv_obj_t * ui____initial_actions0; +lv_obj_t *ui____initial_actions0; // IMAGES AND IMAGE SETS ///////////////////// TEST LVGL SETTINGS //////////////////// #if LV_COLOR_DEPTH != 16 - #error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" +#error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" #endif ///////////////////// ANIMATIONS //////////////////// @@ -26,9 +26,9 @@ lv_obj_t * ui____initial_actions0; void ui_init(void) { - lv_disp_t * dispp = lv_display_get_default(); - lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), - false, LV_FONT_DEFAULT); + lv_disp_t *dispp = lv_display_get_default(); + lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), + false, LV_FONT_DEFAULT); lv_disp_set_theme(dispp, theme); ui_Splash_screen_init(); ui_Main_screen_init(); diff --git a/main/Application/Tasks/GUI/Export/ui.h b/main/Application/Tasks/GUI/Export/ui.h index 19aa4ab..284b65f 100644 --- a/main/Application/Tasks/GUI/Export/ui.h +++ b/main/Application/Tasks/GUI/Export/ui.h @@ -2,47 +2,47 @@ // SquareLine Studio version: SquareLine Studio 1.5.4 // LVGL version: 9.1.0 // Project name: PyroVision + +#ifndef _PYROVISION_UI_H +#define _PYROVISION_UI_H -#ifndef _PYROVISION_UI_H -#define _PYROVISION_UI_H - -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { -#endif - -#include "lvgl.h" - -#include "ui_helpers.h" -#include "ui_events.h" - - -///////////////////// SCREENS //////////////////// - -#include "screens/ui_Splash.h" -#include "screens/ui_Main.h" -#include "screens/ui_Menu.h" -#include "screens/ui_Info.h" - -///////////////////// VARIABLES //////////////////// - - -// EVENTS - -extern lv_obj_t * ui____initial_actions0; - -// IMAGES AND IMAGE SETS -LV_IMG_DECLARE(ui_img_logo_80x44_png); // assets/Logo_80x44.png -LV_IMG_DECLARE(ui_img_text_218x40_png); // assets/Text_218x40.png - -// FONTS -LV_FONT_DECLARE(ui_font_fa); - -// UI INIT -void ui_init(void); -void ui_destroy(void); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif + #endif + + #include "lvgl.h" + +#include "ui_helpers.h" +#include "ui_events.h" + + +///////////////////// SCREENS //////////////////// + +#include "screens/ui_Splash.h" +#include "screens/ui_Main.h" +#include "screens/ui_Menu.h" +#include "screens/ui_Info.h" + +///////////////////// VARIABLES //////////////////// + + +// EVENTS + +extern lv_obj_t *ui____initial_actions0; + +// IMAGES AND IMAGE SETS +LV_IMG_DECLARE(ui_img_logo_80x44_png); // assets/Logo_80x44.png +LV_IMG_DECLARE(ui_img_text_218x40_png); // assets/Text_218x40.png + +// FONTS +LV_FONT_DECLARE(ui_font_fa); + +// UI INIT +void ui_init(void); +void ui_destroy(void); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/main/Application/Tasks/GUI/Export/ui_events.cpp b/main/Application/Tasks/GUI/Export/ui_events.cpp index 06c3784..bb90580 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.cpp +++ b/main/Application/Tasks/GUI/Export/ui_events.cpp @@ -12,13 +12,14 @@ void ScreenMainLoaded(lv_event_t *e) { char Buf[128]; + App_Settings_Info_t Info; - snprintf(Buf, sizeof(Buf), "Firmware %u.%u.%u\n(c) 2026 PyroVision Project", - PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, PYROVISION_VERSION_BUILD); + SettingsManager_GetInfo(&Info); + + snprintf(Buf, sizeof(Buf), "Firmware %s\n(c) 2026 PyroVision Project", Info.FirmwareVersion); lv_label_set_text(ui_SplashScreen_FirmwareVersion, Buf); lv_label_set_text(ui_Image_Main_WiFi, LV_SYMBOL_WIFI); - lv_label_set_text(ui_Image_Main_Bluetooth, LV_SYMBOL_BLUETOOTH); lv_label_set_text(ui_Image_Main_SDCard, LV_SYMBOL_SD_CARD); lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_FULL); @@ -38,162 +39,12 @@ void ScreenInfoLoaded(lv_event_t *e) esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_FPA_AUX_TEMP, NULL, 0, 0); } -/* -static lv_obj_t * create_text(lv_obj_t * parent, const char * icon, const char * txt, - int builder_variant) -{ - lv_obj_t * obj = lv_menu_cont_create(parent); - - lv_obj_t * img = NULL; - lv_obj_t * label = NULL; - - if(icon) { - img = lv_img_create(obj); - lv_img_set_src(img, icon); - } - - if(txt) { - label = lv_label_create(obj); - lv_label_set_text(label, txt); - lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_flex_grow(label, 1); - } - - if(builder_variant == 1 && icon && txt) { - lv_obj_add_flag(img, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK); - lv_obj_swap(img, label); - } - - return obj; -} - -static lv_obj_t * create_slider(lv_obj_t * parent, const char * icon, const char * txt, int32_t min, int32_t max, int32_t val) -{ - lv_obj_t * obj = create_text(parent, icon, txt, 0); - - lv_obj_t * slider = lv_slider_create(obj); - lv_obj_set_flex_grow(slider, 1); - lv_slider_set_range(slider, min, max); - lv_slider_set_value(slider, val, LV_ANIM_OFF); - - if(icon == NULL) { - lv_obj_add_flag(slider, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK); - } - - return obj; -} - -static lv_obj_t * create_switch(lv_obj_t * parent, const char * icon, const char * txt, bool chk) -{ - lv_obj_t * obj = create_text(parent, icon, txt, 0); - - lv_obj_t * sw = lv_switch_create(obj); - lv_obj_add_state(sw, LV_STATE_CHECKED); - - return obj; -} -*/ - -void ScreenMenuLoaded(lv_event_t *e) +void ButtonMainWiFiClicked(lv_event_t *e) { - /* - lv_obj_t * root_page; - lv_obj_t *menu; - lv_obj_t * cont; - lv_obj_t * section; - lv_obj_t * text_area; - lv_obj_t * btn; - - menu = lv_menu_create(ui_Container_Menu); - lv_obj_set_size(menu, 320, 210); - lv_obj_set_pos(menu, 0, 15); - lv_obj_center(menu); - - lv_menu_set_mode_header(menu, LV_MENU_HEADER_TOP_FIXED); - - lv_obj_t * sub_wifi_page = lv_menu_page_create(menu, "WiFi"); - lv_menu_separator_create(sub_wifi_page); - section = lv_menu_section_create(sub_wifi_page); - - cont = create_switch(section, LV_SYMBOL_WIFI, "Auto Connect", false); - - lv_obj_t * ssid_cont = lv_menu_cont_create(sub_wifi_page); - lv_obj_t * ssid_label = lv_label_create(ssid_cont); - lv_label_set_text(ssid_label, "SSID:"); - text_area = lv_textarea_create(ssid_cont); - lv_textarea_set_one_line(text_area, true); - lv_textarea_set_placeholder_text(text_area, "WiFi Name"); - lv_obj_set_width(text_area, 200); - - lv_obj_t * ip_cont = lv_menu_cont_create(sub_wifi_page); - lv_obj_t * ip_label = lv_label_create(ip_cont); - lv_label_set_text(ip_label, "IP Address:"); - text_area = lv_textarea_create(ip_cont); - lv_textarea_set_one_line(text_area, true); - lv_textarea_set_placeholder_text(text_area, "192.168.1.100"); - lv_obj_set_width(text_area, 200); - - lv_obj_t * pwd_cont = lv_menu_cont_create(sub_wifi_page); - lv_obj_t * pwd_label = lv_label_create(pwd_cont); - lv_label_set_text(pwd_label, "Password:"); - text_area = lv_textarea_create(pwd_cont); - lv_textarea_set_one_line(text_area, true); - lv_textarea_set_password_mode(text_area, true); - lv_textarea_set_placeholder_text(text_area, "Password"); - lv_obj_set_width(text_area, 200); - - lv_obj_t * sub_display_page = lv_menu_page_create(menu, "Display"); - lv_menu_separator_create(sub_display_page); - section = lv_menu_section_create(sub_display_page); - create_slider(section, LV_SYMBOL_IMAGE, "Brightness", 0, 100, 80); - - lv_obj_t * sub_about_page = lv_menu_page_create(menu, "About"); - - lv_obj_t * sub_software_info_page = lv_menu_page_create(menu, "Software Information"); - section = lv_menu_section_create(sub_software_info_page); - create_text(section, NULL, "PyroVision Firmware", 0); - char version_buf[64]; - snprintf(version_buf, sizeof(version_buf), "Version %u.%u.%u", - PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, PYROVISION_VERSION_BUILD); - create_text(section, NULL, version_buf, 0); - create_text(section, NULL, "ESP32-S3 Platform", 0); - create_text(section, NULL, "LVGL 9.1.0", 0); - - lv_obj_t * sub_legal_info_page = lv_menu_page_create(menu, "Legal Information"); - section = lv_menu_section_create(sub_legal_info_page); - create_text(section, NULL, "(c) 2026 PyroVision Project", 0); - create_text(section, NULL, "Licensed under GNU GPL v3", 0); - create_text(section, NULL, "", 0); - create_text(section, NULL, "This program is free software:", 0); - create_text(section, NULL, "you can redistribute it and/or", 0); - create_text(section, NULL, "modify it under the terms of", 0); - create_text(section, NULL, "the GNU General Public License", 0); - create_text(section, NULL, "as published by the Free", 0); - create_text(section, NULL, "Software Foundation.", 0); - - lv_menu_separator_create(sub_about_page); - section = lv_menu_section_create(sub_about_page); - cont = create_text(section, LV_SYMBOL_FILE, "Software information", 0); - lv_menu_set_load_page_event(menu, cont, sub_software_info_page); - cont = create_text(section, LV_SYMBOL_LIST, "Legal information", 0); - lv_menu_set_load_page_event(menu, cont, sub_legal_info_page); - - root_page = lv_menu_page_create(menu, NULL); - section = lv_menu_section_create(root_page); - - cont = create_text(section, LV_SYMBOL_WIFI, "WiFi", 0); - lv_menu_set_load_page_event(menu, cont, sub_wifi_page); - - cont = create_text(section, LV_SYMBOL_IMAGE, "Display", 0); - lv_menu_set_load_page_event(menu, cont, sub_display_page); - - cont = create_text(section, LV_SYMBOL_HOME, "About", 0); - lv_menu_set_load_page_event(menu, cont, sub_about_page); - - lv_menu_set_sidebar_page(menu, root_page);*/ + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_OPEN_WIFI_REQUEST, NULL, 0, 0); } -void ButtonMainWiFiClicked(lv_event_t *e) +void ScreenMenuLoaded(lv_event_t * e) { - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_OPEN_WIFI_REQUEST, NULL, 0, 0); + // Your code here } diff --git a/main/Application/Tasks/GUI/Export/ui_helpers.c b/main/Application/Tasks/GUI/Export/ui_helpers.c index 62ee629..84a7df4 100644 --- a/main/Application/Tasks/GUI/Export/ui_helpers.c +++ b/main/Application/Tasks/GUI/Export/ui_helpers.c @@ -7,53 +7,80 @@ void _ui_bar_set_property(lv_obj_t * target, int id, int val) { - if(id == _UI_BAR_PROPERTY_VALUE_WITH_ANIM) lv_bar_set_value(target, val, LV_ANIM_ON); - if(id == _UI_BAR_PROPERTY_VALUE) lv_bar_set_value(target, val, LV_ANIM_OFF); + if (id == _UI_BAR_PROPERTY_VALUE_WITH_ANIM) { + lv_bar_set_value(target, val, LV_ANIM_ON); + } + if (id == _UI_BAR_PROPERTY_VALUE) { + lv_bar_set_value(target, val, LV_ANIM_OFF); + } } void _ui_basic_set_property(lv_obj_t * target, int id, int val) { - if(id == _UI_BASIC_PROPERTY_POSITION_X) lv_obj_set_x(target, val); - if(id == _UI_BASIC_PROPERTY_POSITION_Y) lv_obj_set_y(target, val); - if(id == _UI_BASIC_PROPERTY_WIDTH) lv_obj_set_width(target, val); - if(id == _UI_BASIC_PROPERTY_HEIGHT) lv_obj_set_height(target, val); + if (id == _UI_BASIC_PROPERTY_POSITION_X) { + lv_obj_set_x(target, val); + } + if (id == _UI_BASIC_PROPERTY_POSITION_Y) { + lv_obj_set_y(target, val); + } + if (id == _UI_BASIC_PROPERTY_WIDTH) { + lv_obj_set_width(target, val); + } + if (id == _UI_BASIC_PROPERTY_HEIGHT) { + lv_obj_set_height(target, val); + } } void _ui_dropdown_set_property(lv_obj_t * target, int id, int val) { - if(id == _UI_DROPDOWN_PROPERTY_SELECTED) lv_dropdown_set_selected(target, val); + if (id == _UI_DROPDOWN_PROPERTY_SELECTED) { + lv_dropdown_set_selected(target, val); + } } void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val) { - if(id == _UI_IMAGE_PROPERTY_IMAGE) lv_image_set_src(target, val); + if (id == _UI_IMAGE_PROPERTY_IMAGE) { + lv_image_set_src(target, val); + } } void _ui_label_set_property(lv_obj_t * target, int id, const char * val) { - if(id == _UI_LABEL_PROPERTY_TEXT) lv_label_set_text(target, val); + if (id == _UI_LABEL_PROPERTY_TEXT) { + lv_label_set_text(target, val); + } } void _ui_roller_set_property(lv_obj_t * target, int id, int val) { - if(id == _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM) lv_roller_set_selected(target, val, LV_ANIM_ON); - if(id == _UI_ROLLER_PROPERTY_SELECTED) lv_roller_set_selected(target, val, LV_ANIM_OFF); + if (id == _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM) { + lv_roller_set_selected(target, val, LV_ANIM_ON); + } + if (id == _UI_ROLLER_PROPERTY_SELECTED) { + lv_roller_set_selected(target, val, LV_ANIM_OFF); + } } void _ui_slider_set_property(lv_obj_t * target, int id, int val) { - if(id == _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM) lv_slider_set_value(target, val, LV_ANIM_ON); - if(id == _UI_SLIDER_PROPERTY_VALUE) lv_slider_set_value(target, val, LV_ANIM_OFF); + if (id == _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM) { + lv_slider_set_value(target, val, LV_ANIM_ON); + } + if (id == _UI_SLIDER_PROPERTY_VALUE) { + lv_slider_set_value(target, val, LV_ANIM_OFF); + } } void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, void (*target_init)(void)) { - if(*target == NULL) + if (*target == NULL) { target_init(); + } lv_screen_load_anim(*target, fademode, spd, delay, false); } @@ -84,21 +111,31 @@ void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea) void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value) { - if(value == _UI_MODIFY_FLAG_TOGGLE) { - if(lv_obj_has_flag(target, flag)) lv_obj_remove_flag(target, flag); - else lv_obj_add_flag(target, flag); + if (value == _UI_MODIFY_FLAG_TOGGLE) { + if (lv_obj_has_flag(target, flag)) { + lv_obj_remove_flag(target, flag); + } else { + lv_obj_add_flag(target, flag); + } + } else if (value == _UI_MODIFY_FLAG_ADD) { + lv_obj_add_flag(target, flag); + } else { + lv_obj_remove_flag(target, flag); } - else if(value == _UI_MODIFY_FLAG_ADD) lv_obj_add_flag(target, flag); - else lv_obj_remove_flag(target, flag); } void _ui_state_modify(lv_obj_t * target, int32_t state, int value) { - if(value == _UI_MODIFY_STATE_TOGGLE) { - if(lv_obj_has_state(target, state)) lv_obj_remove_state(target, state); - else lv_obj_add_state(target, state); + if (value == _UI_MODIFY_STATE_TOGGLE) { + if (lv_obj_has_state(target, state)) { + lv_obj_remove_state(target, state); + } else { + lv_obj_add_state(target, state); + } + } else if (value == _UI_MODIFY_STATE_ADD) { + lv_obj_add_state(target, state); + } else { + lv_obj_remove_state(target, state); } - else if(value == _UI_MODIFY_STATE_ADD) lv_obj_add_state(target, state); - else lv_obj_remove_state(target, state); } @@ -106,10 +143,18 @@ void _ui_textarea_move_cursor(lv_obj_t * target, int val) { - if(val == UI_MOVE_CURSOR_UP) lv_textarea_cursor_up(target); - if(val == UI_MOVE_CURSOR_RIGHT) lv_textarea_cursor_right(target); - if(val == UI_MOVE_CURSOR_DOWN) lv_textarea_cursor_down(target); - if(val == UI_MOVE_CURSOR_LEFT) lv_textarea_cursor_left(target); + if (val == UI_MOVE_CURSOR_UP) { + lv_textarea_cursor_up(target); + } + if (val == UI_MOVE_CURSOR_RIGHT) { + lv_textarea_cursor_right(target); + } + if (val == UI_MOVE_CURSOR_DOWN) { + lv_textarea_cursor_down(target); + } + if (val == UI_MOVE_CURSOR_LEFT) { + lv_textarea_cursor_left(target); + } lv_obj_add_state(target, LV_STATE_FOCUSED); } @@ -122,7 +167,7 @@ void scr_unloaded_delete_cb(lv_event_t * e) // Get the destroy callback from user_data screen_destroy_cb_t destroy_cb = lv_event_get_user_data(e); - if(destroy_cb) { + if (destroy_cb) { destroy_cb(); // call the specific screen destroy function @@ -145,7 +190,7 @@ void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_x(usr->target, v); } @@ -155,7 +200,7 @@ void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_y(usr->target, v); } @@ -165,7 +210,7 @@ void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_width(usr->target, v); } @@ -175,7 +220,7 @@ void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_height(usr->target, v); } @@ -185,7 +230,7 @@ void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_style_opa(usr->target, v, 0); } @@ -195,7 +240,7 @@ void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_image_set_scale(usr->target, v); } @@ -205,7 +250,7 @@ void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_image_set_rotation(usr->target, v); } @@ -215,11 +260,15 @@ void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; usr->val = v; - if(v < 0) v = 0; - if(v >= usr->imgset_size) v = usr->imgset_size - 1; + if (v < 0) { + v = 0; + } + if (v >= usr->imgset_size) { + v = usr->imgset_size - 1; + } lv_image_set_src(usr->target, usr->imgset[v]); } @@ -227,7 +276,7 @@ int32_t _ui_anim_callback_get_x(lv_anim_t * a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_x_aligned(usr->target); } @@ -237,7 +286,7 @@ int32_t _ui_anim_callback_get_y(lv_anim_t * a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_y_aligned(usr->target); } @@ -247,7 +296,7 @@ int32_t _ui_anim_callback_get_width(lv_anim_t * a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_width(usr->target); } @@ -257,7 +306,7 @@ int32_t _ui_anim_callback_get_height(lv_anim_t * a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_height(usr->target); } @@ -267,7 +316,7 @@ int32_t _ui_anim_callback_get_opacity(lv_anim_t * a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_style_opa(usr->target, 0); } @@ -276,7 +325,7 @@ int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_image_get_scale(usr->target); } @@ -285,7 +334,7 @@ int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_image_get_rotation(usr->target); } @@ -294,7 +343,7 @@ int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return usr->val; } @@ -318,8 +367,11 @@ void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * pref } void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off) { - if(lv_obj_has_state(src, LV_STATE_CHECKED)) lv_label_set_text(trg, txt_on); - else lv_label_set_text(trg, txt_off); + if (lv_obj_has_state(src, LV_STATE_CHECKED)) { + lv_label_set_text(trg, txt_on); + } else { + lv_label_set_text(trg, txt_off); + } } @@ -327,9 +379,13 @@ void _ui_spinbox_step(lv_obj_t * target, int val) { - if(val > 0) lv_spinbox_increment(target); + if (val > 0) { + lv_spinbox_increment(target); + } - else lv_spinbox_decrement(target); + else { + lv_spinbox_decrement(target); + } lv_obj_send_event(target, LV_EVENT_VALUE_CHANGED, 0); diff --git a/main/Application/Tasks/GUI/Export/ui_helpers.h b/main/Application/Tasks/GUI/Export/ui_helpers.h index 81650e0..45374ca 100644 --- a/main/Application/Tasks/GUI/Export/ui_helpers.h +++ b/main/Application/Tasks/GUI/Export/ui_helpers.h @@ -2,146 +2,146 @@ // SquareLine Studio version: SquareLine Studio 1.5.4 // LVGL version: 9.1.0 // Project name: PyroVision + +#ifndef _PYROVISION_UI_HELPERS_H +#define _PYROVISION_UI_HELPERS_H -#ifndef _PYROVISION_UI_HELPERS_H -#define _PYROVISION_UI_HELPERS_H - -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { -#endif - -#include "ui.h" - -#define _UI_TEMPORARY_STRING_BUFFER_SIZE 32 -#define _UI_BAR_PROPERTY_VALUE 0 -#define _UI_BAR_PROPERTY_VALUE_WITH_ANIM 1 -void _ui_bar_set_property(lv_obj_t * target, int id, int val); - -#define _UI_BASIC_PROPERTY_POSITION_X 0 -#define _UI_BASIC_PROPERTY_POSITION_Y 1 -#define _UI_BASIC_PROPERTY_WIDTH 2 -#define _UI_BASIC_PROPERTY_HEIGHT 3 -void _ui_basic_set_property(lv_obj_t * target, int id, int val); - -#define _UI_DROPDOWN_PROPERTY_SELECTED 0 -void _ui_dropdown_set_property(lv_obj_t * target, int id, int val); - -#define _UI_IMAGE_PROPERTY_IMAGE 0 -void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val); - -#define _UI_LABEL_PROPERTY_TEXT 0 -void _ui_label_set_property(lv_obj_t * target, int id, const char * val); - -#define _UI_ROLLER_PROPERTY_SELECTED 0 -#define _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM 1 -void _ui_roller_set_property(lv_obj_t * target, int id, int val); - -#define _UI_SLIDER_PROPERTY_VALUE 0 -#define _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM 1 -void _ui_slider_set_property(lv_obj_t * target, int id, int val); - -void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, - void (*target_init)(void)); - -void _ui_arc_increment(lv_obj_t * target, int val); - -void _ui_bar_increment(lv_obj_t * target, int val, int anm); - -void _ui_slider_increment(lv_obj_t * target, int val, int anm); - -void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea); - -#define _UI_MODIFY_FLAG_ADD 0 -#define _UI_MODIFY_FLAG_REMOVE 1 -#define _UI_MODIFY_FLAG_TOGGLE 2 -void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value); - -#define _UI_MODIFY_STATE_ADD 0 -#define _UI_MODIFY_STATE_REMOVE 1 -#define _UI_MODIFY_STATE_TOGGLE 2 -void _ui_state_modify(lv_obj_t * target, int32_t state, int value); - -#define UI_MOVE_CURSOR_UP 0 -#define UI_MOVE_CURSOR_RIGHT 1 -#define UI_MOVE_CURSOR_DOWN 2 -#define UI_MOVE_CURSOR_LEFT 3 -void _ui_textarea_move_cursor(lv_obj_t * target, int val) -; - - -void scr_unloaded_delete_cb(lv_event_t * e); - -void _ui_opacity_set(lv_obj_t * target, int val); - -/** Describes an animation*/ -typedef struct _ui_anim_user_data_t { - lv_obj_t * target; - lv_image_dsc_t ** imgset; - int32_t imgset_size; - int32_t val; -} ui_anim_user_data_t; -void _ui_anim_callback_free_user_data(lv_anim_t * a); - -void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v); - -void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v); - -void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v); - -void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v); - - -void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v); - - -void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v); - - -void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v); - - -void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v); - - -int32_t _ui_anim_callback_get_x(lv_anim_t * a); - -int32_t _ui_anim_callback_get_y(lv_anim_t * a); - -int32_t _ui_anim_callback_get_width(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_height(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_opacity(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a); - - -void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); - -void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); - -void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off); - -void _ui_spinbox_step(lv_obj_t * target, int val) -; - - -void _ui_switch_theme(int val) -; - - - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif + #endif + + #include "ui.h" + +#define _UI_TEMPORARY_STRING_BUFFER_SIZE 32 +#define _UI_BAR_PROPERTY_VALUE 0 +#define _UI_BAR_PROPERTY_VALUE_WITH_ANIM 1 +void _ui_bar_set_property(lv_obj_t * target, int id, int val); + +#define _UI_BASIC_PROPERTY_POSITION_X 0 +#define _UI_BASIC_PROPERTY_POSITION_Y 1 +#define _UI_BASIC_PROPERTY_WIDTH 2 +#define _UI_BASIC_PROPERTY_HEIGHT 3 +void _ui_basic_set_property(lv_obj_t * target, int id, int val); + +#define _UI_DROPDOWN_PROPERTY_SELECTED 0 +void _ui_dropdown_set_property(lv_obj_t * target, int id, int val); + +#define _UI_IMAGE_PROPERTY_IMAGE 0 +void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val); + +#define _UI_LABEL_PROPERTY_TEXT 0 +void _ui_label_set_property(lv_obj_t * target, int id, const char * val); + +#define _UI_ROLLER_PROPERTY_SELECTED 0 +#define _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM 1 +void _ui_roller_set_property(lv_obj_t * target, int id, int val); + +#define _UI_SLIDER_PROPERTY_VALUE 0 +#define _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM 1 +void _ui_slider_set_property(lv_obj_t * target, int id, int val); + +void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, + void (*target_init)(void)); + +void _ui_arc_increment(lv_obj_t * target, int val); + +void _ui_bar_increment(lv_obj_t * target, int val, int anm); + +void _ui_slider_increment(lv_obj_t * target, int val, int anm); + +void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea); + +#define _UI_MODIFY_FLAG_ADD 0 +#define _UI_MODIFY_FLAG_REMOVE 1 +#define _UI_MODIFY_FLAG_TOGGLE 2 +void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value); + +#define _UI_MODIFY_STATE_ADD 0 +#define _UI_MODIFY_STATE_REMOVE 1 +#define _UI_MODIFY_STATE_TOGGLE 2 +void _ui_state_modify(lv_obj_t * target, int32_t state, int value); + +#define UI_MOVE_CURSOR_UP 0 +#define UI_MOVE_CURSOR_RIGHT 1 +#define UI_MOVE_CURSOR_DOWN 2 +#define UI_MOVE_CURSOR_LEFT 3 +void _ui_textarea_move_cursor(lv_obj_t * target, int val) +; + + +void scr_unloaded_delete_cb(lv_event_t * e); + +void _ui_opacity_set(lv_obj_t * target, int val); + +/** Describes an animation*/ +typedef struct _ui_anim_user_data_t { + lv_obj_t *target; + lv_image_dsc_t **imgset; + int32_t imgset_size; + int32_t val; +} ui_anim_user_data_t; +void _ui_anim_callback_free_user_data(lv_anim_t * a); + +void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v); + + +int32_t _ui_anim_callback_get_x(lv_anim_t * a); + +int32_t _ui_anim_callback_get_y(lv_anim_t * a); + +int32_t _ui_anim_callback_get_width(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_height(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_opacity(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a); + + +void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); + +void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); + +void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off); + +void _ui_spinbox_step(lv_obj_t * target, int val) +; + + +void _ui_switch_theme(int val) +; + + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/main/Application/Tasks/GUI/Private/guiHelper.cpp b/main/Application/Tasks/GUI/Private/guiHelper.cpp index 4c739ce..e3eef3d 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.cpp +++ b/main/Application/Tasks/GUI/Private/guiHelper.cpp @@ -106,10 +106,10 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t #if CONFIG_LCD_BL >= 0 gpio_config_t bk_gpio_config = { .pin_bit_mask = 1ULL << CONFIG_LCD_BL, - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, }; ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); gpio_set_level(static_cast(CONFIG_LCD_BL), LCD_BK_LIGHT_ON_LEVEL); diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp index ef86936..ebc56d4 100644 --- a/main/Application/Tasks/GUI/guiTask.cpp +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -335,7 +335,7 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) /* Update visual rectangle on display (convert Lepton coords to display coords) */ ESP_LOGD(TAG, "Updating ROI rectangle - Start: (%ld,%ld), End: (%ld,%ld), Size: %ldx%ld", - ROI.x, ROI.y, ROI.x + ROI.w, ROI.y + ROI.h, ROI.w, ROI.h); + ROI.x, ROI.y, ROI.x + ROI.w, ROI.y + ROI.h, ROI.w, ROI.h); DisplayWidth = lv_obj_get_width(ui_Image_Thermal); DisplayHeight = lv_obj_get_height(ui_Image_Thermal); @@ -415,7 +415,8 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) .h = (uint16_t)ROI.h }; - esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_ROI, &SettingsLepton.ROI[ROI.Type], sizeof(App_Settings_ROI_t), portMAX_DELAY); + esp_event_post(GUI_EVENTS, GUI_EVENT_REQUEST_ROI, &SettingsLepton.ROI[ROI.Type], sizeof(App_Settings_ROI_t), + portMAX_DELAY); } /** @brief Create temperature gradient canvas for palette visualization. @@ -522,7 +523,7 @@ void Task_GUI(void *p_Parameters) App_Context = reinterpret_cast(p_Parameters); ESP_LOGD(TAG, "GUI Task started on core %d", xPortGetCoreID()); - /* Show splash screen first */ + /* Show splash screen first and wait for all components to become ready before starting the application. */ /* Initialization process: */ /* - Loading the settings */ /* - Waiting for the Lepton */ @@ -558,6 +559,8 @@ void Task_GUI(void *p_Parameters) GUI_Update_Info(); + esp_event_post(GUI_EVENTS, GUI_EVENT_APP_STARTED, NULL, 0, portMAX_DELAY); + _GUITask_State.RunTask = true; while (_GUITask_State.RunTask) { EventBits_t EventBits; @@ -572,6 +575,9 @@ void Task_GUI(void *p_Parameters) uint32_t Image_Height; char temp_buf[16]; + /* Reset watchdog before image processing */ + esp_task_wdt_reset(); + /* Scale from source (160x120) to destination (240x180) using bilinear interpolation */ dst = _GUITask_State.ThermalCanvasBuffer; Image_Width = lv_obj_get_width(ui_Image_Thermal); @@ -645,6 +651,9 @@ void Task_GUI(void *p_Parameters) } } + /* Reset watchdog after image processing */ + esp_task_wdt_reset(); + /* Max temperature (top of gradient) */ float temp_max_celsius = (LeptonFrame.Max / 100.0f) - 273.15f; snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_max_celsius); @@ -698,8 +707,8 @@ void Task_GUI(void *p_Parameters) /* Process the recieved system events */ EventBits = xEventGroupGetBits(_GUITask_State.EventGroup); if (EventBits & STOP_REQUEST) { - xEventGroupClearBits(_GUITask_State.EventGroup, STOP_REQUEST); + break; } else if (EventBits & BATTERY_VOLTAGE_READY) { char buf[8]; @@ -729,15 +738,15 @@ void Task_GUI(void *p_Parameters) xEventGroupClearBits(_GUITask_State.EventGroup, BATTERY_CHARGING_STATUS_READY); } else if (EventBits & WIFI_CONNECTION_STATE_CHANGED) { if (_GUITask_State.WiFiConnected) { - char ip_buf[16]; + char Buffer[16]; - snprintf(ip_buf, sizeof(ip_buf), "%lu.%lu.%lu.%lu", + snprintf(Buffer, sizeof(Buffer), "%lu.%lu.%lu.%lu", (_GUITask_State.IP_Info.IP >> 0) & 0xFF, (_GUITask_State.IP_Info.IP >> 8) & 0xFF, (_GUITask_State.IP_Info.IP >> 16) & 0xFF, (_GUITask_State.IP_Info.IP >> 24) & 0xFF); - lv_label_set_text(ui_Label_Info_IP, ip_buf); + lv_label_set_text(ui_Label_Info_IP, Buffer); lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0x00FF00), LV_PART_MAIN); lv_obj_remove_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); } else { @@ -748,6 +757,12 @@ void Task_GUI(void *p_Parameters) xEventGroupClearBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); } else if (EventBits & PROVISIONING_STATE_CHANGED) { + if ((_GUITask_State.WiFiConnected == false) && _GUITask_State.ProvisioningActive) { + lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0xFF8800), LV_PART_MAIN); + } else { + lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0xFF0000), LV_PART_MAIN); + } + xEventGroupClearBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); } else if (EventBits & SD_CARD_STATE_CHANGED) { ESP_LOGI(TAG, "SD card state changed: %s", _GUITask_State.CardPresent ? "present" : "removed"); diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp index 5516857..32e83b8 100644 --- a/main/Application/Tasks/Lepton/leptonTask.cpp +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -51,6 +51,7 @@ typedef struct { bool isInitialized; bool Running; bool RunTask; + bool ApplicationStarted; TaskHandle_t TaskHandle; EventGroupHandle_t EventGroup; uint8_t *RGB_Buffer[2]; @@ -74,6 +75,13 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int ESP_LOGD(TAG, "GUI event received: ID=%d", ID); switch (ID) { + case GUI_EVENT_APP_STARTED: { + ESP_LOGD(TAG, "Application started event received"); + + _LeptonTask_State.ApplicationStarted = true; + + break; + } case GUI_EVENT_REQUEST_ROI: { memcpy(&_LeptonTask_State.ROI, p_Data, sizeof(App_Settings_ROI_t)); @@ -146,25 +154,17 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGD(TAG, " Part number: %s", DeviceInfo.PartNumber); ESP_LOGD(TAG, " Serial number: %s", DeviceInfo.SerialNumber); - /* Wait for Lepton to stabilize after configuration */ - ESP_LOGD(TAG, "Waiting for Lepton to stabilize..."); - for (uint8_t i = 0; i < 50; i++) { - esp_task_wdt_reset(); - vTaskDelay(100 / portTICK_PERIOD_MS); - } + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_READY, &DeviceInfo, sizeof(App_Lepton_Device_t), portMAX_DELAY); - /* Wait for initial warm-up period */ - ESP_LOGD(TAG, "Waiting for initial warm-up period..."); - for (uint8_t i = 0; i < 50; i++) { + while (_LeptonTask_State.ApplicationStarted == false) { esp_task_wdt_reset(); vTaskDelay(100 / portTICK_PERIOD_MS); } - esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_READY, &DeviceInfo, sizeof(App_Lepton_Device_t), portMAX_DELAY); - Lepton_FluxLinearParams_t FluxParams; Lepton_GetFluxLinearParameters(&_LeptonTask_State.Lepton, &FluxParams); - ESP_LOGI(TAG, "Flux Linear Parameters - Scene Emissivity: %u, TBkgK: %u, TauWindow: %u, TWindowK: %u, TauAtm: %u, TAtmK: %u, ReflWindow: %u, TReflK: %u", + ESP_LOGI(TAG, + "Flux Linear Parameters - Scene Emissivity: %u, TBkgK: %u, TauWindow: %u, TWindowK: %u, TauAtm: %u, TAtmK: %u, ReflWindow: %u, TReflK: %u", FluxParams.SceneEmissivity, FluxParams.TBkgK, FluxParams.TauWindow, @@ -179,6 +179,13 @@ static void Task_Lepton(void *p_Parameters) if (Lepton_StartCapture(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrameQueue) != LEPTON_ERR_OK) { ESP_LOGE(TAG, "Can not start image capturing!"); esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); + + /* Critical error - cannot continue without capture task */ + _LeptonTask_State.Running = false; + _LeptonTask_State.TaskHandle = NULL; + esp_task_wdt_delete(NULL); + vTaskDelete(NULL); + return; } _LeptonTask_State.RunTask = true; @@ -229,7 +236,8 @@ static void Task_Lepton(void *p_Parameters) _LeptonTask_State.RawFrame.Height, static_cast(ImageSize)); } else { /* RAW14: Convert to RGB */ - Lepton_Raw14ToRGB(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrame.Image_Buffer, WriteBuffer, &Min, &Max, _LeptonTask_State.RawFrame.Width, + Lepton_Raw14ToRGB(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrame.Image_Buffer, WriteBuffer, &Min, &Max, + _LeptonTask_State.RawFrame.Width, _LeptonTask_State.RawFrame.Height); } @@ -269,8 +277,8 @@ static void Task_Lepton(void *p_Parameters) ROI.Start_Row = _LeptonTask_State.ROI.y; ROI.End_Col = _LeptonTask_State.ROI.x + _LeptonTask_State.ROI.w - 1; ROI.End_Row = _LeptonTask_State.ROI.y + _LeptonTask_State.ROI.h - 1; - - switch(_LeptonTask_State.ROI.Type) { + + switch (_LeptonTask_State.ROI.Type) { case ROI_TYPE_SPOTMETER: { Error = Lepton_SetSpotmeterROI(&_LeptonTask_State.Lepton, &ROI); break; @@ -353,12 +361,16 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGD(TAG, "Crosshair center in Lepton Frame: (%d,%d), size (%d,%d)", x, y, _LeptonTask_State.RawFrame.Width, _LeptonTask_State.RawFrame.Height); - if (Lepton_GetPixelTemperature(&_LeptonTask_State.Lepton, - _LeptonTask_State.RawFrame.Image_Buffer[(y * _LeptonTask_State.RawFrame.Width) + x], - &Temperature) == LEPTON_ERR_OK) { - esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE, &Temperature, sizeof(float), 0); + if (_LeptonTask_State.RawFrame.Image_Buffer != NULL) { + if (Lepton_GetPixelTemperature(&_LeptonTask_State.Lepton, + _LeptonTask_State.RawFrame.Image_Buffer[(y * _LeptonTask_State.RawFrame.Width) + x], + &Temperature) == LEPTON_ERR_OK) { + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE, &Temperature, sizeof(float), 0); + } else { + ESP_LOGW(TAG, "Failed to get pixel temperature!"); + } } else { - ESP_LOGW(TAG, "Failed to get pixel temperature!"); + ESP_LOGW(TAG, "Image buffer is NULL, cannot get pixel temperature"); } xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index a777c26..ea696a1 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -36,21 +36,22 @@ #include "Application/Manager/managers.h" #include "Application/Tasks/GUI/guiTask.h" -#define NETWORK_TASK_STOP_REQUEST BIT0 -#define NETWORK_TASK_BROADCAST_FRAME BIT1 -#define NETWORK_TASK_PROV_SUCCESS BIT2 -#define NETWORK_TASK_WIFI_CONNECTED BIT3 -#define NETWORK_TASK_WIFI_DISCONNECTED BIT4 -#define NETWORK_TASK_PROV_TIMEOUT BIT5 -#define NETWORK_TASK_OPEN_WIFI_REQUEST BIT6 -#define NETWORK_TASK_SNTP_TIMEZONE_SET BIT7 -#define NETWORK_TASK_WIFI_CREDENTIALS_UPDATED BIT8 +#define NETWORK_TASK_STOP_REQUEST BIT0 +#define NETWORK_TASK_BROADCAST_FRAME BIT1 +#define NETWORK_TASK_PROV_SUCCESS BIT2 +#define NETWORK_TASK_WIFI_CONNECTED BIT3 +#define NETWORK_TASK_WIFI_DISCONNECTED BIT4 +#define NETWORK_TASK_OPEN_WIFI_REQUEST BIT5 +#define NETWORK_TASK_PROV_TIMEOUT BIT6 +#define NETWORK_TASK_SNTP_TIMEZONE_SET BIT7 +#define NETWORK_TASK_WIFI_CREDENTIALS_UPDATED BIT8 typedef struct { bool isInitialized; bool isConnected; bool Running; bool RunTask; + bool ApplicationStarted; TaskHandle_t TaskHandle; EventGroupHandle_t EventGroup; uint32_t StartTime; @@ -125,7 +126,6 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, case NETWORK_EVENT_PROV_SUCCESS: { ESP_LOGD(TAG, "Provisioning success"); - /* Signal task to handle WiFi restart with new credentials */ xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); break; @@ -138,7 +138,6 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, case NETWORK_EVENT_PROV_TIMEOUT: { ESP_LOGW(TAG, "Provisioning timeout - stopping provisioning"); - /* Stop provisioning in task context (not timer context) */ Provisioning_Stop(); break; @@ -156,6 +155,28 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, } } +/** @brief GUI event handler for task coordination. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + switch (ID) { + case GUI_EVENT_APP_STARTED: { + ESP_LOGD(TAG, "Application started event received"); + + _NetworkTask_State.ApplicationStarted = true; + + break; + } + default: { + break; + } + } +} + /** @brief Network task main loop. * @param p_Parameters Pointer to App_Context_t structure */ @@ -167,54 +188,41 @@ static void Task_Network(void *p_Parameters) ESP_LOGD(TAG, "Network task started on core %d", xPortGetCoreID()); + while (_NetworkTask_State.ApplicationStarted == false) { + esp_task_wdt_reset(); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + SettingsManager_GetWiFi(&WiFiSettings); ESP_LOGI(TAG, "Autoconnect is %s", (WiFiSettings.AutoConnect) ? "enabled" : "disabled"); - if (WiFiSettings.AutoConnect == false) { - do { - EventBits_t EventBits; - - esp_task_wdt_reset(); - EventBits = xEventGroupGetBits(_NetworkTask_State.EventGroup); - if (EventBits & NETWORK_TASK_OPEN_WIFI_REQUEST) { + /* If autoconnect is disabled, wait for explicit WiFi open request in main loop */ + bool WaitingForWiFiRequest = (WiFiSettings.AutoConnect == false); - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); - break; - } - - vTaskDelay(100 / portTICK_PERIOD_MS); - } while (true); - } - - if ((Provisioning_isProvisioned() == false) && - (strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0)) { - ESP_LOGI(TAG, "No credentials found, starting provisioning"); + if (WaitingForWiFiRequest == false) { + /* Check if WiFi credentials are available */ + if (strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0) { + ESP_LOGW(TAG, "No credentials found, starting provisioning"); - Provisioning_Start(); + Provisioning_Start(); - _NetworkTask_State.State = NETWORK_STATE_PROVISIONING; + _NetworkTask_State.State = NETWORK_STATE_PROVISIONING; + } else { + ESP_LOGD(TAG, "Credentials found, connecting to WiFi"); + NetworkManager_StartSTA(); + } } else { - NetworkManager_StartSTA(); + ESP_LOGD(TAG, "Waiting for WiFi open request..."); + _NetworkTask_State.State = NETWORK_STATE_IDLE; } _NetworkTask_State.RunTask = true; while (_NetworkTask_State.RunTask) { - uint32_t NotificationValue = 0; EventBits_t EventBits; esp_task_wdt_reset(); - /* Check for task notifications (from timer callbacks) */ - if (xTaskNotifyWait(0, 0xFFFFFFFF, &NotificationValue, 0) == pdTRUE) { - if (NotificationValue & 0x01) { - /* Provisioning timeout notification */ - ESP_LOGW(TAG, "Provisioning timeout"); - - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); - } - } - EventBits = xEventGroupGetBits(_NetworkTask_State.EventGroup); if (EventBits & NETWORK_TASK_STOP_REQUEST) { ESP_LOGD(TAG, "Stop request received"); @@ -225,18 +233,21 @@ static void Task_Network(void *p_Parameters) break; } else if (EventBits & NETWORK_TASK_WIFI_CONNECTED) { - ESP_LOGD(TAG, "Handling WiFi connection"); - /* Notify Time Manager that network is available */ TimeManager_OnNetworkConnected(); - if (NetworkManager_StartServer(&_NetworkTask_State.AppContext->Server_Config) == ESP_OK) { - ESP_LOGI(TAG, "HTTP/WebSocket server started"); + /* Ensure we have valid server config */ + if (_NetworkTask_State.AppContext->Server_Config.HTTP_Server.Port == 0) { + ESP_LOGW(TAG, "Server config port is 0, using default 8080"); + _NetworkTask_State.AppContext->Server_Config.HTTP_Server.Port = 8080; + } + if (NetworkManager_StartServer(&_NetworkTask_State.AppContext->Server_Config) == ESP_OK) { + ESP_LOGD(TAG, "HTTP/WebSocket server started on port %d", + _NetworkTask_State.AppContext->Server_Config.HTTP_Server.Port); esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SERVER_STARTED, NULL, 0, portMAX_DELAY); } else { ESP_LOGE(TAG, "Failed to start HTTP/WebSocket server"); - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SERVER_ERROR, NULL, 0, portMAX_DELAY); } @@ -247,31 +258,45 @@ static void Task_Network(void *p_Parameters) /* Notify Time Manager that network is unavailable */ TimeManager_OnNetworkDisconnected(); - Provisioning_Start(); + /* Only start provisioning if not already active and we have no credentials */ + if ((Provisioning_isActive() == false) && strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0) { + Provisioning_Start(); + } xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_DISCONNECTED); } else if (EventBits & NETWORK_TASK_PROV_SUCCESS) { - ESP_LOGD(TAG, "Handling provisioning success"); + ESP_LOGI(TAG, "Provisioning success - stopping provisioning and connecting to WiFi"); + /* Reset watchdog before potentially long operation */ + esp_task_wdt_reset(); + + /* Stop provisioning (HTTP server on port 80 and DNS) */ Provisioning_Stop(); - /* Restart WiFi in STA mode with new credentials */ - NetworkManager_Stop(); + ESP_LOGI(TAG, "Provisioning stopped, starting WiFi STA connection"); + + /* Reset watchdog after provisioning stop */ + esp_task_wdt_reset(); + + /* Connect to WiFi with the new credentials */ NetworkManager_StartSTA(); + ESP_LOGI(TAG, "WiFi STA connection initiated"); + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); } else if (EventBits & NETWORK_TASK_PROV_TIMEOUT) { - ESP_LOGW(TAG, "Handling provisioning timeout"); + ESP_LOGD(TAG, "Handling provisioning timeout"); + esp_task_wdt_reset(); Provisioning_Stop(); - - /* Post event for GUI */ - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_TIMEOUT, NULL, 0, portMAX_DELAY); + esp_task_wdt_reset(); xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); } else if (EventBits & NETWORK_TASK_SNTP_TIMEZONE_SET) { App_Settings_System_t SystemSettings; + ESP_LOGD(TAG, "Handling timezone set request"); + SettingsManager_GetSystem(&SystemSettings); memcpy(&SystemSettings.Timezone, _NetworkTask_State.Timezone, sizeof(SystemSettings.Timezone)); @@ -281,6 +306,26 @@ static void Task_Network(void *p_Parameters) SettingsManager_Save(); xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); + } else if (EventBits & NETWORK_TASK_OPEN_WIFI_REQUEST) { + ESP_LOGD(TAG, "Handling WiFi open request"); + + /* Start WiFi connection if we were waiting */ + if (WaitingForWiFiRequest) { + if ((Provisioning_isProvisioned() == false) && + (strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0)) { + ESP_LOGW(TAG, "No credentials found, starting provisioning"); + + Provisioning_Start(); + + _NetworkTask_State.State = NETWORK_STATE_PROVISIONING; + } else { + NetworkManager_StartSTA(); + } + + WaitingForWiFiRequest = false; + } + + xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); } else if (EventBits & NETWORK_TASK_WIFI_CREDENTIALS_UPDATED) { App_Settings_WiFi_t WiFiSettings; @@ -314,6 +359,7 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) esp_err_t Error; App_Settings_WiFi_t WiFiSettings; App_Settings_Provisioning_t ProvisioningSettings; + App_Settings_VISA_Server_t VISASettings; if (p_AppContext == NULL) { return ESP_ERR_INVALID_ARG; @@ -334,7 +380,7 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) } if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to init NVS flash: %d!", Error); + ESP_LOGE(TAG, "Failed to init NVS flash: 0x%x!", Error); return Error; } @@ -345,9 +391,8 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) return ESP_ERR_NO_MEM; } - /* Register event handler for network events */ - Error = esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL); - if (Error != ESP_OK) { + if ((esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL) != ESP_OK) || + (esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL) != ESP_OK)) { ESP_LOGE(TAG, "Failed to register event handler: %d!", Error); vEventGroupDelete(_NetworkTask_State.EventGroup); @@ -364,21 +409,23 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) _NetworkTask_State.AppContext->STA_Config.MaxRetries = WiFiSettings.MaxRetries; _NetworkTask_State.AppContext->STA_Config.RetryInterval = WiFiSettings.RetryInterval; + /* Copy the required VISA settings from settings to network config */ + SettingsManager_GetVISAServer(&VISASettings); + _NetworkTask_State.AppContext->Server_Config.VISA_Server.Port = VISASettings.Port; + /* Copy the required Provisioning settings from settings to network config */ SettingsManager_GetProvisioning(&ProvisioningSettings); strncpy(_NetworkTask_State.AppContext->Prov_Config.Name, ProvisioningSettings.Name, sizeof(_NetworkTask_State.AppContext->Prov_Config.Name) - 1); - strncpy(_NetworkTask_State.AppContext->Prov_Config.PoP, - ProvisioningSettings.PoP, - sizeof(_NetworkTask_State.AppContext->Prov_Config.PoP) - 1); _NetworkTask_State.AppContext->Prov_Config.Timeout = ProvisioningSettings.Timeout; Error = NetworkManager_Init(&_NetworkTask_State.AppContext->STA_Config); if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to init WiFi manager: %d!", Error); + ESP_LOGE(TAG, "Failed to init WiFi manager: 0x%x!", Error); esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); + esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); vEventGroupDelete(_NetworkTask_State.EventGroup); return Error; @@ -386,7 +433,7 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) Error = Provisioning_Init(&_NetworkTask_State.AppContext->Prov_Config); if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to init provisioning: %d!", Error); + ESP_LOGE(TAG, "Failed to init provisioning: 0x%x!", Error); /* Continue anyway, provisioning is optional */ } @@ -405,13 +452,14 @@ void Network_Task_Deinit(void) return; } - ESP_LOGI(TAG, "Deinitializing Network Task"); + ESP_LOGD(TAG, "Deinitializing Network Task"); Network_Task_Stop(); Provisioning_Deinit(); NetworkManager_Deinit(); esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); + esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); if (_NetworkTask_State.EventGroup != NULL) { vEventGroupDelete(_NetworkTask_State.EventGroup); @@ -448,8 +496,6 @@ esp_err_t Network_Task_Start(void) return ESP_ERR_NO_MEM; } - /* Register task handle with provisioning for timeout notification */ - Provisioning_SetNetworkTaskHandle(_NetworkTask_State.TaskHandle); _NetworkTask_State.Running = true; _NetworkTask_State.StartTime = xTaskGetTickCount() * portTICK_PERIOD_MS / 1000; @@ -462,7 +508,7 @@ esp_err_t Network_Task_Stop(void) return ESP_OK; } - ESP_LOGI(TAG, "Stopping Network Task"); + ESP_LOGD(TAG, "Stopping Network Task"); xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_STOP_REQUEST); diff --git a/main/Application/application.h b/main/Application/application.h index 37b369a..0276f9c 100644 --- a/main/Application/application.h +++ b/main/Application/application.h @@ -68,6 +68,7 @@ enum { */ enum { GUI_EVENT_INIT_DONE, /**< GUI task initialization done. */ + GUI_EVENT_APP_STARTED, /**< Application has started. */ GUI_EVENT_REQUEST_ROI, /**< Update the ROI rectangle on the GUI. Data is transmitted in a App_Settings_ROI_t structure. */ GUI_EVENT_REQUEST_FPA_AUX_TEMP, /**< Request update of the FPA and AUX temperature. */ @@ -136,10 +137,10 @@ typedef struct { /** @brief Application context aggregating shared resources. */ typedef struct { - QueueHandle_t Lepton_FrameEventQueue; /**< Queue for Lepton frame ready events. */ - Network_WiFi_STA_Config_t STA_Config; /**< WiFi STA configuration. */ - Network_Provisioning_Config_t Prov_Config; /**< Network provisioning configuration. */ - Server_Config_t Server_Config; /**< Server configuration. */ + QueueHandle_t Lepton_FrameEventQueue; /**< Queue for Lepton frame ready events. */ + Network_WiFi_STA_Config_t STA_Config; /**< WiFi STA configuration. */ + Network_Provisioning_Config_t Prov_Config; /**< Network provisioning configuration. */ + Network_Server_Config_t Server_Config; /**< Server configuration. */ } App_Context_t; #endif /* APPLICATION_H_ */ \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 9b3552b..dbf45a7 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -2,10 +2,10 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/main/*.*) idf_component_register(SRCS ${app_sources} REQUIRES esp_http_server esp_timer esp_wifi json nvs_flash driver + EMBED_TXTFILES "../webserver/provision.html" + EMBED_TXTFILES "../LICENSE" ) -target_add_binary_data(${COMPONENT_TARGET} "../LICENSE" TEXT) - target_compile_definitions(${COMPONENT_LIB} PUBLIC PYROVISION_VERSION_MAJOR=1 PYROVISION_VERSION_MINOR=0 diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 3dd3f78..d11ddf4 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -1,9 +1,15 @@ menu "PyroVision" + menu "Device" + config DEVICE_MANUFACTURER + string "Device manufacturer" + default "PyroVision" + endmenu + menu "Network" menu "Task" config NETWORK_TASK_STACKSIZE int "Stack size" - default 8192 + default 6144 config NETWORK_TASK_PRIO int "Task prio" @@ -15,17 +21,6 @@ menu "PyroVision" endmenu menu "VISA" - config NETWORK_VISA_DEVICE_MANUFACTURER - string "Device manufacturer" - default "PyroVision" - - config NETWORK_VISA_DEVICE_MODEL - string "Device model" - default "PyroVision" - - config NETWORK_VISA_DEVICE_SERIAL - string "Device manufacturer" - default "0000001" endmenu endmenu @@ -223,7 +218,7 @@ menu "PyroVision" menu "Task" config GUI_TASK_STACKSIZE int "Stack size" - default 8192 + default 32768 config GUI_TASK_PRIO int "Task prio" diff --git a/platformio.ini b/platformio.ini index 033e746..9d3540e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,6 +28,7 @@ board_build.partitions = partitions.csv board_build.filesystem = littlefs board_build.embed_txtfiles = LICENSE + webserver/provision.html debug_tool = esp-builtin debug_port = /dev/ttyUSB0 @@ -38,6 +39,7 @@ upload_port = ${sysenv.PIO_UPLOAD_PORT, /dev/ttyUSB0} monitor_speed = 115200 monitor_filters = esp32_exception_decoder monitor_port = ${sysenv.PIO_UPLOAD_PORT, /dev/ttyUSB0} + [env:debug] build_type = debug build_flags = diff --git a/sdkconfig.debug b/sdkconfig.debug index e6c33d3..8c7f16e 100644 --- a/sdkconfig.debug +++ b/sdkconfig.debug @@ -595,6 +595,12 @@ CONFIG_PARTITION_TABLE_MD5=y # PyroVision # +# +# Device +# +CONFIG_DEVICE_MANUFACTURER="PyroVision" +# end of Device + # # Network # @@ -610,10 +616,6 @@ CONFIG_NETWORK_TASK_CORE=1 # # VISA # -CONFIG_NETWORK_VISA_DEVICE_MANUFACTURER="PyroVision" -CONFIG_NETWORK_VISA_DEVICE_MODEL="PyroVision" -CONFIG_NETWORK_VISA_DEVICE_SERIAL="0000001" -# end of VISA # end of Network # @@ -704,7 +706,7 @@ CONFIG_GUI_LVGL_TICK_PERIOD_MS=2 # # Task # -CONFIG_GUI_TASK_STACKSIZE=8192 +CONFIG_GUI_TASK_STACKSIZE=32768 CONFIG_GUI_TASK_PRIO=2 CONFIG_GUI_TASK_CORE=0 # end of Task @@ -785,295 +787,15 @@ CONFIG_APPTRACE_LOCK_ENABLE=y # # Bluetooth # -CONFIG_BT_ENABLED=y -# CONFIG_BT_BLUEDROID_ENABLED is not set -CONFIG_BT_NIMBLE_ENABLED=y -# CONFIG_BT_CONTROLLER_ONLY is not set -CONFIG_BT_CONTROLLER_ENABLED=y -# CONFIG_BT_CONTROLLER_DISABLED is not set - -# -# NimBLE Options -# -# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL is not set -# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL is not set -CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT=y -# CONFIG_BT_NIMBLE_LOG_LEVEL_NONE is not set -# CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR is not set -# CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING is not set -CONFIG_BT_NIMBLE_LOG_LEVEL_INFO=y -# CONFIG_BT_NIMBLE_LOG_LEVEL_DEBUG is not set -CONFIG_BT_NIMBLE_LOG_LEVEL=1 -CONFIG_BT_NIMBLE_MAX_CONNECTIONS=3 -CONFIG_BT_NIMBLE_MAX_BONDS=3 -CONFIG_BT_NIMBLE_MAX_CCCDS=8 -CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=0 -CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=y -# CONFIG_BT_NIMBLE_PINNED_TO_CORE_1 is not set -CONFIG_BT_NIMBLE_PINNED_TO_CORE=0 -CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=4096 -CONFIG_BT_NIMBLE_ROLE_CENTRAL=y -CONFIG_BT_NIMBLE_ROLE_PERIPHERAL=y -CONFIG_BT_NIMBLE_ROLE_BROADCASTER=y -CONFIG_BT_NIMBLE_ROLE_OBSERVER=y -CONFIG_BT_NIMBLE_GATT_CLIENT=y -CONFIG_BT_NIMBLE_GATT_SERVER=y -CONFIG_BT_NIMBLE_NVS_PERSIST=y -# CONFIG_BT_NIMBLE_SMP_ID_RESET is not set -CONFIG_BT_NIMBLE_SECURITY_ENABLE=y -CONFIG_BT_NIMBLE_SM_LEGACY=y -CONFIG_BT_NIMBLE_SM_SC=y -# CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS is not set -CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION=y -CONFIG_BT_NIMBLE_SM_LVL=0 -CONFIG_BT_NIMBLE_SM_SC_ONLY=0 -CONFIG_BT_NIMBLE_PRINT_ERR_NAME=y -# CONFIG_BT_NIMBLE_DEBUG is not set -# CONFIG_BT_NIMBLE_DYNAMIC_SERVICE is not set -CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="nimble" -CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31 -CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=256 -CONFIG_BT_NIMBLE_ATT_MAX_PREP_ENTRIES=64 -CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE=0 - -# -# Memory Settings -# -CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=12 -CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE=256 -CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT=24 -CONFIG_BT_NIMBLE_MSYS_2_BLOCK_SIZE=320 -CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=24 -CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE=255 -CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=70 -CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT=30 -CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT=8 -CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT=1 -# end of Memory Settings - -CONFIG_BT_NIMBLE_GATT_MAX_PROCS=4 -# CONFIG_BT_NIMBLE_HS_FLOW_CTRL is not set -CONFIG_BT_NIMBLE_RPA_TIMEOUT=900 -# CONFIG_BT_NIMBLE_MESH is not set -CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS=y -CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS=2000 -CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=y -CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT=3 -# CONFIG_BT_NIMBLE_HANDLE_REPEAT_PAIRING_DELETION is not set -CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=y -CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY=y -CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY=y -# CONFIG_BT_NIMBLE_EXT_ADV is not set -CONFIG_BT_NIMBLE_EXT_SCAN=y -CONFIG_BT_NIMBLE_ENABLE_PERIODIC_SYNC=y -CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS=0 -# CONFIG_BT_NIMBLE_GATT_CACHING is not set -# CONFIG_BT_NIMBLE_INCL_SVC_DISCOVERY is not set -CONFIG_BT_NIMBLE_WHITELIST_SIZE=12 -# CONFIG_BT_NIMBLE_TEST_THROUGHPUT_TEST is not set -CONFIG_BT_NIMBLE_BLUFI_ENABLE=y -CONFIG_BT_NIMBLE_USE_ESP_TIMER=y -CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE=y -# CONFIG_BT_NIMBLE_BLE_GATT_BLOB_TRANSFER is not set - -# -# BLE Services -# -CONFIG_BT_NIMBLE_PROX_SERVICE=y -CONFIG_BT_NIMBLE_ANS_SERVICE=y -CONFIG_BT_NIMBLE_CTS_SERVICE=y -CONFIG_BT_NIMBLE_HTP_SERVICE=y -CONFIG_BT_NIMBLE_IPSS_SERVICE=y -CONFIG_BT_NIMBLE_TPS_SERVICE=y -CONFIG_BT_NIMBLE_IAS_SERVICE=y -CONFIG_BT_NIMBLE_LLS_SERVICE=y -CONFIG_BT_NIMBLE_SPS_SERVICE=y -CONFIG_BT_NIMBLE_HR_SERVICE=y -# CONFIG_BT_NIMBLE_HID_SERVICE is not set -CONFIG_BT_NIMBLE_BAS_SERVICE=y -# CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY is not set -CONFIG_BT_NIMBLE_DIS_SERVICE=y -# CONFIG_BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME is not set -# CONFIG_BT_NIMBLE_SVC_DIS_SERIAL_NUMBER is not set -# CONFIG_BT_NIMBLE_SVC_DIS_HARDWARE_REVISION is not set -# CONFIG_BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION is not set -# CONFIG_BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION is not set -# CONFIG_BT_NIMBLE_SVC_DIS_SYSTEM_ID is not set -# CONFIG_BT_NIMBLE_SVC_DIS_PNP_ID is not set -# CONFIG_BT_NIMBLE_SVC_DIS_INCLUDED is not set -CONFIG_BT_NIMBLE_GAP_SERVICE=y - -# -# GAP Appearance write permissions -# -# CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE is not set -CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM=0 -CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC=0 -CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN=0 -CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR=0 -# end of GAP Appearance write permissions - -CONFIG_BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP=y -# CONFIG_BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP is not set -# CONFIG_BT_NIMBLE_SVC_GAP_CAR_SUPP is not set -CONFIG_BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION=-1 - -# -# GAP device name write permissions -# -# CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE is not set -# end of GAP device name write permissions - -# -# PPCP settings -# -CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL=0 -CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL=0 -CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY=0 -CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO=0 -# end of PPCP settings - -CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM=0 -CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC=0 -CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN=0 -CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR=0 -# CONFIG_BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL is not set -# CONFIG_BT_NIMBLE_SVC_GAP_RPA_ONLY is not set -# end of BLE Services - -# CONFIG_BT_NIMBLE_VS_SUPPORT is not set -# CONFIG_BT_NIMBLE_ENC_ADV_DATA is not set -# CONFIG_BT_NIMBLE_HIGH_DUTY_ADV_ITVL is not set -# CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN is not set -# CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK is not set -# CONFIG_BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT is not set - -# -# Host-controller Transport -# -CONFIG_UART_HW_FLOWCTRL_DISABLE=y -# CONFIG_UART_HW_FLOWCTRL_CTS_RTS is not set -CONFIG_BT_NIMBLE_HCI_UART_FLOW_CTRL=0 -CONFIG_BT_NIMBLE_HCI_UART_RTS_PIN=19 -CONFIG_BT_NIMBLE_HCI_UART_CTS_PIN=23 -# end of Host-controller Transport - -CONFIG_BT_NIMBLE_EATT_CHAN_NUM=0 -# CONFIG_BT_NIMBLE_SUBRATE is not set -# end of NimBLE Options - -# -# Controller Options -# -CONFIG_BT_CTRL_MODE_EFF=1 -CONFIG_BT_CTRL_BLE_MAX_ACT=6 -CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=6 -CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 -CONFIG_BT_CTRL_PINNED_TO_CORE_0=y -# CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set -CONFIG_BT_CTRL_PINNED_TO_CORE=0 -CONFIG_BT_CTRL_HCI_MODE_VHCI=y -# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set -CONFIG_BT_CTRL_HCI_TL=1 -CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30 -CONFIG_BT_BLE_CCA_MODE_NONE=y -# CONFIG_BT_BLE_CCA_MODE_HW is not set -# CONFIG_BT_BLE_CCA_MODE_SW is not set -CONFIG_BT_BLE_CCA_MODE=0 -CONFIG_BT_CTRL_HW_CCA_VAL=20 -CONFIG_BT_CTRL_HW_CCA_EFF=0 -CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y -# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set -# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set -CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0 -CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y -# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set -CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0 -CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y -# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set -CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0 -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set -CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9=y -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set -# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P20 is not set -CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=11 -CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y -CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 -CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 -CONFIG_BT_CTRL_BLE_SCAN_DUPL=y -CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE=y -# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA is not set -# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE is not set -CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0 -CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100 -CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD=0 -# CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN is not set -# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set -CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y -CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0 - -# -# MODEM SLEEP Options -# -# CONFIG_BT_CTRL_MODEM_SLEEP is not set -# end of MODEM SLEEP Options - -CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 -CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 -CONFIG_BT_CTRL_HCI_TL_EFF=1 -# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set -# CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set -# CONFIG_BT_BLE_ADV_DATA_LENGTH_ZERO_AUX is not set -CONFIG_BT_CTRL_CHAN_ASS_EN=y -CONFIG_BT_CTRL_LE_PING_EN=y - -# -# BLE disconnects when Instant Passed (0x28) occurs -# -# CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE is not set -# CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE is not set -# CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE is not set -# end of BLE disconnects when Instant Passed (0x28) occurs - -# CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY is not set -CONFIG_BT_CTRL_DTM_ENABLE=y -CONFIG_BT_CTRL_BLE_MASTER=y -# CONFIG_BT_CTRL_BLE_TEST is not set -CONFIG_BT_CTRL_BLE_SCAN=y -CONFIG_BT_CTRL_BLE_SECURITY_ENABLE=y -CONFIG_BT_CTRL_BLE_ADV=y -# CONFIG_BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS is not set - -# -# Controller debug log Options (Experimental) -# -# end of Controller debug log Options (Experimental) -# end of Controller Options +# CONFIG_BT_ENABLED is not set # # Common Options # -CONFIG_BT_ALARM_MAX_NUM=50 # CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set # end of Common Options - -# CONFIG_BT_HCI_LOG_DEBUG_EN is not set # end of Bluetooth -# CONFIG_BLE_MESH is not set - # # Console Library # @@ -1202,8 +924,7 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y # Wireless Coexistence # CONFIG_ESP_COEX_ENABLED=y -CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y -# CONFIG_ESP_COEX_POWER_MANAGEMENT is not set +# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set # CONFIG_ESP_COEX_GPIO_DEBUG is not set # end of Wireless Coexistence @@ -1211,6 +932,7 @@ CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y # Common ESP-related # # CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set +CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y # end of Common ESP-related # @@ -1345,13 +1067,8 @@ CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y # # Ethernet # -CONFIG_ETH_ENABLED=y -CONFIG_ETH_USE_SPI_ETHERNET=y -# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set -# CONFIG_ETH_SPI_ETHERNET_W5500 is not set -# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_SPI_ETHERNET is not set # CONFIG_ETH_USE_OPENETH is not set -# CONFIG_ETH_TRANSMIT_MUTEX is not set # end of Ethernet # @@ -1618,16 +1335,15 @@ CONFIG_SPIRAM_SPEED=80 CONFIG_SPIRAM_BOOT_HW_INIT=y CONFIG_SPIRAM_BOOT_INIT=y CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y -# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set # CONFIG_SPIRAM_USE_MEMMAP is not set # CONFIG_SPIRAM_USE_CAPS_ALLOC is not set CONFIG_SPIRAM_USE_MALLOC=y CONFIG_SPIRAM_MEMTEST=y CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 -# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 -# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set -# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y # end of SPI RAM config # end of ESP PSRAM @@ -1777,10 +1493,10 @@ CONFIG_ESP_TIMER_IMPL_SYSTIMER=y CONFIG_ESP_WIFI_ENABLED=y CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10 CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32 -# CONFIG_ESP_WIFI_STATIC_TX_BUFFER is not set -CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER=y -CONFIG_ESP_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=32 CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y # CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 @@ -1790,6 +1506,7 @@ CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP_WIFI_TX_BA_WIN=6 CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP_WIFI_RX_BA_WIN=6 +# CONFIG_ESP_WIFI_AMSDU_TX_ENABLED is not set CONFIG_ESP_WIFI_NVS_ENABLED=y CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y # CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set @@ -1816,7 +1533,6 @@ CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y # CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y -CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y # CONFIG_ESP_WIFI_WAPI_PSK is not set # CONFIG_ESP_WIFI_SUITE_B_192 is not set # CONFIG_ESP_WIFI_11KV_SUPPORT is not set @@ -1834,8 +1550,7 @@ CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y # CONFIG_ESP_WIFI_DEBUG_PRINT is not set # CONFIG_ESP_WIFI_TESTING_OPTIONS is not set -CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y -# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set +# CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT is not set # end of Wi-Fi # @@ -2056,7 +1771,7 @@ CONFIG_LOG_IN_IRAM=y # LWIP # CONFIG_LWIP_ENABLE=y -CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +CONFIG_LWIP_LOCAL_HOSTNAME="PyroVision" CONFIG_LWIP_TCPIP_TASK_PRIO=18 # CONFIG_LWIP_TCPIP_CORE_LOCKING is not set # CONFIG_LWIP_CHECK_THREAD_SAFETY is not set @@ -2140,6 +1855,7 @@ CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 CONFIG_LWIP_TCP_OVERSIZE_MSS=y # CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set # CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# CONFIG_LWIP_WND_SCALE is not set CONFIG_LWIP_TCP_RTO_TIME=1500 # end of TCP @@ -2684,11 +2400,6 @@ CONFIG_WL_SECTOR_SIZE=4096 # CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 -# CONFIG_WIFI_PROV_BLE_BONDING is not set -CONFIG_WIFI_PROV_BLE_SEC_CONN=y -# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set -# CONFIG_WIFI_PROV_BLE_NOTIFY is not set -# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y # CONFIG_WIFI_PROV_STA_FAST_SCAN is not set # end of Wi-Fi Provisioning Manager @@ -2736,7 +2447,7 @@ CONFIG_LEPTON_VOSPI_FRAME_BUFFERS=2 # CONFIG_LEPTON_CAPTURE_TASK_CORE_AFFINITY=y CONFIG_LEPTON_CAPTURE_TASK_CORE=0 -CONFIG_LEPTON_CAPTURE_TASK_STACK=8192 +CONFIG_LEPTON_CAPTURE_TASK_STACK=6144 CONFIG_LEPTON_CAPTURE_TASK_PRIORITY=12 # end of Capture Task @@ -2761,30 +2472,28 @@ CONFIG_CU_DIAGNOSTICS_COLOR_ALWAYS=y # # Camera configuration # -CONFIG_OV7670_SUPPORT=y -CONFIG_OV7725_SUPPORT=y -CONFIG_NT99141_SUPPORT=y -CONFIG_OV2640_SUPPORT=y -CONFIG_OV3660_SUPPORT=y +# CONFIG_OV7670_SUPPORT is not set +# CONFIG_OV7725_SUPPORT is not set +# CONFIG_NT99141_SUPPORT is not set +# CONFIG_OV2640_SUPPORT is not set +# CONFIG_OV3660_SUPPORT is not set CONFIG_OV5640_SUPPORT=y -CONFIG_GC2145_SUPPORT=y -CONFIG_GC032A_SUPPORT=y -CONFIG_GC0308_SUPPORT=y -CONFIG_BF3005_SUPPORT=y -CONFIG_BF20A6_SUPPORT=y +# CONFIG_GC2145_SUPPORT is not set +# CONFIG_GC032A_SUPPORT is not set +# CONFIG_GC0308_SUPPORT is not set +# CONFIG_BF3005_SUPPORT is not set +# CONFIG_BF20A6_SUPPORT is not set # CONFIG_SC101IOT_SUPPORT is not set -CONFIG_SC030IOT_SUPPORT=y +# CONFIG_SC030IOT_SUPPORT is not set # CONFIG_SC031GS_SUPPORT is not set -CONFIG_HM1055_SUPPORT=y -CONFIG_HM0360_SUPPORT=y -CONFIG_MEGA_CCM_SUPPORT=y +# CONFIG_HM1055_SUPPORT is not set +# CONFIG_HM0360_SUPPORT is not set +# CONFIG_MEGA_CCM_SUPPORT is not set # CONFIG_SCCB_HARDWARE_I2C_DRIVER_LEGACY is not set CONFIG_SCCB_HARDWARE_I2C_DRIVER_NEW=y # CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set CONFIG_SCCB_HARDWARE_I2C_PORT1=y CONFIG_SCCB_CLK_FREQ=100000 -# CONFIG_GC_SENSOR_WINDOWING_MODE is not set -CONFIG_GC_SENSOR_SUBSAMPLE_MODE=y CONFIG_CAMERA_TASK_STACK_SIZE=4096 CONFIG_CAMERA_CORE0=y # CONFIG_CAMERA_CORE1 is not set @@ -3270,49 +2979,8 @@ CONFIG_STACK_CHECK_NONE=y # CONFIG_ESP32_APPTRACE_DEST_TRAX is not set CONFIG_ESP32_APPTRACE_DEST_NONE=y CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y -# CONFIG_BLUEDROID_ENABLED is not set -CONFIG_NIMBLE_ENABLED=y -# CONFIG_NIMBLE_MEM_ALLOC_MODE_INTERNAL is not set -# CONFIG_NIMBLE_MEM_ALLOC_MODE_EXTERNAL is not set -CONFIG_NIMBLE_MEM_ALLOC_MODE_DEFAULT=y -CONFIG_NIMBLE_MAX_CONNECTIONS=3 -CONFIG_NIMBLE_MAX_BONDS=3 -CONFIG_NIMBLE_MAX_CCCDS=8 -CONFIG_NIMBLE_L2CAP_COC_MAX_NUM=0 -CONFIG_NIMBLE_PINNED_TO_CORE_0=y -# CONFIG_NIMBLE_PINNED_TO_CORE_1 is not set -CONFIG_NIMBLE_PINNED_TO_CORE=0 -CONFIG_NIMBLE_TASK_STACK_SIZE=4096 -CONFIG_BT_NIMBLE_TASK_STACK_SIZE=4096 -CONFIG_NIMBLE_ROLE_CENTRAL=y -CONFIG_NIMBLE_ROLE_PERIPHERAL=y -CONFIG_NIMBLE_ROLE_BROADCASTER=y -CONFIG_NIMBLE_ROLE_OBSERVER=y -CONFIG_NIMBLE_NVS_PERSIST=y -CONFIG_NIMBLE_SM_LEGACY=y -CONFIG_NIMBLE_SM_SC=y -# CONFIG_NIMBLE_SM_SC_DEBUG_KEYS is not set -CONFIG_BT_NIMBLE_SM_SC_LVL=0 -# CONFIG_NIMBLE_DEBUG is not set -CONFIG_NIMBLE_SVC_GAP_DEVICE_NAME="nimble" -CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31 -CONFIG_NIMBLE_ATT_PREFERRED_MTU=256 -CONFIG_NIMBLE_SVC_GAP_APPEARANCE=0 -CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT=12 -CONFIG_BT_NIMBLE_ACL_BUF_COUNT=24 -CONFIG_BT_NIMBLE_ACL_BUF_SIZE=255 -CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 -CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=30 -CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8 -# CONFIG_NIMBLE_HS_FLOW_CTRL is not set -CONFIG_NIMBLE_RPA_TIMEOUT=900 -# CONFIG_NIMBLE_MESH is not set -CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS=y -# CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EN is not set -CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS=y -CONFIG_SW_COEXIST_ENABLE=y -CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y -CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y +# CONFIG_EXTERNAL_COEX_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set # CONFIG_GPTIMER_ISR_IRAM_SAFE is not set # CONFIG_MCPWM_ISR_IRAM_SAFE is not set # CONFIG_EVENT_LOOP_PROFILING is not set @@ -3389,15 +3057,16 @@ CONFIG_TIMER_TASK_STACK_SIZE=3584 CONFIG_ESP32_WIFI_ENABLED=y CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 -# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y -CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32 # CONFIG_ESP32_WIFI_CSI_ENABLED is not set CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=6 +# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set CONFIG_ESP32_WIFI_NVS_ENABLED=y CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y # CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set @@ -3408,7 +3077,6 @@ CONFIG_ESP32_WIFI_RX_IRAM_OPT=y CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y CONFIG_WPA_MBEDTLS_CRYPTO=y -CONFIG_WPA_MBEDTLS_TLS_CLIENT=y # CONFIG_WPA_WAPI_PSK is not set # CONFIG_WPA_SUITE_B_192 is not set # CONFIG_WPA_11KV_SUPPORT is not set diff --git a/ui/PyroVision.sll b/ui/PyroVision.sll index 71c9a09..c5a6be7 100644 --- a/ui/PyroVision.sll +++ b/ui/PyroVision.sll @@ -12,7 +12,7 @@ "board": "ESP WROVER KIT", "board_version": "2.0.0", "editor_version": "1.5.4", - "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQBLa273V3Dbx/flkVF+pOK7q8Phvw9J/Z76SupXMQxNIz7FDegOCTXJ+Hf+Rn0n/r8h/9DFXtf/5GPU/+vuX/ANDNbQfLDmtrcpaK5q/274d/6FGD/wACT/8AE1d1GbS9J+yfbvBUEX2u2S6g/wBMDb4nztbgHGcHg81xte1XGh2L/wDCP+Kdej36Fo/hyyaWIxM/2mVt4SMdAcMVJyccqCMMSF7aXZfcv8gucPp02l6t9r+w+CoJfsls91P/AKYF2RJjc3IGcZHA5ql/bvh3/oUYP/Ak/wDxNei2+h2Kf8JB4p0GPZoWseHL1oohEyfZpV2B4z1AywYjBxwwAwoJ8Vo9tLsvuX+QXOusz4b8Qyf2emkrptzKMQyK+9S3oTgEVwt1bva3c1vJ9+KRkb6g4rc0D/kY9M/6+4v/AEMVR8Rf8jPq3/X5N/6Gac3zQ5ra3B6q5reF9KsGsLrWdVBa0t3ESxqATI5GcDP1FaB1rw4DgeE4COxNwef/AB2qdn/yTc/9hf8A9o1kVTlyJKKW3ZP8x7HTQ6poVxPHBB4OjlmkYIkaTszMxOAAAvJJrQ+z2n/CQ/2D/wAIGv8AanmeV9m+0HOeuc7cbcc7s4xznHNRfDqGK31q71+6jR7XRLSS8KyqNkkuNsUe48KxY5U4JyvA9O98+P7d/wALO+yw+V/YO/z8v5f9pZ8nZs3btv8AB/dxznPNT7aXZfcv8guebzapoVvPJBP4OjimjYo8bzsrKwOCCCvBBpg1rw4Tg+E4AO5FweP/AB2tH4lwWs3iGDXtOH/Ev1q2S7jKxhQr/dkQlSQXBGW7gtz6ni6PbS7L7l/kFzT8UaVYLYWus6UCtpcOYmjYAGNwM4OPoa5u1t3uruG3j+/LIqL9ScV1F5/yTcf9hf8A9o1i+Hf+Rn0n/r8h/wDQxROKc1bS9hNanWXh8N+HpP7PfSV1K5iGJpGfYob0BwSarf274d/6FGD/AMCT/wDE1la//wAjHqf/AF9y/wDoZrPpzqtSaSVvRDbPRtB0M+JrF73SPAEFzbpIYmf+0ETDAAkYbB6MPzo17Qz4ZsUvdX8AQW1u8giV/wC0EfLEEgYXJ6Kfyrk/B3/I76B/2Erf/wBGLR4x/wCR31//ALCVx/6Map9tLsvuX+Qrlv8At3w7/wBCjB/4En/4mrNmfDfiGT+z00ldNuZRiGRX3qW9CcAiuRrQ0D/kY9M/6+4v/QxVQqtySaVvRDTMO6t3tbua3k+/FIyN9QcV0nhfSrBrC61nVQWtLdxEsagEyORnAz9RWT4i/wCRn1b/AK/Jv/QzW1Z/8k3P/YX/APaNKEUpu+triS1Lh1rw4DgeE4COxNwef/Hams7/AES/vreztvB8ElxcSLFEn2rG5mOAMlcDk965atrwf/yO2g/9hG3/APRi0e2l2X3L/IdzZiXT59eOhw+B45NSEzQGBLrJDqSGGQMYGDk5wACc4qreX+iWF9cWdz4PgjuLeRopU+1Z2spwRkLg8jtXf2t74Lg8ea1ZWx1e31/Ubm4s47+dEaO1ndnUtFsIYZY4BPOMcqCxryHUrGXS9Uu9PnZGmtZngdkJKllYqcZxxkUe2l2X3L/ILmyNa8OE4PhOADuRcHj/AMdrP8UaVYLYWus6UCtpcOYmjYAGNwM4OPoazK17z/km4/7C/wD7RqlLnTUktuyX5BuclRRRXOQFFFFABRRRQAUUUUAFFFFAFiwumsdQtrxFDNBKsoB7lSD/AErs7/w/Lr95LqmgtHdwXLGVo/NVZImPJDAkd64SitITSXLJXQ0zsv8AhB/Ef/QO/wDI8f8A8VXSeJIPF/iHStG0s6Y9vY6baRwCAXcbLJIq7TKeRyRgAHOOcHk15TRTvS/lf3r/ACHdHq3huDxf4e0rWdLGmPcWOpWkkBgN3GqxyMu0Sjk8gZBAxnjJ4Fc3/wAIP4j/AOgd/wCR4/8A4quNoovS7P7/APgBdHd2Hh+XQLyLVNeaO0gtmEqx+arSSsOQFAJ71xl/dNfahc3jqFaeVpSB2LEn+tV6KU5prlirITZ1fhy4tr/Q7nQJ7iO3macXNrJKcIz7dpUntkdKt/8ACE+Ie1gGHYiaPB/8eriaKpVItJTW3nb9GO/c9Tt9N8SWvgq88PQaIiNeXaz3F0J4t0kagbYiOuAw3A59Rjk5meHxbJ4Aj8KNpriGO789ZVuo1Bj5PlFQfmG8l8knnHHAryaijmpfyv7/APgBdHqdxpviS68FWfh6fREdrO7ae3ujPFujjYHdEB1wWO4nPoMcDGF/whPiHvYBR3JmjwP/AB6uJoo5qX8r+/8A4AXR1fiO4trDQ7bQILiO4mWc3N1JEcor7doUHvgda5ywumsdQtrxFDNBKsoB7lSD/Sq9FRKblK60E2d3f+H5dfvJdU0Fo7uC5YytH5qrJEx5IYEjvVb/AIQfxH/0Dv8AyPH/APFVxtFW505O7i7+v/AHdHrXhXSZ9A8qe+8Ef2lqEFyJ4Lr+1RD5e3aVGwEg4YE5PrijxVpM+v8Amz2Pgj+zdQnuTPPdf2qJvM3biw2EgDLEHI9MV5LRS5qX8r+9f5BdHZf8IP4j/wCgd/5Hj/8Aiqs2Hh+XQLyLVNeaO0gtmEqx+arSSsOQFAJ71wlFNTpxd1F39f8AgBdFi/umvtQubx1CtPK0pA7FiT/Wuj8OXFtf6Hc6BPcR28zTi5tZJThGfbtKk9sjpXKUVEZuMrvUSZ23/CE+Ie1gGHYiaPB/8eq7o/hjxFpOt2Gpf2V5v2S5jn8v7RGu/YwbGcnGcdcV55RV81L+V/f/AMAd0e7G4Eery61bfDeFdWaR50uJtX81FmbJ3mM4BwTnAx7EHBHC3nhTxRf31xeXNl5lxcSNLK/mxDczHJOAcDk9q4Oijmpfyv7/APgBdHbf8IT4h72AUdyZo8D/AMeqp4juLaw0O20CC4juJlnNzdSRHKK+3aFB74HWuUoodSKTUFv53/RBfsFFFFYkhRRRQAUUUUAek3XgrR4vF+oaUhf7Tb3E8/2Pedi2oLbFDZ3FwoRzycq3qprAt9L0i60hRHLaJfNpAlXzbsRj7R9sKkfMwAbyR909ucZ5rnTf3hvXvTdzm7dmZp/MO9iepLdSTk5+tRyTyzLEssrusS7IwzEhFyTgegyScepNAy9r0Nlbap5NiY2ijggV2jk3qZREnmkNk5Hmb+nHpxis2iigR2HhvRtKs9DufE2vMz2sR2xQqN24k4ACngsSG68ADNX4dV065uGih8CLxCk5eS+gRVjcAoWYxbRkEcE57Vm6lEZ/hLp8SlFZ9UiUF2CqCRcDkngD3NRal9nv7KXR4tQsEukisH3tcp5Unl25jdRJnblWb155rScpKbinZK22m8U366sxhCNRc0tdX+Da/Q2YNS0+e8uLQeAwk1t/rvNvIY1j7DLNCAM9uee1Nl1fSoGkSXwMUkjmWBozcxbt7AkADycnODyOPzFZV5NaarZXOk21/aCeH7JieWURx3PlQmNsM2BwTxnqKi/tSztfGemXJlWa3shbRSzoCQ5jRVZxxzgjj1wKXPP+Z/eyvYU+x0N/e6XpkayXfglERmKblvIXAYdVJWI4b2PNVB4i8Nk/8imv/gRH/wDGay7iGPStAu7SS9tLqa6uYnjW3lEgCoHy5I6Z3AAHB68VkJ1o55/zP72HsKfY68a74bP/ADKi/wDf+P8A+M1KuseG2P8AyKy/9/4//jNcmnUfWrMfWjnn/M/vYewp9jp11Pw2xH/FLr/3+j/+NVIt74bb/mWV/wC/0f8A8arnY+oqzH1/Cjnn/M/vY/YU+xvLceG2/wCZbX/v7H/8aqRX8Nt/zLi/9/I//jVYsfX8Ksx9KOef8z+9i9hT7Gqq+Gz/AMy8v/fyP/41Uq2/htv+ZfX/AL7j/wDjVZqd60YLuWO3MKeWF3bt3lruB46NjI6etHPP+Z/ew9hT7FpNK0B4JJh4dHlxkKx3x8E5x/yz9jVp/DejRQiWTw4qqcZ+eLK56ZHl5GferVxrdzPaCQXTsszKJ4WlPBHXaM/dYHkYxnj0qadokbUbr7TFKl0CIlVssdzhuR2wB370c8/5n97H7Cn2KcPhbRZ2dU8PplH2NmSEDd6AlOT9Ki/sDw4GKtogVh1B8vI/8h1oW6Ld6bBCs8UTxSuzCR9uQwX5h69OnXpS3kyXF/PNH9x3JB9RnrRzz/mf3sPYU+xRHh3w2f8AmDr/AOQ//jdSjwx4bP8AzCV/KP8A+N1ZToPpVlaOef8AM/vYewp9iiPCXhsnH9lL+Uf/AMRUo8G+Gyf+QYv/AHzH/wDEVpJ94fWrCdR9aOef8z+9h7Cn2MlfBHhtj/yDl/74j/8AiKkXwH4bb/mHr/3xH/8AEVtx9asp1FHPP+Z/ew9hT7GAvw98Nt/y4r/37j/+IqRfhx4bb/lyX/v3H/8AEV0cdWY+v4Uc8/5n97D2FPscuvwz8Nt/y6L/AN+o/wD4mpV+F3htv+XVf+/Mf/xNdjAB5Y+6CWwSwzmp1AUEherHr/Kjnn/M/vYewp9ji1+FHhth/wAe6/8AfmP/AOJqO6+GGkWEBu7GytJpIxny7i1jdX9sba79AAxHYE06Xm1l/wB0/wAqipVqQg5KTul6/gxqhT6I+QfGcVlD4svU063Fva/u2WEdEJjUsB7bice1YNbfi7/kaLz/AIB/6AtYlbYiKjVlFdG/zJpSc6cZPqkFFFFYmgVreFbaG98X6La3MYkgmv4I5EboymRQQfwNZNbXg448b6Af+olb/wDoxaAPsSMxxRrHGoRFGFVQAAPQCneaKo+b7mjzfc1RZ89fHS0tbXx9C9tCkRuLFJpdoxvfe67j74UflXmVen/HVt3jeyOf+Yan/oyWvMKklnVax/yR+z/7CUf8rmuCT7orvdY/5I/Z/wDYSj/lc1wSfdFXU/iy/wC3f/SImVD4PnL/ANKZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hVmPpVaPr+FWY+lAFhO9Wo+n41VTvVqPp+NAFiPp+NWU+6KrR9Pxqyn3RQBYT7oqynQfSqyfdFWU6D6UAWU6D6VZWqydB9KsrQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FIC3C7KMA8delTxswzz71Wj6GrEfegCzGT196klObWX/dP8qjj6fjUkn/AB6y/wC6f5VnX/hS9H+Q1ufH3i7/AJGi8/4B/wCgLWJW34u/5Gi8/wCAf+gLWJXViv48/V/mcuH/AIMPRfkFFFFYGwVs+EjjxnoR9NQt/wD0YtY1a/hU48YaIf8Ap/g/9GLQB9Xed9KPO+lUfOo86qLPEvjc27xnZn/qHp/6MkrzWvRPjM27xhaH/pwT/wBGSV53Uks6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETKh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8Ksx9KALCd6tR9PxqqnerUfT8aALEfT8asp90VWj6fjVlPuigCwn3RVlOg+lVk+6Ksp0H0oAsp0H0qytVk6D6VZWgCyn3h9asJ1H1qun3h9asJ1H1oAsx9asp1FVo+tWU6imMsR1Zj6/hVaOrMfX8KQFmPoasR96rx9DViPvQBZj6fjUkn/AB6y/wC6f5VHH0/GpJP+PWX/AHT/ACrOv/Cl6P8AIa3Pj7xd/wAjRef8A/8AQFrErb8Xf8jRef8AAP8A0BaxK6sV/Hn6v8zlw/8ABh6L8gooorA2CtXwwceLNGPpfQf+jFrKrY8JRef4z0OHdt8zULdc4zjMiigD6R84+9HnH3rZ/wCEVb/n+/8AIP8A9ej/AIRVv+f7/wAg/wD16ZR8+fF5t3iy1P8A04p/6MkrgK9J+NmnnTfGdnCZfN3aejZ27f8AlpIPX2rzakI6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETKh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8K1NJ0271e9js7KEyzv0A7D1J7CgBid6tR9PxrvbX4S3BhBudXjjkPVY4C4H4lh/Kra/CnaP+Q1/wCSv/2dAHn8fT8asp90V3a/C3aP+Qz/AOSv/wBnUi/DPaP+Qv8A+S3/ANnQBxCfdFWU6D6V2S/DjaP+Qr/5L/8A2VSj4e4H/IU/8l//ALKgDkU6D6VZWtPVPC15pURmDLPAv3nUYK/UVmLQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf8AhS9H+Q1ufH3i7/kaLz/gH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBWt4VNyPF+imzEZuhfweSJc7C/mLt3Y5xnGaya3fBX/I+eHf8AsJ23/o1aAPpfzviL/wA+3hz/AL6m/wAaPO+Iv/Pt4c/76m/xrsaKZR8u/GRtabxfaHXUskuvsCbRZltmzzJMZ3c5zn9K88r0/wCPF5b3fj6BbeZZDb2CQy7Tna4kkJX64YV5hSEdVrH/ACR+z/7CUf8AK5rgk+6K73WP+SP2f/YSj/lc1wSfdFXU/iy/7d/9IiZUPg+cv/SmWU6D6VYToPpVdOg+lWE6D6VBqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4V7H8IbGJdIvtQ2gzPP5O7uFVQ382/QV45H1/CvbfhH/wAipc/9fr/+gR0AXvFPi2907V7TQ9DskvdWuBvKyE7I09Tgj0PcYA96YJviKRn7L4dHsWl/xrOtefjle57WAx/3yleh0Acd53xF/wCfbw5/31N/jR53xF/59vDn/fU3+NdjRQBx3nfEX/n28Of99S/41y2qfEfxXo+sNpk9hpNxcINzpaiR8DGSPvcEAZ6cV1HjXxbNpzR6Hoi/aNdvPljRBnyQf4j2zjpnp1PHWbwx4OtvDekzPPtudTuI2N1ctyWJ5KgnnH8+p9AAbOhavB4j0C21KOIpFcocxvzgglWHuMg/WvPruEW9/cwL92OVkH0BIrqPhp/yT3SvpL/6Neub1T/kMX3/AF8Sf+hGgBqfeH1qwnUfWq6feH1qwnUfWgCzH1qynUVWj61ZTqKYyxHVmPr+FVo6sx9fwpAWY+hqxH3qvH0NWI+9AFmPp+NSSf8AHrL/ALp/lUcfT8akk/49Zf8AdP8AKs6/8KXo/wAhrc+PvF3/ACNF5/wD/wBAWsStvxd/yNF5/wAA/wDQFrErqxX8efq/zOXD/wAGHovyCiiisDYK3fBX/I+eHf8AsJ23/o1awq2/BjKnjnw+zMFVdStiSTgAeatAH2VXFeMvFVzb3Mfh3w+vn63dfKdvP2dSPvH0OOfYcntl/i7xsmmKmmaLsvdaujsijjIcR5/ib39B+J4qz4N8Ir4etpLu8k+06xd/Pc3DHJBPJUH0z1Pc/hhlHz58U/DieGPEOn2XnNPPJp6TXEpOd0hkkBI9uBXDV6t+0B/yPlj/ANgyP/0bLXlNIR1Wsf8AJH7P/sJR/wArmuCT7orvdY/5I/Z/9hKP+VzXBJ90VdT+LL/t3/0iJlQ+D5y/9KZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hXtvwj/5FS5/6/X/APQI68Sj6/hXtvwj/wCRUuf+v1//AECOgDA1jX4PDnxmlvLoH7M8KQysOSisi/N+BA/DNen3+rafpmky6reXcUVjFH5jTlsrtPTGOucjAHJJAGc15pqugWXiT4wX1hf+Z5P2MP8Au2wQQigH8M5rA8XSat4c8J6t4Kvle6t5lSTTbkcZVZVYr+QPHUHjkEUAdxZ+OPFmq2qX2l/D+aawny1vLPqkULyR5+VijDIyOe454JGDWdcfFt55tR02z0C+ttURoorSC8QrK7OpJLx4+XHGBk7tw6c1pal8W/DcHhmLU7C9hnurhf3Vm7hZEbv5i5yoB/PsSDmuA8DaVr/ivxfret2/iH+ztQRLeQzSaesxdZUJG0SY2gKoAIHIPBx1AO00Czbwl4m0W31OD7brfiH7S0940v8Ax7+WgfaBj5s5wTkdO4r0W4/49pf9w/yry+bS9d034peC/wC2/Ef9seZ9u8r/AEJLfysQfN90/NnI69Me9eoXH/HtL/uH+VAHL/DP/knul/SX/wBGvXN6p/yGL7/r4k/9CNdJ8M/+Se6X9Jf/AEa9c3qn/IYvv+viT/0I0ANT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf+FL0f5DW58feLv+RovP8AgH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBWr4XtItQ8W6NZT58m4voIn2nB2tIoOPwNZVbngshfHfh4kgAanbEk/8AXVaAPqrQPBmieG3aWwtf37DBmlbc+PQHt+Fb9Rfabf8A57xf99ij7Tb/APPeL/vsUyj5m+N2qR6l8QWSJGUWdslsSf4mDOxP/j2PwrzivT/jvFbJ4+gktwmZrCOSVkOdzb5FyffCr+VeYUhHVax/yR+z/wCwlH/K5rgk+6K73WP+SP2f/YSj/lc1wSfdFXU/iy/7d/8ASImVD4PnL/0pllOg+lWE6D6VXToPpVhOg+lQalkVZTrVYVZTrTAsJ1H1qzH1qsnUfWrMfWgZZj6irMfX8KrR9RVmPr+FAFiPr+Fe2/CP/kVLn/r9f/0COvEo+v4V7b8I/wDkVLn/AK/X/wDQI6AIbT/kuV9/14D/ANBSu01fRdP12yNpqVsk8RORngqfUEcg1wt1cw6L8aPtN+4ggvbMJFK5wucAcntyuPxFeiC6tyMieLH++KAOV034YeEdNleUaRDdSP3u1EoH4EY/HGa6G10ewstVv9Tt4Nl5qHl/aZN7HzPLXanBOBgHsB71Z+02/wDz3i/77FH2m3/57xf99igDz7xlqF3deNtNstEsbebWdOgkuIZ53Ybd67WRRkKSVA5b8MVt+DPFEnirwzPc3EKxXUDNFKE+6x25BHp16e1WNc8OaNrszXE04iuWt2tzNFIMlD2OfTtTLeLQfBPhaaGG4jjto1Z2Z5AXlcj9ScAce1AEPwz/AOSe6X9Jf/Rr1zeqf8hi+/6+JP8A0I10nw0GPh7pWfSX/wBGvXN6p/yGL7/r4k/9CNADU+8PrVhOo+tV0+8PrVhOo+tAFmPrVlOoqtH1qynUUxliOrMfX8KrR1Zj6/hSAsx9DViPvVePoasR96ALMfT8akk/49Zf90/yqOPp+NSSf8esv+6f5VnX/hS9H+Q1ufH3i7/kaLz/AIB/6AtYlbfi7/kaLz/gH/oC1iV1Yr+PP1f5nLh/4MPRfkFFFFYGwVq+GbOLUfFej2UxYRXF9BC5U4O1nAOPfmsqrel3U1jq9leW77J4J0ljbAO1lYEHB4PIoA+nP+FQeGv+el//AN/l/wDiaP8AhUHhr/npf/8Af5f/AImvMP8AhaXjD/oLj/wGi/8AiKP+FpeMP+guP/AaL/4imUYvxd8N2PhfxXa2Vg0zRPYpMTKwY7i8g7AcfKK4Guh8Y6/qXiLV4rzVLn7ROkAiVvLVMKGY4woA6k1z1IR1Wsf8kfs/+wlH/K5rgk+6K73WP+SP2f8A2Eo/5XNcEn3RV1P4sv8At3/0iJlQ+D5y/wDSmWU6D6VYToPpVdOg+lWE6D6VBqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4V6p8J9dgt/tOjTuEeZxNASfvNgBl+uAMfjXlcfX8KtREqQykgjBBHagD6M1zw9pniOzFtqdsJVU5RgcMh9iOlcqfhD4aJ4e/H0mH/AMTXC2njjxLbQiKPVZCo6eYiSH82BNXU8e+JiOdS7/8APCP/AOJoA63/AIVB4a/56X//AH+X/wCJo/4VB4a/56X/AP3+X/4muYTx14kI51Hv/wA8I/8A4mp08beISBnUP/IMf/xNAHQf8Kg8Nf8APXUP+/y//E1NbfCjwvbzLI8VzOFOdks3yn64Arn08Za+QM3/AP5Bj/8AiamXxdrpHN92/wCeSf8AxNAHpE01ppGnbiEht4U2qigAADooFeZTTNcXMszcNI5c/UnNR3Wo3moOHu7h5SOgJ4H0HQULQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf+FL0f5DW58feLv+RovP8AgH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBUkBxPGf9ofzqOnIcSKfcUAbXmj1o80etUvOHqaPOHqaBkeoNunU/7P8AU1UqW4bdID7VFQI6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETOh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8Ksx9KALCd6tR9PxqqnerUfT8aALEfT8asp90VWj6fjVlPuigCwn3RVlOg+lVk+6Ksp0H0oAsp0H0qytVk6D6VZWgCyn3h9asJ1H1qun3h9asJ1H1oAsx9asp1FVo+tWU6imMsR1Zj6/hVaOrMfX8KQFmPoasR96rx9DViPvQBZj6fjUkn/AB6y/wC6f5VHH0/GpJP+PWX/AHT/ACrOv/Cl6P8AIa3Pj7xd/wAjRef8A/8AQFrErb8Xf8jRef8AAP8A0BaxK6sV/Hn6v8zlw/8ABh6L8gooorA2CjOOfSimucIx9jQA/wA76Ued9Ko+b7Ueb7Uxl3du5oqKBtyE+9S0hHVax/yR+z/7CUf8rmuCT7orvdY/5I/Z/wDYSj/lc1wSfdFXU/iy/wC3f/SImdD4PnL/ANKZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hVmPpVaPr+FWY+lAFhO9Wo+n41VTvVqPp+NAFiPp+NWU+6KrR9Pxqyn3RQBYT7oqynQfSqyfdFWU6D6UAWU6D6VZWqydB9KsrQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/wB0/wAqjj6fjUkn/HrL/un+VZ1/4UvR/kNbnx94u/5Gi8/4B/6AtYlbfi7/AJGi8/4B/wCgLWJXViv48/V/mcuH/gw9F+QUUUVgbBTXUsjKOpBFOq9ounf2xr2naZ5vk/bLqK38zbu2b2C5xkZxnpmgDn/s1x/d/wDHhR9muP7v/jwrsl8JXi6aL6aWNIzavcbV+ZkIAZVccbSysGHXIPscWn8J2I06K8TWfNRri3t38qFZMGVHbIVZC/BQjBVSew4xQM4+2jeOLD9Sc1NWnr2jtoOpHT5phJcxopm2rhFY8gKf4hgjnA5JxkYJzKBHVax/yR+z/wCwlH/K5rgk+6K9A1SKSX4OwMilhFqEbvj+Ff365P4so/EV5+n3RVVP4sv+3f8A0iJnR+D5y/8ASmWU6D6VYToPpVdOg+lWE6D6VJqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4VZj6VWj6/hVmPpQBYTvVqPp+NVU71aj6fjQBYj6fjVlPuiq0fT8asp90UAWE+6Ksp0H0qsn3RVlOg+lAFlOg+lWVqsnQfSrK0AWU+8PrVhOo+tV0+8PrVhOo+tAFmPrVlOoqtH1qynUUxliOrMfX8KrR1Zj6/hSAsx9DViPvVePoasR96ALMfT8akk/49Zf90/yqOPp+NPmYLaSliANp5P0rOv8Awpej/Ia3Pj/xd/yNF5/wD/0BaxK2/F3/ACNF5/wD/wBAWsSurFfx5+r/ADObD/wYei/IKKKKwNQq3peoS6Tq1lqUCo01pOk8ayAlSyMGAOCDjI9aqUUAbEXibU431ZjKsn9qoUuQ68HJzuAHQjkD0BI6Gqp1rVWS2RtTvStrzADO2IuMfLz8vHHFUaKAJJJ5ZljWWV3WJdkYZidi5JwPQZJOPc1HRRQB0XhnxVLoiz2d1Al3ps4IeFwGwD1G08EHAOOMHmrp1PwIWLf8IsQSc8STAfl51chRV8yfxJN/12sZumm7ptHYDVfAo6eF2/7+zf8Ax6nDWfBA6eGG/wC/s3/x6uNopXj/AC/i/wDMXsv7zO1/tzwV/wBCy3/fyX/49Th4g8GDp4bb/v5L/wDHq4iii8f5fxf+Yez/ALzO5HiTweOnhxv++5f/AI9Th4o8Ijp4db/vuT/49XCUUXj/AC/i/wDMPZv+ZnejxX4THTw83/fUn/x6njxf4VHTw+3/AH1J/wDHq8/oovH+X8X/AJh7N/zM9CHjPwwOmgN+cn/x2nDxv4aHTQW/N/8A47XndFF4/wAv4v8AzD2b/mZ6MPHXhwdNCb83/wDjtOHj7w+OmiN/4/8A/Ha83oovH+X8X/mHs3/Mz0ofELQR00Vv/H//AI7Tx8RdDHTRm/Jv/jteZUUXj/L+L/zD2b/mZ6ePiToo6aO35N/8dpw+JukDppDf98t/8dry6ii8f5fxf+Y/Zv8AmZ6mPihpQ6aS3/fLf/Had/wtTTB/zCm/75P/AMcryqii8f5fxf8AmHs3/Mz1gfFjTx00tv8Avg//ABynD4uWI6aY3/fB/wDjleS0UXj/AC/i/wDMPZv+Znrg+MFmOmnN/wB+/wD7ZTh8Y7YdNPb/AL9//bK8hoovH+X8X/mHs3/Mz2AfGeAdLBv+/X/2ynD41xDpYt/36/8AtleO0UXj/L+L/wAw9m/5meyj43KOlk3/AH5H/wAcpw+OWOlm3/fkf/F14xRReP8AL+L/AMw9m/5me0j47MOlo3/fkf8AxdRz/GmHUU+z3q3kNs3EhtoE3EenL141RT5o78q/F/m7B7Lu395reJtXh13xDd6jb232aCQqscWclVVQgye5IUE+5NZNFFS227s0CiiikAqKXdUXqxwKtfYc3ZhEo2gZEmOD6fqcVDbyCGUSEElQduPXHFP+0j7GIgCJAcbv9kc4/M1lPnv7v9f8MehhVhVC9bV79enT/t5vfdW8yuQQcHrVhYI/Kjd5HBfOAsee+PWo53WSZnUEBjkj37/rVmG6VIYl86eMpnIQcHnPrRNy5U0LC06HtZxqNNLb715rpfqVZozDM8ZIJU4yKIozLIEBA6kk9AB1NJK4eV3C7QzEgelOhl8qTcRuUgqwzjIIxV+9y+ZgvZOvr8F/wv8AeLIkSrmOYuc4IKYqKpZPIC/ujITn+IAYFRUR2JrpKeiS9Ltfi2FFFFUYhRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV1uj+ELG/XTBd6zJbS6jaSXFvGlqJC7rK8flAmRRuOzIyRknHXGeSrrbzUfC15Bpdi82si3sLRoluVt4lfeZnkOY95BGHx98HigZmvpuiC8MI1u4iRZVRmubAoyrtYsSqu3IIVQM87u2DV8+DP7QjtJvD+oLfQXLTIDdKtoyNEqu+QzlcbWByG9c4xUOs65p2t63cPLBJBZzyxM915QkusJHsJ+8qkufnYZ69+ObniXxTBd3mi32k6jqj3unxBGkuYliUFCNjIiu4BI+8OASM45NAFbU/B40fTbG9vdWs9t3BK4W2mjnIkUuFUbHOVYoAXHClsHkU1fDWn3un3Umk6017e2kCzywG0aNGUsqnY5bLEFxwVXPOKraprVrcaibi0tc2727oLS5BaO1eQHf5QDcKGYsvTBPIOMnX1HxTYy+H4LbTbu8s5kt7ZJLSLToI4pZIwu5nmVt7Aspf5lPOOnUAFTVvCVvp0Gpxw6qbjUNJC/boDbFEXLrGdj7jvw7KDlV65GRXL12ninxjF4hsZ2S7vo5rqUSz2jW8Xl5yTjzgQ7qCflDDjjniuLoA2PD2jwaxcXguruW2gtbVrl2hgEzkKVGApZf73r2qXWNBtrLSLTVbC9muLS4mkgAubbyJA6BScKGYFcMOQevUCpPCGtwaFf3ss91fWn2ize3S4sVDSxMWU7hl1/unv3qXxV4hg1m0022ju9R1CS080vfaiAJZA5UhMBm+VcHGWP3j0oA5miiigRpaZpP8Aadjqcsc+LiygFwsGzPmoGAcg54KghsYOQD6Vo6b4e03VbdYbbWy2rNbyTi1+yMI/kVnKGQt97ap/hxnvVvw1qfhjS5NNvbt9TjvYGkW7jhtkljuY2yCmWlUjKEqeO9TnxJpEXhn+zrC6v7GZYZ4WMWm25a5DSOy75t4kAKsqsBkYHQ9wZiafoC6haxXS3RFuFlN0Vj3NCURnwBkbtyqSDkchh/DmqGqWP9m6jLa+Z5gXaysV2kqwDDIycHBGRng8V07eMIF+ypE98sJysoGFa2QqgVYSG/gZd4J25PGOWzx8sjyyvJI7O7sWZ2OSxPUk+tAH/9k=", + "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQBLa273V3Dbx/flkVF+pOK7q8Phvw9J/Z76SupXMQxNIz7FDegOCTXJ+Hf+Rn0n/r8h/9DFXtf/5GPU/+vuX/ANDNbQfLDmtrcpaK5q/274d/6FGD/wACT/8AE10Og6GfE1i97pHgCC5t0kMTP/aCJhgASMNg9GH515zXpOg2Olah8Hni1fWf7Ktxr5ZZ/srT7m+zgBdq8jgk59vel7aXZfcv8guUtftLfwvPDDrPgOO1aZS0ZN2HVgDg4ZQRkcZGcjI9RWR/bvh3/oUYP/Ak/wDxNdJ40jtdD+HGg6HYX02q2V3cvfxagzBYxgFTEkeSy435YHGGJ7khfNqPbS7L7l/kFzrrM+G/EMn9nppK6bcyjEMivvUt6E4BFcLdW72t3NbyffikZG+oOK3NA/5GPTP+vuL/ANDFUfEX/Iz6t/1+Tf8AoZpzfNDmtrcHqrmZRRRWJIUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBYsLprHULa8RQzQSrKAe5Ug/wBK7O/8Py6/eS6poLR3cFyxlaPzVWSJjyQwJHeuEorSE0lyyV0NM7L/AIQfxH/0Dv8AyPH/APFV12g2t9p/hV9A1fwZ/atub03qn+1Fg2tsCD7vJ4B79+nFeP0U70v5X96/yHdHqfinT/EfiH7Da2vh6HTdK0+Mx2lnFcRts3YLszkgszEZJP8APJPPf8IP4j/6B3/keP8A+KrjaKL0v5X96/yC6O7sPD8ugXkWqa80dpBbMJVj81WklYcgKAT3rjL+6a+1C5vHUK08rSkDsWJP9ar0UpzTXLFWQmwooorMQUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB0Wp6Da2XhDw7q0ckxuNS+0+crEbV8uQKu0YyODzkmsLy19TXY6//wAk08E/9v3/AKOFcvaxJNdRpLII4yfnYnovf8cUDK3lr6mjy19TW62owzSLeMPKkXdDiPG5FI+RlHGSBkfgOealh1C0kMLzysUjubcyPIoLyBfMJYqD7gd+MdaAOd8tfU1O2nyrB52FKAAnbIrEA9MgHI/GtSHVljgnSSWaZmWRVLKQW3Ltyx39vcHp+Stq0Jtpk3Tsskcarbso8tCrKTg56Haew60AYflr6mjy19TWzf6lDdD9286t82DzgAj7mCxGPcY6dKyaBDPLX1NHlr6mn0UAM8tfU0eWvqafRQAzy19TR5a+pp9FADPLX1NHlr6mn0UAM8tfU0eWvqafRQAzy19TR5a+pp9FADPLX1NHlr6mn0UAM8tfU0eWvqafRQAzy19TR5a+pp9FADPLX1NHlr6mn0UAM8tfU0eWvqafRQAzy19TR5a+pp9FADPLX1NHlr6mn11un6rpNr4YuTFpdk161ubW5WWeUPJl1ZZFG8Aj5cFQMggHkEgAHH+WvqaPLX1NdvpGtarL4dvbe81xo7BopXQjUAkySqmFXy9251fCoRggZzxg1neHNSi8P2lxq4EE140i20Nu5B/dnmUkdgVxHnuJGxyKBnM+Wvqa3dM0G1vfCHiLVpJJhcab9m8lVI2t5khVtwxk8DjBFUtWtra01W4hs51ntQ26GQEHKMMrnHRsEAjscjtXQ6B/yTTxt/24/wDo40AcTRRRQI7bX/8Akmngn/t+/wDRwrka67X/APkmngn/ALfv/RwrmLLH22HdMYV3jMg/h96BkFFb0l9GizCWaSOQQbYZFmE8hJdScupGOAePQn8Ug1a2c2kdwz7FnhkkJQ7VCAjAG45Bz2A6dDQBhUVrwav9nlt2E1w+24MkzHrIvy4B5OSMHr60waigsYYEmuI2XG443YxnlSWwPwA+tAGXRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoor0dNT0azvVaK5tp7q90DyppmYbbbbp2wRKf+ejSKAfThepYUAecUV6Dp3i7Rnv7EX0179i8+0JtJYVa3shGyFmjAYk5CkHCg4ds7j1r2uuabBa6Rqd7qN9d3dlq892gKK0k2FtyvmZclASmAfm6HjigZw1XLDS7nUt/wBnNuNpAPnXMcWSegG9hnp2rfj1fTl0eGyvDcIsuj/ZN8CxylXF6Zsld4wMDGDg85xggmceK7PdOsNxqNgMWyR3FtGpkmjhhWLY43AAHaGxlhk8g4BoA5CaGS3nkgmjaOWNijowwVYHBBHrXV6B/wAk08bf9uP/AKONYWv6hFq3iTVNRgV1iu7uWdFcAMFdywBx3wa3dA/5Jp42/wC3H/0caAOJooooEdtr/wDyTTwT/wBv3/o4VyNddr//ACTTwT/2/f8Ao4U2zhkTw3p8trFpIkkkmEjXqwbmwVxgycnGT0rSEOdsq1zk6K6+azsH159JngjilubVA7W8YOy4A3Dy844YYXAIBLemKzryDTrHQfMtjLNNeybUNzAqtGiH5iuGbGWwM8fdYVTotXd9gsYNFautwxRJpflxom+xjdtqgbmJbk+pqzeW8K32hKsMYWW2haQBRhyXOSfWp9m7tCsYNFdV4h+0W8t/GsWiLbLKyKsK2/mqu7A4X5gf1FXHstFHif7OuVvHijWCB7dfs4laNducHJGTn7vU88db9g72uPlOJoroNF0prqx1NpEi8108i2DjlpgQ5VOOu1SP+BAd65+s5QaSb6isFFFFQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK67QP+SaeNv+3H/wBHGuRrrtA/5Jp42/7cf/RxoGjiaKKKBHba/wD8k08E/wDb9/6OFYsGteXp8NlNp9ncxwszRtMH3DdjP3WA7CtDQ/E2mLoJ0DxFYz3OnrKZree1cLPbsfvbc8EH0Pf14xZ8z4a+niz/AMlqqMnHYZz15qVxeX4vHKxyrtCCIbRGFAChR2xgVPd61Lf6qt9dWttJtXaLfawixz2BB6knr1NbXmfDX08Wf+S1HmfDX08Wf+S1Pnl3Azp/Ea3IiE2i6Y3lRiNPll4UdB/rPc0258RNdCDOl6fG8CosTosmUCnIAy5H/wCutPzPhr6eLP8AyWo8z4a+niz/AMlqftZ9x3Zj32tJf+ez6VYRzTMWaaMSbgSckjLkfpVh/FE5n+1JYWEd4FCi5EbF1wAARuYrnAHOK0PM+Gvp4s/8lqPM+Gvp4s/8lqPaz3uF2c9PqdxMlmgIiFoP3Xl5HzZyXJz94nv7Cory6a9vJbl4442lbcyxjC57kD36103mfDX08Wf+S1HmfDX08Wf+S1S5N7iOSorrfM+Gvp4s/wDJajzPhr6eLP8AyWqQOSorrfM+Gvp4s/8AJajzPhr6eLP/ACWoA5Kiut8z4a+niz/yWo8z4a+niz/yWoA5Kiut8z4a+niz/wAlqPM+Gvp4s/8AJagDkqK63zPhr6eLP/JajzPhr6eLP/JagDkqK63zPhr6eLP/ACWo8z4a+niz/wAlqAOSorrfM+Gvp4s/8lqPM+Gvp4s/8lqAOSorrfM+Gvp4s/8AJajzPhr6eLP/ACWoA5Kiut8z4a+niz/yWo8z4a+niz/yWoA5Kiut8z4a+niz/wAlqPM+Gvp4s/8AJagDkqK63zPhr6eLP/JajzPhr6eLP/JagDkqK63zPhr6eLP/ACWo8z4a+niz/wAlqAOSorrfM+Gvp4s/8lqPM+Gvp4s/8lqAOSrrtA/5Jp42/wC3H/0caTzPhr6eLP8AyWqtrnibTG0EaB4dsZ7bT2lE1xPdOGnuGH3d2OAB6Dv6c5AOTooooEbugeEtT8RRT3Fube3srfAmvLuURwxn0Lev09vWtb/hXbf9Df4T/wDBl/8AY1LrTtD8LvCMMbFY7iW8mlUdHdZAqsfcAkVx9Azq/wDhXbf9Df4T/wDBl/8AY0f8K7b/AKG/wn/4Mv8A7GuUooA6v/hXbf8AQ3+E/wDwZf8A2NH/AArtv+hv8J/+DL/7GuUooA6v/hXbf9Df4T/8GX/2NH/Cu2/6G/wn/wCDL/7GuUooA6v/AIV23/Q3+E//AAZf/Y0f8K7b/ob/AAn/AODL/wCxrlKKAOr/AOFdt/0N/hP/AMGX/wBjR/wrtv8Aob/Cf/gy/wDsa5SigDq/+Fdt/wBDf4T/APBl/wDY0f8ACu2/6G/wn/4Mv/sa5SigDq/+Fdt/0N/hP/wZf/Y0f8K7b/ob/Cf/AIMv/sa5SigDq/8AhXbf9Df4T/8ABl/9jR/wrtv+hv8ACf8A4Mv/ALGuUooA6v8A4V23/Q3+E/8AwZf/AGNH/Cu2/wChv8J/+DL/AOxrlKKAOr/4V23/AEN/hP8A8GX/ANjR/wAK7b/ob/Cf/gy/+xrlKKAOr/4V23/Q3+E//Bl/9jR/wrtv+hv8J/8Agy/+xrlKKAOr/wCFdt/0N/hP/wAGX/2NH/Cu2/6G/wAJ/wDgy/8Asa5SigDq/wDhXbf9Df4T/wDBl/8AY0f8K7b/AKG/wn/4Mv8A7GuUooA6v/hXbf8AQ3+E/wDwZf8A2NH/AArtv+hv8J/+DL/7GuUooA6v/hXbf9Df4T/8GX/2NH/Cu2/6G/wn/wCDL/7GuUooA6v/AIV23/Q3+E//AAZf/Y0f8K7b/ob/AAn/AODL/wCxrlKKAOr/AOFdt/0N/hP/AMGX/wBjR/wrtv8Aob/Cf/gy/wDsa5SigDq/+Fdt/wBDf4T/APBl/wDY1k6/4S1Pw7FBcXBt7iyuMiG8tJRJDIfQN6/X39Kyq7DRXab4XeLoZGLR28tnNEp6I7SFWYe5AAoA4eiiigR22v8A/JNPBP8A2/f+jhXI112v/wDJNPBP/b9/6OFcjQNhRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACuu0D/AJJp42/7cf8A0ca5Guu0D/kmnjb/ALcf/RxoGjiaKKKBHba//wAk08E/9v3/AKOFcpEqvKqsxUE4JC5P5d66vX/+SaeCf+37/wBHCuVt53triOePG9GDDNAzSOihQXed4kCbmWVFSQc4HylsYPqTUf8AZDefbRNIV865MGSoO37uDwf9vpntVU3brKJLdRbNjGYWYZ/EkmiK9uInBE0hUP5hUuwBbOcnB68DnrQBOmnxvYPcLcgskYcoAOMuFx97PfPTFQXlulrcywCQu0UjxklcDg4B696Z9pn8kQmaQwg5Ee47fypbm6lu55JZD992faCdqljk4FAENFFFAgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKv6Tpw1O7eN5vIgiieeaULuKooycLkZJ6AZHJHIHNUKt6bqMumXf2iJI5AUaOSKUEpIjAhlOCDgg9iCOoIIoA1z4atljN8+oyjSTai5WcWwMpzIYtnl78btyt/FjAznoKWXwzbWXnT6hqTxWQaEQTQ23mNKJY/MUlSw2gKRnkkE4APWq//CTTmUq1jZtZG3FsLEh/KCB94wd2/O8ls7s5J5wcUo8UXEks5urKyu4JWjZbeZGEcRjXYm3awIAX5cEkEYznFAy4ng7y7xLC+v8AyL6e8ksrVI4fMR5EYLlmyNqliACAx6kgd68XhqN7SNWvWTUprSS8jtvJynloGYgybuGKoxA2kdOQTw2HxbfxyGeaG2urtbl7qG5mRt8ErkFmXBA6gHDAgEZA65ij8SXMdgtuLe2adIHto7xlbzkifO5B823ozDJUkBsA9MAFqXwsojmggvGl1O2iimuLYw7UAkKKAr7vmYGRAcqB1wTjlt54bt4hJ9k1Frj7PeJZXW6DYEdt2GT5juX5H5O08DjmoJvE13NaPGsFtFcSRxxTXkYYSyohUqGy20cohyACSoyTzmWXxVNNMsjabp4DXAurhFWRVuZQCAz4fIxuYgKVGSeKAMnUbT7Bqd3Z7/M+zzPFvxjdtYjOO3Sul0D/AJJp42/7cf8A0ca5i9unvr64u5QoknlaVgo4BY5OPbmun0D/AJJp42/7cf8A0caARzWgqra1bhgCMscH/dNGvKq61cBQAMqcD/dFL4f/AOQ3b/8AAv8A0E0eIP8AkN3H/Af/AEEV6Vl/Zt/7/wD7aX/y7+Z0mv8A/JNPBP8A2/f+jhXL2dv9rvre23bPOkWPdjOMnGcV1Gv/APJNPBP/AG/f+jhXLW07Wt1DcIAXidXUN0JBzzXmkFg6ZMba3niKP5sZk2b1DDDMOFzk/dzkD+VVHCB8IxZeOSMGrcepPHFCoghMkKFI5Tu3KCSfXHVj2qo7vI252LMe7HJoENooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK1tP0q1uLBL69vmtbb7YltIyQeYUDKzb8bhnG3p/+qsmtSDWjBpcOn/YLN4kuPPkLhyZjggBvmwBhj90A+9AF6fw3br4jt9Ht76ZjcL+6mmt1RJGIPl7SsjAqx2jdnjPTjFVNO0m1ura4ubq8mt4rRc3IW3DsCWCoqgsNxJJznbgKevAqc+Jw4SOTRdMkgijWOCJhMPICu7/I4kD8tIxOWPb0FRv4knl1bUb6Wys5E1Ek3NqVcRMSwbIwwYHcM5DevYkUDJh4bhGpS2r37COOEXZmEGQbYxeYGxuzvwVG3pk/ewM1BdaLawy2nl30skN9Gslq5twpYGQxsHG47SCrdC2cDpmox4gu/wC2G1Jo4GLx+Q0BU+UYtmwR4BztCgAc5GAc55ok115dSs7p7G0MNmoSC0G8RIoJbHDbz8zFsls5PpxQBT1G0+wand2e/wAz7PM8W/GN21iM47dK6XQP+SaeNv8Atx/9HGuYvbp76+uLuUKJJ5WlYKOAWOTj25rp9A/5Jp42/wC3H/0caARzfh//AJDdv/wL/wBBNHiD/kN3H/Af/QRR4f8A+Q3b/wDAv/QTR4g/5Ddx/wAB/wDQRXp/8y3/ALf/APbS/wDl38zpNf8A+SaeCf8At+/9HCuXs7f7XfW9tu2edIse7GcZOM4rqNf/AOSaeCf+37/0cK5a2na1uobhAC8Tq6huhIOea8wgsjS5Rb+c7KF8syYHJHQgH0yCCPannSX3MyyoYfL3qwZdzA/d+XORkkD2qBdRuFN0Swb7SpEmR79R6H/GkN7KbNLX5QqNuDAfN3IGfQEk/jQA+a2tYZGia6dpEba+2H5ffad3P4gVTq3LfvKTIIYo52O5po9wYn164H4AVUoEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAblh4XutWsrS40+a3kaaYwPHNPHCUkzwBuYFgVIOQPUY45uHwcJruGSz1O3m0qQO5u3aON1RCfMbyS+44Ck4HUY6ZrJ0zW7rSre8ggWJluo9h8xclDgrvXnhgrOufRj3wQW+t3VtotzpSLEYZ23b2X50+7uCnPAbYmfXYOnOQZsad4Rj1LS47+2fV7lJbl7dUs9L84qVSNiW/eDbkyEDrnaT7VJbeCTPbyyJNqF4U1CeyB0vT/tKHywh37t64Db+OOxrNtfFFxDa28NzZ2189vcNcxTXLyl0crGvVXAIAiTAIPSlg8UTRxItxp9ldvHeSXsckvmKySybN2NjqMfu1OCKAFXw/bCfUBLqQ+z6c7rcTxRb1YBwieV8w3liSedoAHWmpo+mG3mv21ScaajpEri0BmeRgTt8vftwAOTv7jGe0MHiK+jmuDMUuoLnd51rNnym3MHOACNp3AHKkHjrT08QbRND/AGVp5sZSjGyIk8sMoIDBt+8H5jzu5zz0GACWy0fSrsahKdUuhbWUBnd0sgWYebFGoCmQc5lyeeNvfNTw+GbGS1m1E6pP/ZcdqbhZUtAZSwmjiKFDIACDKrZDEYx34FO28RzW73itZWs1ncxGE2UhkEMal0k+QK4YHdGvOecc5qaPxVLGJYTptg1jJbfZvsREojVTIspIIcOW3IvJY8cdMYAJbXwza3uo6VDBqUpt9UnSC3ma2wysZFRw67+CoYNwSDkcjnE0XhGObWrbTg2swtLDPMRc6V5chEcbPiNPNO8naR1HJHWqMXiq/ttQsLm0jhtobGRJIrOLeISVcSDcCxZssASSSeByMDDINfjtNQju7XRdPg2xTQvErTlJVkjMbBt0hI+VjjaR1oAtR+G7aXxJZ6N9o1K2lupYYlN5p4iZS8gUkr5h4AOQc8njjrUdp4P1m4+3Ryabfw3Vva/aYrdrR98482OMhR148zdkA/d/EV7bX5bDV7bUNOtLez8iSKU28TymKVo3DrvDOSeQOM9uMHmpYPEUNsbhYdB0xIbmDyJot9wVdd6SA5MuQQ0Y6EdTnNAGRcW09pcPb3MMkMyHDxyKVZT6EHkV1Ogf8k08bf8Abj/6ONcvdTR3Fy8sVtFbI2MQxFiq8dtzMffkmuo0D/kmnjb/ALcf/RxoA5vw/wD8hu3/AOBf+gmjxB/yG7j/AID/AOgijw//AMhu3/4F/wCgmjxB/wAhu4/4D/6CK9P/AJlv/b//ALaX/wAu/mdJr/8AyTTwT/2/f+jhWNb6IZdPhvJdRsraOZmWNZi+TtxnopHcd62df/5Jp4J/7fv/AEcKpfZBqPhvTIoruySSGScyJNcpGRuK44Jz2NcNOKd9LkopLoF4dWttP3Qh7kAxSh90bqc8gjPHBqK702G2gMiarY3BBA8uEybj/wB9IB+tb9heWdprGgWX2uGRLJnM1xuxHuc5wCccDjn1JqtNp8dzNbRTJolnC0wEktreBmC98gyNxj264rR0o293+th2Mq70a7stLtNQlCeTdZ2gH5l9Nw7ZHI9qcuhXkk9rDH5bNcW4uAd2FRMkEsTgDGDWiNUi1a+1S2mZIba7T/R95CrE0Y/dDJ4Hygr/AMCqx9us2jtrOS6jjW50lLczA7hE4kLANjkDgA/UUKnTbunp/X5isjIn0Vo/L8rULC53yLGfJlJKk9MggEj3ANOvdESx89X1bT3mhJVokMm4sDggZQDP405dMXTrq1ml1Cwf9+mEhnEhxnliRwAPcitLxFGk0l/NFBomxpmdZoLwNKw3Zzt8w8nvxS5Fyt21CxytFFFc5IUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFddoH/JNPG3/bj/6ONcjXXaB/yTTxt/24/wDo40DRzfh//kN2/wDwL/0E0eIP+Q3cf8B/9BFHh/8A5Ddv/wAC/wDQTR4g/wCQ3cf8B/8AQRXp/wDMt/7f/wDbS/8Al38zr10658UfDTR49JjNzdaLLcJc20fMu2Vw6uF6kcY45/I1z3/CJeJP+he1b/wCk/wrGtLy6sLgXFnczW8y9JIXKMPxHNaX/CX+Jv8AoYtW/wDA2T/4qvMIJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4V0Ladc+F/hprEerRm2utalt0traTiXbE5dnK9QOcc8/mK5f/AIS/xN/0MWrf+Bsn/wAVWbd3l1f3BuLy5muJm6yTOXY/ieaALfh//kN2/wDwL/0E0eIP+Q3cf8B/9BFM0WaODV4JJXCICQWPQZUijWpo59XnkicOhIAYdDhQK9Hmj/Z/LfXn/wDbS7/u/mUKK3P+EWvv+etv/wB9N/hR/wAItff89bf/AL6b/Co/s3F/8+2L2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cux11FFFfeHaFFFFABRRRQAUUUUAFT2Ks9/bqluLl2kULC2cSHPC8EHmoKltriW0uormByk0Th0YdiDkGpkm07AdLqr26aTdQ6gmkrf5X7PHYRgPGQ3zB2T5SMZGCSc1Xu9J8rwfaz7IvtSyGeZQP3iwyYWNm4+7lT9N49apXetrdjnStOiJkDu0cTAvg5wfm4B7hcU3+3bs6tcajII5JLhWSWNgdjIRjbgHoBjHPGB6VxwpVYpW0s7/pZdlv8AMlJm9YmG2gtjrFpo9rp7wgmIxbrmVSOGUjLgnqCSB+FY2mwxSeHtbleJGkjWHYzKCVzJg4PbikPiCWS2jjnsLCeWOIQpcSxEyBQMDvtOB0JBPFSWviMWlg9mujaa8cqIspdZcybeQTh+ueeMUlTqRTdtW1100d/xFZmtZQyR+FdNmtIdGEsks4le/WAM2Cu3Bk5OMnpUdppq6vpFxJMltCyaiDcXEEahY4ljYtt28Y44A4Jx61mr4i/0SO1l0jTpoYpHkiVxL+73kEgYcccDrnpVdtcuf7Mu9Ohjht7W6mE0iRBu3RRkn5eh/Ac1Ko1dbKzvv5X9ewWZszaZYjQ9W1KyhzZTQRNbmQBngcSqrpnsRn8VYVmaXBFJ4e12V4kaSKOExuyglCZVBwe3HFVbbWLu10i90tCptbsozqwJ2lSCCvoeADUdtqEtrY3toioY7tUWQsDkBWDDHPqK2jSqKLTd/eTXorf5P1HZnXz6LYweJWvr2BE05Gt44bdFC/aJTGhwB/dGcsfw6mq99pmnyWWs75bWx8rWWjjleFjhcP8AINikgd8dOKwtQ8Q3+p6hbXdyyE2wRYowCEULjtnvjmpl8SylbxLjT7G5S6ujdOkqvhXOem1hxyeuawWHrpRbeqS28vUVmS2NtZ6fY6jqW2DUjbSRQwblbysuGJdlIBONuADxk96V5Ida0LULqSxtre6sfLdZbaMRq6s4UqyjjPIIIHY1Sh1yW2vJZra0tIoZkCS2gQtC4HqGJOc85zx2pL7W5ry0FpHb21na7t7Q2yFQ7dixJJOMnqa29lUc7+a1vstLr56+Wo7O51MthoQ8WfZlyt68UawQSWy/ZhM0S7c4OSMnONuMnnI658GlW0mhade3kIS3t2uHu2RQrSYZAseR3JOB6DJ7VTfxbcNcfa007To70KqrdCNi64UKCNzFc4A5xWdNrF3Po0GlMwFtDK0oAzlmbu3POOcfU1jChXtFN9r6+TTt9+gkmdE1nZ6Lpi3xtoru0bUYXieSMEyW7Rvlc+vBB9GX2pP7J0bSbm+uvOuboWEYdEuLZPJmZx+653HIOd3TkKelc82sXb6EujuVa1Sfz0yDuVsEYB9OScetOutau7zSbXTpfL8m3PDAfM/XbuPfaCQPQGr+r1r6y3evp/V9u/kHKycQxHwa8/lJ539oBPM2jdt8snGfTPatk2FikVreyWkci22jJcmADaJpDKUBfHJAyCfXAFZv/CTr9iNn/YWlfZzJ5uzbL97GM/6z0qqviC9S5tJ4/KRra3+zBQuVePJJDg5DZ3HP4USp1p9Lavr+GgWbNC1uYdfgv7e406zglhtZLiGe1hERUoM7SBwQRxzzkirM2i2skWmXtyi2+nQ6dHLdPGoDSuXfCj1dsAZ7AZPSse51+aa0ltrezsrKObAm+yxFTIOuCSScZ7DAqK/1u91GwsrGZ1FtZpsjjQEA/wC0fU9v8mj2NW65fdV++2n9fmFmWvF0UEPia5W2t47eHZEyxRjAXMan+tYlW9S1CXVL57udUWRlRSEBAwqhR1J7AVUrqoxcKcYy3SRS2CiiitRhRRRQAUUUUAFFFFAH/9k=", "export_temp_image": false, "force_export_images": false, "flat_export": false, @@ -23,7 +23,7 @@ "theme_color1": 5, "theme_color2": 0, "custom_variable_prefix": "uic", - "backup_cnt": 72, + "backup_cnt": 73, "autosave_cnt": 0, "group_color_cnt": 0, "lvgl_version": "9.1.0", diff --git a/ui/PyroVision.spj b/ui/PyroVision.spj index 8363e16..ed99082 100644 --- a/ui/PyroVision.spj +++ b/ui/PyroVision.spj @@ -1507,192 +1507,6 @@ ], "saved_objtypeKey": "LABEL" }, - { - "guid": "GUID89924559-68981S4954354", - "deepid": 1996386752, - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Image Main Bluetooth", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 25, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 51, - "strtype": "OBJECT/Size", - "intarray": [ - 1, - 1 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "TOP_LEFT", - "InheritedType": 3 - }, - { - "nid": 90, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 130, - "strtype": "OBJECT/Press_lock", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 140, - "strtype": "OBJECT/Click_focusable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 210, - "strtype": "OBJECT/Gesture_bubble", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 220, - "strtype": "OBJECT/Snappable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "nid": 1010, - "strtype": "LABEL/Label", - "InheritedType": 1 - }, - { - "nid": 1020, - "strtype": "LABEL/Long_mode", - "strval": "WRAP", - "InheritedType": 3 - }, - { - "nid": 1030, - "strtype": "LABEL/Text", - "strval": "B", - "InheritedType": 10 - }, - { - "part": "lv.PART.MAIN", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10410, - "strtype": "_style/Text_Color", - "intarray": [ - 255, - 0, - 0, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10450, - "strtype": "_style/Text_Font", - "strval": "montserrat_12", - "InheritedType": 3 - } - ], - "InheritedType": 1 - } - ], - "nid": 1040, - "strtype": "LABEL/Style_main", - "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "LABEL" - }, { "guid": "GUID85409111-68983S431164354", "deepid": -1585715219, @@ -1733,7 +1547,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 45, + 25, 0 ], "InheritedType": 7 @@ -9578,80 +9392,278 @@ ], "saved_objtypeKey": "LABEL", "tree_closed": true - } - ], - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Info Container4", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 1, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 1, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 0, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 34, - "strtype": "OBJECT/Size", - "intarray": [ - 50, - 100 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "LEFT_MID", - "InheritedType": 3 - }, - { - "nid": 90, - "strtype": "OBJECT/Flags", - "InheritedType": 1 }, { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 130, - "strtype": "OBJECT/Press_lock", + "guid": "GUID56191097-584542S741516", + "deepid": -567540342, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Serial Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Serial:\\n", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 136, + 136, + 136, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL", + "tree_closed": true + } + ], + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Info Container4", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 1, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 1, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 34, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 100 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "LEFT_MID", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", "strval": "False", "InheritedType": 2 }, @@ -9942,7 +9954,7 @@ "saved_objtypeKey": "LABEL" }, { - "guid": "GUID6232689-47165S95524359", + "guid": "GUID97387059-584544S524516", "deepid": -1317032992, "dont_export": false, "locked": false, @@ -10087,7 +10099,210 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "127.0.0.1\\n", + "strval": "127.0.0.1", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_10", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID64451864-584545S24208516", + "deepid": -1317032992, + "dont_export": false, + "locked": false, + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Serial", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "00000001", "InheritedType": 10 }, { @@ -17243,7 +17458,7 @@ "theme_color1": 5, "theme_color2": 0, "custom_variable_prefix": "uic", - "backup_cnt": 71, + "backup_cnt": 72, "autosave_cnt": 0, "group_color_cnt": 0, "lvgl_version": "9.1.0", diff --git a/ui/project.info b/ui/project.info index 0504663..5bb3305 100644 --- a/ui/project.info +++ b/ui/project.info @@ -1,7 +1,7 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-01-05T13:41:48.0249747+01:00", + "datetime": "2026-01-16T13:29:19.5084763+01:00", "editor_version": "1.5.4", - "project_version": 92, + "project_version": 94, "user": "Kampert Daniel" } \ No newline at end of file diff --git a/webserver/provision.html b/webserver/provision.html new file mode 100644 index 0000000..3852439 --- /dev/null +++ b/webserver/provision.html @@ -0,0 +1,308 @@ + + + + + + PyroVision WiFi Setup + + + +
+
+

🔥 PyroVision

+

WiFi-Konfiguration

+
+
+
+ +
+
+ + +
+ +
+ +
+ + +
+
+ + +
+
+
+ + + + From 0b261e5bb5d8864227fc472f4c5f990346a5bdce Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Mon, 19 Jan 2026 08:58:58 +0100 Subject: [PATCH 07/26] Remove custom target registration for format --- scripts/format.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/format.py b/scripts/format.py index 616673c..3426928 100644 --- a/scripts/format.py +++ b/scripts/format.py @@ -79,5 +79,4 @@ def run_astyle(source, target, env): raise -# Register custom target -env.AlwaysBuild(env.Alias("format", None, run_astyle)) \ No newline at end of file +env.AlwaysBuild(env.Alias("format", None, run_astyle)) From 4d331eb8da67a0d9273681d237cc7dc4c3a11bd0 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Sat, 31 Jan 2026 14:52:20 +0100 Subject: [PATCH 08/26] Working on firmware - Replace touch controller with GT911 - Improve loading of default settings from SD card - UI improvements and fixes Signed-off-by: Daniel Kampert --- .github/copilot-instructions.md | 149 +- .gitignore | 3 +- ...lt_settings.json => settings_default.json} | 3 +- main/Application/Manager/Devices/ADC/adc.cpp | 61 +- main/Application/Manager/Devices/ADC/adc.h | 7 +- main/Application/Manager/Devices/I2C/i2c.cpp | 17 + .../Manager/Devices/devicesManager.cpp | 21 +- .../Manager/Devices/devicesManager.h | 2 +- .../Application/Manager/Network/SNTP/sntp.cpp | 25 +- main/Application/Manager/Network/SNTP/sntp.h | 28 +- .../Manager/Network/Server/http_server.cpp | 6 +- .../Manager/Network/networkTypes.h | 4 - .../Private/settingsDefaultLoader.cpp | 17 +- .../Settings/Private/settingsJSONLoader.cpp | 273 +++- .../Manager/Settings/Private/settingsLoader.h | 19 +- .../Manager/Settings/settingsManager.cpp | 13 +- .../Manager/Settings/settingsTypes.h | 1 + .../Tasks/GUI/Export/fonts/ui_font_fa.c | 3 +- .../GUI/Export/images/ui_img_logo_80x44_png.c | 228 +-- .../Export/images/ui_img_text_218x40_png.c | 552 +++---- .../Application/Tasks/GUI/Export/project.info | 6 +- .../Tasks/GUI/Export/screens/ui_Info.c | 145 +- .../Tasks/GUI/Export/screens/ui_Info.h | 94 +- .../Tasks/GUI/Export/screens/ui_Main.c | 93 +- .../Tasks/GUI/Export/screens/ui_Main.h | 65 +- .../Tasks/GUI/Export/screens/ui_Menu.c | 26 +- .../Tasks/GUI/Export/screens/ui_Menu.h | 16 +- .../Tasks/GUI/Export/screens/ui_Splash.c | 26 +- .../Tasks/GUI/Export/screens/ui_Splash.h | 16 +- main/Application/Tasks/GUI/Export/ui.c | 12 +- main/Application/Tasks/GUI/Export/ui.h | 86 +- .../Tasks/GUI/Export/ui_events.cpp | 1 - main/Application/Tasks/GUI/Export/ui_events.h | 2 +- .../Application/Tasks/GUI/Export/ui_helpers.c | 167 +-- .../Application/Tasks/GUI/Export/ui_helpers.h | 286 ++-- .../Tasks/GUI/Private/guiHelper.cpp | 148 +- .../Application/Tasks/GUI/Private/guiHelper.h | 4 +- main/Application/Tasks/GUI/guiTask.cpp | 66 +- main/Application/Tasks/Lepton/leptonTask.cpp | 33 +- .../Application/Tasks/Network/networkTask.cpp | 50 +- main/Application/application.h | 5 +- main/Kconfig.projbuild | 94 +- main/idf_component.yml | 4 +- sdkconfig.debug | 41 +- ui/PyroVision.sll | 7 +- ui/PyroVision.spj | 1298 ++++++++++------- ui/project.info | 6 +- 47 files changed, 2484 insertions(+), 1745 deletions(-) rename data/{default_settings.json => settings_default.json} (94%) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index abd1c04..b2f425d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -177,20 +177,75 @@ along with this program. If not, see . ## Documentation Standards -### Code Comments +### Function Documentation Requirements + +**CRITICAL**: Every function declaration in header files MUST include complete Doxygen documentation. + +#### Doxygen-Style Documentation for ALL Functions + +Use Doxygen comments for **ALL** public API functions with complete documentation: + +```cpp +/** @brief Initialize the settings manager and load configuration from NVS. + * + * This function initializes the settings subsystem, opens the NVS namespace, + * and attempts to load stored settings. If no settings exist, default values + * are loaded from JSON or hardcoded defaults. + * + * @return ESP_OK on success + * @return ESP_ERR_NVS_NOT_FOUND if settings namespace doesn't exist + * @return ESP_ERR_NO_MEM if memory allocation fails + * @return ESP_ERR_INVALID_STATE if already initialized + * + * @note Must be called after NVS flash initialization. + * @note This function must be called before any other SettingsManager API calls. + * @warning Not thread-safe during initialization. Call once from main task. + */ +esp_err_t SettingsManager_Init(void); +``` -#### Doxygen-Style Documentation -Use Doxygen comments for all public API functions: +**Mandatory documentation elements:** +- `@brief` - Short one-line description +- Detailed description paragraph explaining what the function does +- `@param` - Description for EACH parameter (include direction: in/out/inout if relevant) +- `@return` - Document ALL possible return values (one `@return` per value) +- `@note` - Important usage notes (at least one recommended) +- `@warning` - Critical warnings about misuse or side effects (if applicable) +#### Incomplete Documentation is NOT Acceptable + +❌ **Insufficient:** +```cpp +/** @brief Brief description. + * @param p_Param Description + * @return ESP_OK on success + */ +``` + +✅ **Complete:** ```cpp -/** @brief Brief description of the function. - * @param p_Param Description of parameter - * @param Size Description of size parameter - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Set WiFi credentials and update configuration. + * + * Updates the WiFi SSID and password in RAM and posts a SETTINGS_EVENT_WIFI_CHANGED + * event. Changes are not persisted until SettingsManager_Save() is called. + * + * @param p_SSID Pointer to null-terminated SSID string (max 32 chars) + * @param p_Pass Pointer to null-terminated password string (max 64 chars) + * + * @return ESP_OK on success + * @return ESP_ERR_INVALID_ARG if p_SSID or p_Pass is NULL + * @return ESP_ERR_INVALID_ARG if strings exceed maximum length + * @return ESP_ERR_INVALID_STATE if SettingsManager not initialized + * + * @note Call SettingsManager_Save() to persist changes to NVS. + * @note This function is thread-safe. + * @warning Password is stored in plain text in NVS. */ -esp_err_t MyFunction(uint8_t *p_Param, size_t Size); +esp_err_t SettingsManager_SetWiFi(const char *p_SSID, const char *p_Pass); ``` +### Code Comments + #### Inline Comments - Use `//` for single-line comments - Use `/* */` for block comments @@ -561,6 +616,70 @@ Documentation is automatically built and deployed via GitHub Actions workflow (` --- +## Code Quality and Validation + +### Mandatory Checks After Code Changes + +**CRITICAL**: After making ANY code changes, you MUST perform the following validation steps: + +#### 1. Syntax Validation +- Verify code compiles without errors using `pio run` or `idf.py build` +- Check for correct bracket matching, semicolons, and C++ syntax +- Validate all include statements and dependencies +- Ensure no missing header files or forward declarations + +#### 2. Error and Warning Analysis +- **Zero tolerance for compiler warnings** - all warnings must be addressed +- Run static analysis if available +- Check for: + - Unused variables + - Type mismatches or implicit conversions + - Potential null pointer dereferences + - Memory leaks in error paths + - Missing return statements + +#### 3. Error Handling Validation +- Verify ALL ESP-IDF function return codes are checked +- Ensure proper error propagation (don't silently ignore errors) +- Validate error cleanup paths (free resources on failure) +- Check mutex/semaphore release in all paths (including errors) + +#### 4. Documentation Synchronization +- Update function documentation if signatures changed +- Update parameter descriptions if behavior changed +- Verify code examples in documentation still compile +- Update relevant `.adoc` files in `docs/` directory + +**Example validation checklist for each change:** +``` +☐ Code compiles without errors (pio run -e debug) +☐ No compiler warnings introduced +☐ All new/modified functions have complete Doxygen documentation +☐ All return values and parameters documented +☐ Error handling implemented for all ESP-IDF calls +☐ Mutex/semaphore properly released in all code paths +☐ Related documentation (.adoc files) updated +☐ Code formatted with AStyle (scripts/format.py) +☐ Run static analysis if available (pio check) +``` + +### Automated Validation + +Use provided scripts for validation: + +```bash +# Format code +python scripts/format.py + +# Build and check for errors/warnings +pio run -e debug + +# Run static analysis (if configured) +pio check +``` + +--- + ## Testing and Debugging ### Debugging @@ -619,20 +738,24 @@ Documentation is automatically built and deployed via GitHub Actions workflow (` - Mix tabs and spaces - Exceed 120 character line length - Forget error checking on ESP-IDF calls -- Access shared state without mutex protection -- Forget to call `SettingsManager_Save()` after updates +- Omit or provide incomplete function documentation +- Skip syntax and error validation after code changes +- Ignore compiler warnings (treat warnings as errors) - Use blocking operations in ISRs -- Ignore compiler warnings +- Forget to call `SettingsManager_Save()` after updates +- Access shared state without mutex protection ✅ **Do:** - Use consistent naming conventions -- Document all public APIs +- **Document ALL public functions with complete Doxygen comments** - Include license headers in all files -- Test error paths +- **Validate syntax, check for errors and warnings after every code change** +- Test error paths and edge cases - Use appropriate log levels - Clean up resources on failure - Follow the established module patterns - **Update corresponding AsciiDoc documentation when changing code** +- Address all compiler warnings before committing --- diff --git a/.gitignore b/.gitignore index d379b21..a44760d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ managed_components/ */backup/ -*/Font-Awesome/* \ No newline at end of file +*/Font-Awesome/* +data/settings.json \ No newline at end of file diff --git a/data/default_settings.json b/data/settings_default.json similarity index 94% rename from data/default_settings.json rename to data/settings_default.json index f47e77b..2519d1b 100644 --- a/data/default_settings.json +++ b/data/settings_default.json @@ -65,7 +65,8 @@ "timeout" : 60 }, "system" : { - "timezone" : "CET-1CEST,M3.5.0,M10.5.0/3" + "timezone" : "CET-1CEST,M3.5.0,M10.5.0/3", + "ntp-server" : "pool.ntp.org" }, "http-server" : { "port" : 80, diff --git a/main/Application/Manager/Devices/ADC/adc.cpp b/main/Application/Manager/Devices/ADC/adc.cpp index dd0d7cf..7e63b24 100644 --- a/main/Application/Manager/Devices/ADC/adc.cpp +++ b/main/Application/Manager/Devices/ADC/adc.cpp @@ -30,21 +30,42 @@ #include #include "adc.h" -#include "../PortExpander/portexpander.h" #include +#ifdef CONFIG_BATTERY_ADC_1 + #define ADC_UNIT ADC_UNIT_1 +#elif CONFIG_BATTERY_ADC_2 + #define ADC_UNIT ADC_UNIT_2 +#else + #error "No ADC channel configured for battery measurement" +#endif + +#ifdef CONFIG_BATTERY_ADC_ATT_0 + #define ADC_ATTEN ADC_ATTEN_DB_0 +#elif CONFIG_BATTERY_ADC_ATT_2_5 + #define ADC_ATTEN ADC_ATTEN_DB_2_5 +#elif CONFIG_BATTERY_ADC_ATT_6 + #define ADC_ATTEN ADC_ATTEN_DB_6 +#elif CONFIG_BATTERY_ADC_ATT_12 + #define ADC_ATTEN ADC_ATTEN_DB_12 +#else + #error "No ADC attenuation configured for battery measurement" +#endif + static bool _ADC_Calib_Done = false; +static adc_channel_t _ADC_Channel = static_cast(CONFIG_BATTERY_ADC_CHANNEL); static adc_cali_handle_t _ADC_Calib_Handle; static adc_oneshot_unit_handle_t _ADC_Handle; static adc_oneshot_unit_init_cfg_t _ADC_Init_Config = { - .unit_id = ADC_UNIT_1, + .unit_id = ADC_UNIT, .clk_src = ADC_RTC_CLK_SRC_RC_FAST, .ulp_mode = ADC_ULP_MODE_DISABLE, }; -static adc_oneshot_chan_cfg_t config = { - .atten = ADC_ATTEN_DB_0, + +static adc_oneshot_chan_cfg_t ADC_Config = { + .atten = static_cast(ADC_ATTEN), .bitwidth = ADC_BITWIDTH_DEFAULT, }; @@ -55,7 +76,7 @@ esp_err_t ADC_Init(void) esp_err_t Error; ESP_ERROR_CHECK(adc_oneshot_new_unit(&_ADC_Init_Config, &_ADC_Handle)); - ESP_ERROR_CHECK(adc_oneshot_config_channel(_ADC_Handle, ADC_CHANNEL_0, &config)); + ESP_ERROR_CHECK(adc_oneshot_config_channel(_ADC_Handle, _ADC_Channel, &ADC_Config)); Error = ESP_OK; _ADC_Calib_Done = false; @@ -64,8 +85,8 @@ esp_err_t ADC_Init(void) ESP_LOGD(TAG, "calibration scheme version is %s", "Curve Fitting"); adc_cali_curve_fitting_config_t CaliConfig = { .unit_id = _ADC_Init_Config.unit_id, - .chan = ADC_CHANNEL_0, - .atten = config.atten, + .chan = _ADC_Channel, + .atten = ADC_Config.atten, .bitwidth = ADC_BITWIDTH_DEFAULT, }; @@ -80,7 +101,7 @@ esp_err_t ADC_Init(void) } else if ((Error == ESP_ERR_NOT_SUPPORTED) || (_ADC_Calib_Done == false)) { ESP_LOGW(TAG, "eFuse not burnt, skip software calibration"); } else { - ESP_LOGE(TAG, "Invalid arg or no memory"); + ESP_LOGE(TAG, "Invalid arg or no memory!"); return ESP_FAIL; } @@ -100,24 +121,36 @@ esp_err_t ADC_Deinit(void) return ESP_OK; } -esp_err_t ADC_ReadBattery(int *p_Voltage) +esp_err_t ADC_ReadBattery(int *p_Voltage, uint8_t *p_Percentage) { int Raw; - if (p_Voltage == NULL) { + if ((p_Voltage == NULL) || (p_Percentage == NULL)) { return ESP_ERR_INVALID_ARG; } - ESP_ERROR_CHECK(adc_oneshot_read(_ADC_Handle, ADC_CHANNEL_0, &Raw)); + ESP_ERROR_CHECK(ADC_Init()); + + ESP_ERROR_CHECK(adc_oneshot_read(_ADC_Handle, _ADC_Channel, &Raw)); if (_ADC_Calib_Done) { ESP_ERROR_CHECK(adc_cali_raw_to_voltage(_ADC_Calib_Handle, Raw, p_Voltage)); + *p_Voltage = (*p_Voltage) * (CONFIG_BATTERY_ADC_R1 + CONFIG_BATTERY_ADC_R2) / CONFIG_BATTERY_ADC_R2; } else { *p_Voltage = Raw; } - ESP_LOGD(TAG, "ADC%d Channel%d raw data: %d", ADC_UNIT_1, ADC_CHANNEL_0, Raw); - ESP_LOGD(TAG, "ADC%d Channel%d cali voltage: %d mV", ADC_UNIT_1, ADC_CHANNEL_0, *p_Voltage); + /* Calculate battery percentage (LiPo: 3.0V = 0%, 4.2V = 100%) */ + if (*p_Voltage <= CONFIG_BATTERY_ADC_MIN_MV) { + *p_Percentage = 0; + } else if (*p_Voltage >= CONFIG_BATTERY_ADC_MAX_MV) { + *p_Percentage = 100; + } else { + *p_Percentage = (uint8_t)((*p_Voltage - CONFIG_BATTERY_ADC_MIN_MV) * 100 / (CONFIG_BATTERY_ADC_MAX_MV - CONFIG_BATTERY_ADC_MIN_MV)); + } - return ESP_OK; + ESP_LOGD(TAG, "ADC%d Channel%d raw data: %d", ADC_UNIT_1, _ADC_Channel, Raw); + ESP_LOGD(TAG, "ADC%d Channel%d battery: %d mV (%d%%)", ADC_UNIT_1, _ADC_Channel, *p_Voltage, *p_Percentage); + + return ADC_Deinit(); } \ No newline at end of file diff --git a/main/Application/Manager/Devices/ADC/adc.h b/main/Application/Manager/Devices/ADC/adc.h index 6f3c201..5c6c76e 100644 --- a/main/Application/Manager/Devices/ADC/adc.h +++ b/main/Application/Manager/Devices/ADC/adc.h @@ -33,6 +33,11 @@ esp_err_t ADC_Init(void); esp_err_t ADC_Deinit(void); -esp_err_t ADC_ReadBattery(int *p_Voltage); +/** @brief Read battery voltage and calculate percentage + * @param p_Voltage Pointer to store battery voltage in mV + * @param p_Percentage Pointer to store battery percentage (0-100%) + * @return ESP_OK on success + */ +esp_err_t ADC_ReadBattery(int *p_Voltage, uint8_t *p_Percentage); #endif /* ADC_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/I2C/i2c.cpp b/main/Application/Manager/Devices/I2C/i2c.cpp index 5e40152..ecae397 100644 --- a/main/Application/Manager/Devices/I2C/i2c.cpp +++ b/main/Application/Manager/Devices/I2C/i2c.cpp @@ -48,10 +48,12 @@ static const char *TAG = "I2C"; int32_t I2CM_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_Bus_Handle) { _I2C_Mutex = xSemaphoreCreateMutex(); + if (_I2C_Mutex == NULL) { ESP_LOGE(TAG, "Failed to create I2C mutex!"); return ESP_ERR_NO_MEM; } + return i2c_new_master_bus(p_Config, p_Bus_Handle); } @@ -62,6 +64,7 @@ int32_t I2CM_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_ int32_t I2CM_Deinit(i2c_master_bus_handle_t Bus_Handle) { vSemaphoreDelete(_I2C_Mutex); + return i2c_del_master_bus(Bus_Handle); } @@ -74,17 +77,21 @@ int32_t I2CM_Deinit(i2c_master_bus_handle_t Bus_Handle) int32_t I2CM_Write(i2c_master_dev_handle_t *p_Dev_Handle, const uint8_t *p_Data, uint32_t Length) { esp_err_t Error; + if ((p_Dev_Handle == NULL) || (*p_Dev_Handle == NULL) || (p_Data == NULL)) { ESP_LOGE(TAG, "I2C Write: Invalid handle or data pointer"); return ESP_ERR_INVALID_ARG; } else if (Length == 0) { return ESP_OK; } + ESP_LOGD(TAG, "Write %u bytes:", static_cast(Length)); for (uint8_t i = 0; i < Length; i++) { ESP_LOGD(TAG, " Byte %u: 0x%02X", static_cast(i), *(p_Data + i)); } + Error = ESP_FAIL; + if (xSemaphoreTake(_I2C_Mutex, portMAX_DELAY) == pdTRUE) { Error = i2c_master_transmit(*p_Dev_Handle, p_Data, Length, I2C_WAIT); xSemaphoreGive(_I2C_Mutex); @@ -92,6 +99,7 @@ int32_t I2CM_Write(i2c_master_dev_handle_t *p_Dev_Handle, const uint8_t *p_Data, ESP_LOGW(TAG, "I2C transmit failed: %d", Error); } } + return Error; } @@ -104,17 +112,22 @@ int32_t I2CM_Write(i2c_master_dev_handle_t *p_Dev_Handle, const uint8_t *p_Data, int32_t I2CM_Read(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t *p_Data, uint32_t Length) { esp_err_t Error; + if ((p_Dev_Handle == NULL) || (*p_Dev_Handle == NULL) || (p_Data == NULL)) { ESP_LOGE(TAG, "I2C Read: Invalid handle or data pointer"); return ESP_ERR_INVALID_ARG; } else if (Length == 0) { return ESP_OK; } + ESP_LOGD(TAG, "Read %u bytes:", static_cast(Length)); + for (uint8_t i = 0; i < Length; i++) { ESP_LOGD(TAG, " Byte %u: 0x%02X", static_cast(i), *(p_Data + i)); } + Error = ESP_FAIL; + if (xSemaphoreTake(_I2C_Mutex, portMAX_DELAY) == pdTRUE) { Error = i2c_master_receive(*p_Dev_Handle, p_Data, Length, I2C_WAIT); xSemaphoreGive(_I2C_Mutex); @@ -122,6 +135,7 @@ int32_t I2CM_Read(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t *p_Data, uint32 ESP_LOGW(TAG, "I2C receive failed: %d", Error); } } + return Error; } @@ -129,12 +143,15 @@ int32_t I2CM_ModifyRegister(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Regis { int32_t Error; uint8_t Data[2] = {Register, 0xFF}; + Error = I2CM_Write(p_Dev_Handle, &Data[0], 1) || I2CM_Read(p_Dev_Handle, &Data[1], 1); if (Error) { return Error; } + Data[1] &= ~Mask; Data[1] |= Value; ESP_LOGD(TAG, "Modify Register 0x%02X with mask 0x%02X: 0x%02X", Register, Mask, Data[1]); + return I2CM_Write(p_Dev_Handle, Data, sizeof(Data)); } \ No newline at end of file diff --git a/main/Application/Manager/Devices/devicesManager.cpp b/main/Application/Manager/Devices/devicesManager.cpp index 19df7d0..f2630d2 100644 --- a/main/Application/Manager/Devices/devicesManager.cpp +++ b/main/Application/Manager/Devices/devicesManager.cpp @@ -111,11 +111,6 @@ esp_err_t DevicesManager_Init(void) return ESP_FAIL; } - if (ADC_Init() != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize ADC!"); - return ESP_FAIL; - } - if (PortExpander_Init(&_Devices_Manager_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { ESP_LOGE(TAG, "Failed to set default configuration for port expander!"); return ESP_FAIL; @@ -171,9 +166,8 @@ i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void) return _Devices_Manager_State.I2C_Bus_Handle; } -esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage) +esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, uint8_t *p_Percentage) { - int Raw; esp_err_t Error; if (_Devices_Manager_State.initialized == false) { @@ -185,7 +179,7 @@ esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage) PortExpander_EnableBatteryVoltage(true); - Error = ADC_ReadBattery(&Raw); + Error = ADC_ReadBattery(p_Voltage, p_Percentage); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to read battery voltage: %d", Error); @@ -196,15 +190,6 @@ esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage) PortExpander_EnableBatteryVoltage(false); - *p_Voltage = Raw * (BATTERY_R1 + BATTERY_R2) / BATTERY_R2; - - *p_Percentage = (*p_Voltage - BATTERY_MIN_VOLTAGE) * 100 / (BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE); - if (*p_Percentage < 0) { - *p_Percentage = 0; - } else if (*p_Percentage > 100) { - *p_Percentage = 100; - } - return ESP_OK; } @@ -222,4 +207,4 @@ esp_err_t DevicesManager_GetRTCHandle(i2c_master_dev_handle_t *p_Handle) *p_Handle = _Devices_Manager_State.RTC_Handle; return ESP_OK; -} \ No newline at end of file +} diff --git a/main/Application/Manager/Devices/devicesManager.h b/main/Application/Manager/Devices/devicesManager.h index cf94893..269c0b2 100644 --- a/main/Application/Manager/Devices/devicesManager.h +++ b/main/Application/Manager/Devices/devicesManager.h @@ -50,7 +50,7 @@ i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void); * @param p_Percentage Pointer to store percentage (0-100) * @return ESP_OK on success */ -esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, int *p_Percentage); +esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, uint8_t *p_Percentage); /** @brief Get the RTC device handle (for Time Manager). * @param p_Handle Pointer to store the RTC handle diff --git a/main/Application/Manager/Network/SNTP/sntp.cpp b/main/Application/Manager/Network/SNTP/sntp.cpp index 5b8f918..d1e26bf 100644 --- a/main/Application/Manager/Network/SNTP/sntp.cpp +++ b/main/Application/Manager/Network/SNTP/sntp.cpp @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: SNTP management implementation. + * File info: SNTP client implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,7 +26,8 @@ #include #include "sntp.h" -#include "../networkManager.h" + +ESP_EVENT_DEFINE_BASE(SNTP_EVENTS); static const char *TAG = "sntp"; @@ -37,22 +38,28 @@ static void on_SNTP_Time_Sync(struct timeval *p_tv) { ESP_LOGD(TAG, "Time synchronized via SNTP"); - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SNTP_SYNCED, p_tv, sizeof(struct timeval), portMAX_DELAY); + esp_event_post(SNTP_EVENTS, SNTP_EVENT_SNTP_SYNCED, p_tv, sizeof(struct timeval), portMAX_DELAY); } -esp_err_t SNTP_Init(void) +esp_err_t SNTP_Init(const char* p_Timezone, const char* p_Server, uint32_t SyncInterval) { esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); - esp_sntp_setservername(0, "pool.ntp.org"); + esp_sntp_setservername(0, p_Server); esp_sntp_set_time_sync_notification_cb(on_SNTP_Time_Sync); esp_sntp_init(); + SNTP_SetTimezone(p_Timezone); + + /* Setup automatic sync timer if interval is specified */ + esp_sntp_set_sync_interval(3600); + return ESP_OK; } esp_err_t SNTP_Deinit(void) { esp_sntp_stop(); + return ESP_OK; } @@ -84,4 +91,12 @@ esp_err_t SNTP_GetTime(uint8_t Retries) localtime_r(&Now, &TimeInfo); return ESP_OK; +} + +void SNTP_SetTimezone(const char* p_Timezone) +{ + setenv("TZ", p_Timezone, 1); + tzset(); + + esp_event_post(SNTP_EVENTS, SNTP_EVENT_TZ_CHANGED, p_Timezone, strlen(p_Timezone) + 1, portMAX_DELAY); } \ No newline at end of file diff --git a/main/Application/Manager/Network/SNTP/sntp.h b/main/Application/Manager/Network/SNTP/sntp.h index 053f3eb..8eefa04 100644 --- a/main/Application/Manager/Network/SNTP/sntp.h +++ b/main/Application/Manager/Network/SNTP/sntp.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: SNTP management. + * File info: SNTP client implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,13 +25,28 @@ #define SNTP_H_ #include +#include #include -/** @brief Initialize SNTP and event handlers. - * @return ESP_OK on success +/** @brief SNTP event types (used as event IDs in SNTP_EVENTS base). + */ +typedef enum { + SNTP_EVENT_SNTP_SYNCED, /**< SNTP time synchronization completed + Data is of type struct timeval */ + SNTP_EVENT_TZ_CHANGED, /**< Timezone changed + Data is of type const char* */ +} SNTP_Event_t; + +ESP_EVENT_DECLARE_BASE(SNTP_EVENTS); + +/** @brief Initialize SNTP and event handlers. + * @param p_Timezone Timezone string (e.g. "CET-1CEST,M3.5.0,M10.5.0/3") + * @param p_Server NTP server address (e.g. "pool.ntp.org") + * @param SyncInterval SNTP sync interval in seconds + * @return ESP_OK on success */ -esp_err_t SNTP_Init(void); +esp_err_t SNTP_Init(const char* p_Timezone = "CET-1CEST,M3.5.0,M10.5.0/3", const char* p_Server = "pool.ntp.org", uint32_t SyncInterval = 3600); /** @brief Deinitialize SNTP and event handlers. * @return ESP_OK on success @@ -44,4 +59,9 @@ esp_err_t SNTP_Deinit(void); */ esp_err_t SNTP_GetTime(uint8_t Retries); +/** @brief Set SNTP timezone. + * @param p_Timezone Timezone string (e.g. "CET-1CEST,M3.5.0,M10.5.0/3") + */ +void SNTP_SetTimezone(const char* p_Timezone); + #endif /* SNTP_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Network/Server/http_server.cpp b/main/Application/Manager/Network/Server/http_server.cpp index 2d859cc..e06e82a 100644 --- a/main/Application/Manager/Network/Server/http_server.cpp +++ b/main/Application/Manager/Network/Server/http_server.cpp @@ -34,9 +34,10 @@ #include #include "http_server.h" -#include "../networkTypes.h" #include "ImageEncoder/imageEncoder.h" +#include "../networkTypes.h" #include "../Provisioning/provisionHandlers.h" +#include "../SNTP/sntp.h" #define HTTP_SERVER_API_BASE_PATH "/api/v1" #define HTTP_SERVER_API_KEY_HEADER "X-API-Key" @@ -198,8 +199,7 @@ static esp_err_t HTTP_Handler_Time(httpd_req_t *p_Request) /* Set timezone if provided */ if (cJSON_IsString(timezone) && (timezone->valuestring != NULL)) { - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SET_TZ, (void *)timezone->valuestring, strlen(timezone->valuestring) + 1, - portMAX_DELAY); + SNTP_SetTimezone(timezone->valuestring); } ESP_LOGD(TAG, "Time set to epoch: %f", epoch->valuedouble); diff --git a/main/Application/Manager/Network/networkTypes.h b/main/Application/Manager/Network/networkTypes.h index 7777a25..cfcb0ec 100644 --- a/main/Application/Manager/Network/networkTypes.h +++ b/main/Application/Manager/Network/networkTypes.h @@ -90,10 +90,6 @@ typedef enum { NETWORK_EVENT_OTA_PROGRESS, NETWORK_EVENT_OTA_COMPLETED, NETWORK_EVENT_OTA_FAILED, - NETWORK_EVENT_SNTP_SYNCED, /**< SNTP time synchronization completed - Data is of type struct timeval */ - NETWORK_EVENT_SET_TZ, /**< Set the timezone - Data is a const char* string */ NETWORK_EVENT_OPEN_WIFI_REQUEST, /**< Request to open a WiFi connection */ NETWORK_EVENT_SERVER_STARTED, /**< HTTP/WebSocket server started */ NETWORK_EVENT_SERVER_STOPPED, /**< HTTP/WebSocket server stopped */ diff --git a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp index e3077db..1ca0482 100644 --- a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp @@ -82,7 +82,7 @@ void SettingsManager_InitDefaults(SettingsManager_State_t *p_State) SettingsManager_InitDefaultDisplay(&p_State->Settings); SettingsManager_InitDefaultProvisioning(&p_State->Settings); SettingsManager_InitDefaultWiFi(&p_State->Settings); - SettingsManager_InitDefaultSystem(p_State); + SettingsManager_InitDefaultSystem(&p_State->Settings); SettingsManager_InitDefaultLepton(&p_State->Settings); SettingsManager_InitDefaultHTTPServer(&p_State->Settings); SettingsManager_InitDefaultVISAServer(&p_State->Settings); @@ -111,28 +111,29 @@ void SettingsManager_InitDefaultWiFi(App_Settings_t *p_Settings) p_Settings->WiFi.AutoConnect = SETTINGS_WIFI_DEFAULT_AUTOCONNECT; p_Settings->WiFi.MaxRetries = SETTINGS_WIFI_DEFAULT_MAX_RETRIES; p_Settings->WiFi.RetryInterval = SETTINGS_WIFI_DEFAULT_RETRY_INTERVAL; - strncpy(p_Settings->WiFi.SSID, "", sizeof(p_Settings->WiFi.SSID)); - strncpy(p_Settings->WiFi.Password, "", sizeof(p_Settings->WiFi.Password)); + strncpy(p_Settings->WiFi.SSID, SETTINGS_WIFI_DEFAULT_SSID, sizeof(p_Settings->WiFi.SSID)); + strncpy(p_Settings->WiFi.Password, SETTINGS_WIFI_DEFAULT_PASSWORD, sizeof(p_Settings->WiFi.Password)); } -void SettingsManager_InitDefaultSystem(SettingsManager_State_t *p_State) +void SettingsManager_InitDefaultSystem(App_Settings_t *p_Settings) { uint8_t Mac[6]; ESP_LOGW(TAG, "Loading default System settings"); if (esp_efuse_mac_get_default(Mac) == ESP_OK) { - snprintf(p_State->Settings.System.DeviceName, sizeof(p_State->Settings.System.DeviceName), + snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), "PyroVision-%02X%02X%02X%02X%02X%02X", Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]); } else { - snprintf(p_State->Settings.System.DeviceName, sizeof(p_State->Settings.System.DeviceName), + snprintf(p_Settings->System.DeviceName, sizeof(p_Settings->System.DeviceName), SETTINGS_SYSTEM_DEFAULT_DEVICENAME); ESP_LOGW(TAG, "Failed to get MAC address, using default name"); } - p_State->Settings.System.SDCard_AutoMount = true; - strncpy(p_State->Settings.System.Timezone, SETTINGS_SYSTEM_DEFAULT_TIMEZONE, sizeof(p_State->Settings.System.Timezone)); + p_Settings->System.SDCard_AutoMount = true; + strncpy(p_Settings->System.Timezone, SETTINGS_SYSTEM_DEFAULT_TIMEZONE, sizeof(p_Settings->System.Timezone)); + strncpy(p_Settings->System.NTPServer, SETTINGS_SYSTEM_DEFAULT_NTP_SERVER, sizeof(p_Settings->System.NTPServer)); } void SettingsManager_InitDefaultLepton(App_Settings_t *p_Settings) diff --git a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp index 96635f0..f60fc1a 100644 --- a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp @@ -23,10 +23,15 @@ #include #include +#include +#include +#include #include #include #include +#include +#include #include "settingsLoader.h" #include "../settingsManager.h" @@ -151,14 +156,14 @@ static void SettingsManager_LoadWiFi(SettingsManager_State_t *p_State, const cJS if (cJSON_IsString(ssid)) { strncpy(p_State->Settings.WiFi.SSID, ssid->valuestring, sizeof(p_State->Settings.WiFi.SSID)); } else { - strncpy(p_State->Settings.WiFi.SSID, "", sizeof(p_State->Settings.WiFi.SSID)); + strncpy(p_State->Settings.WiFi.SSID, SETTINGS_WIFI_DEFAULT_SSID, sizeof(p_State->Settings.WiFi.SSID)); } cJSON *password = cJSON_GetObjectItem(wifi, "password"); if (cJSON_IsString(password)) { strncpy(p_State->Settings.WiFi.Password, password->valuestring, sizeof(p_State->Settings.WiFi.Password)); } else { - strncpy(p_State->Settings.WiFi.Password, "", sizeof(p_State->Settings.WiFi.Password)); + strncpy(p_State->Settings.WiFi.Password, SETTINGS_WIFI_DEFAULT_PASSWORD, sizeof(p_State->Settings.WiFi.Password)); } } else { SettingsManager_InitDefaultWiFi(&p_State->Settings); @@ -219,7 +224,7 @@ static void SettingsManager_LoadSystem(SettingsManager_State_t *p_State, const c sizeof(p_State->Settings.System.DeviceName)); } } else { - SettingsManager_InitDefaultSystem(p_State); + SettingsManager_InitDefaultSystem(&p_State->Settings); } } @@ -279,110 +284,168 @@ static void SettingsManager_LoadVISAServer(SettingsManager_State_t *p_State, con } } -esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State) +/** @brief Initialize and mount the SD card. + * @return ESP_OK on success + */ +static esp_err_t SettingsManager_Mount_SD_Card(void) { - uint8_t ConfigLoaded = 0; esp_err_t Error; - cJSON *json = NULL; - size_t Total = 0; - size_t Used = 0; - size_t BytesRead = 0; - FILE* SettingsFile = NULL; - char *SettingsBuffer = NULL; - long FileSize; - esp_vfs_littlefs_conf_t LittleFS_Config = { - .base_path = "/littlefs", - .partition_label = "storage", - .format_if_mount_failed = true, - .read_only = true, - .dont_mount = false + sdmmc_card_t *card; + const char mount_point[] = "/sdcard"; + + ESP_LOGD(TAG, "Initializing SD card"); + + sdmmc_host_t Host = SDSPI_HOST_DEFAULT(); + Host.slot = SPI2_HOST; + + spi_bus_config_t SPI_Config; + memset(&SPI_Config, 0, sizeof(SPI_Config)); + SPI_Config = { + .mosi_io_num = GPIO_NUM_38, + .miso_io_num = GPIO_NUM_40, + .sclk_io_num = GPIO_NUM_39, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 4000, }; - Error = nvs_get_u8(p_State->NVS_Handle, "config_loaded", &ConfigLoaded); - if ((Error == ESP_OK) && (ConfigLoaded == true)) { - ESP_LOGD(TAG, "Default config already loaded, skipping"); - return ESP_OK; + Error = spi_bus_initialize(static_cast(Host.slot), &SPI_Config, SDSPI_DEFAULT_DMA); + if (Error != ESP_OK) { + if (Error == ESP_ERR_INVALID_STATE) { + ESP_LOGD(TAG, "SPI bus already initialized, continuing..."); + } else { + ESP_LOGD(TAG, "Failed to initialize SPI: %d!", Error); + + return Error; + } } - ESP_LOGD(TAG, "Initializing LittleFS"); + sdspi_device_config_t Slot = SDSPI_DEVICE_CONFIG_DEFAULT(); + Slot.gpio_cs = GPIO_NUM_47; + Slot.host_id = static_cast(Host.slot); - Error = esp_vfs_littlefs_register(&LittleFS_Config); + esp_vfs_fat_sdmmc_mount_config_t Mount_Config = { + .format_if_mount_failed = false, + .max_files = 5, + .allocation_unit_size = 16 * 1024 + }; + + Error = esp_vfs_fat_sdspi_mount(mount_point, &Host, &Slot, &Mount_Config, &card); if (Error != ESP_OK) { if (Error == ESP_FAIL) { - ESP_LOGE(TAG, "Failed to mount or format filesystem!"); - } else if (Error == ESP_ERR_NOT_FOUND) { - ESP_LOGE(TAG, "Failed to find LittleFS partition!"); + ESP_LOGD(TAG, "Failed to mount SD card filesystem!"); } else { - ESP_LOGE(TAG, "Failed to initialize LittleFS: %d!", Error); + ESP_LOGD(TAG, "Failed to mount SD card: 0x%x!", Error); } + + return Error; + } + /* Log the mount point and list files in the directory */ + DIR *dir = opendir(mount_point); + if (dir == NULL) { + ESP_LOGE(TAG, "Failed to open mount point: %s!", mount_point); return ESP_FAIL; } - Error = esp_littlefs_info(LittleFS_Config.partition_label, &Total, &Used); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to get LittleFS partition information: %d!", Error); - } else { - ESP_LOGD(TAG, "Partition size: total: %zu, used: %zu", Total, Used); + struct dirent *entry; + ESP_LOGD(TAG, "Files in mount point %s:", mount_point); + /* Enhanced logging for file names */ + while ((entry = readdir(dir)) != NULL) { + ESP_LOGD(TAG, " Found file: %s", entry->d_name); + if (strcmp(entry->d_name, "settings.json") == 0 || strcmp(entry->d_name, "SETTIN~1.JSO") == 0) { + ESP_LOGD(TAG, " Matched settings file: %s", entry->d_name); + } + } + closedir(dir); + + ESP_LOGD(TAG, "SD card mounted successfully"); + + return ESP_OK; +} + +/** @brief Unmount the SD card. + */ +static void SettingsManager_Unmount_SD_Card(void) +{ + esp_vfs_fat_sdcard_unmount("/sdcard", NULL); + ESP_LOGD(TAG, "SD card unmounted"); +} + +/** @brief Load and parse JSON settings from file. + * @param p_State Settings state structure + * @param filepath Full path to JSON file + * @return ESP_OK on success + */ +static esp_err_t SettingsManager_Load_JSON(SettingsManager_State_t *p_State, const char *p_FilePath) +{ + FILE *File = NULL; + char *Buffer = NULL; + long FileSize; + size_t BytesRead; + cJSON *JSON = NULL; + + ESP_LOGD(TAG, "Loading settings from: %s", p_FilePath); + + /* Check if file exists */ + struct stat st; + if (stat(p_FilePath, &st) != 0) { + ESP_LOGE(TAG, "File does not exist or cannot be accessed: %s!", p_FilePath); + return ESP_ERR_NOT_FOUND; } ESP_LOGD(TAG, "Opening settings file..."); - SettingsFile = fopen("/littlefs/default_settings.json", "r"); - if (SettingsFile == NULL) { - ESP_LOGE(TAG, "Failed to open file for reading!"); - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + File = fopen(p_FilePath, "r"); + if (File == NULL) { + ESP_LOGW(TAG, "Failed to open: %s!", p_FilePath); - return ESP_FAIL; + return ESP_ERR_NOT_FOUND; } /* Get file size */ - fseek(SettingsFile, 0, SEEK_END); - FileSize = ftell(SettingsFile); - fseek(SettingsFile, 0, SEEK_SET); + fseek(File, 0, SEEK_END); + FileSize = ftell(File); + fseek(File, 0, SEEK_SET); if (FileSize <= 0) { ESP_LOGE(TAG, "Invalid file size: %ld!", FileSize); - fclose(SettingsFile); - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); - return ESP_FAIL; + fclose(File); + + return ESP_ERR_INVALID_SIZE; } ESP_LOGD(TAG, "File size: %ld bytes", FileSize); /* Allocate buffer for file content */ - SettingsBuffer = (char*)heap_caps_malloc(FileSize + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (SettingsBuffer == NULL) { + Buffer = (char*)heap_caps_malloc(FileSize + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (Buffer == NULL) { ESP_LOGE(TAG, "Failed to allocate memory for file buffer!"); - fclose(SettingsFile); - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + fclose(File); return ESP_ERR_NO_MEM; } /* Read file content */ - BytesRead = fread(SettingsBuffer, 1, FileSize, SettingsFile); - fclose(SettingsFile); - SettingsFile = NULL; + BytesRead = fread(Buffer, 1, FileSize, File); + fclose(File); + Buffer[FileSize] = '\0'; if (BytesRead != FileSize) { - ESP_LOGE(TAG, "Failed to read file (read %zu of %ld bytes)", BytesRead, FileSize); - heap_caps_free(SettingsBuffer); - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + ESP_LOGE(TAG, "Read error: got %zu of %ld bytes!", BytesRead, FileSize); + + heap_caps_free(Buffer); return ESP_FAIL; } - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); - - ESP_LOGD(TAG, "File read successfully, parsing JSON..."); - /* Parse JSON */ - json = cJSON_Parse(SettingsBuffer); - heap_caps_free(SettingsBuffer); - SettingsBuffer = NULL; + JSON = cJSON_Parse(Buffer); + heap_caps_free(Buffer); + Buffer = NULL; - if (json == NULL) { + if (JSON == NULL) { const char *error_ptr = cJSON_GetErrorPtr(); if (error_ptr != NULL) { ESP_LOGE(TAG, "JSON Parse Error: %s!", error_ptr); @@ -393,30 +456,96 @@ esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State) return ESP_FAIL; } - ESP_LOGD(TAG, "JSON parsed successfully"); + ESP_LOGD(TAG, "JSON parsed successfully from %s", p_FilePath); - /* Extract display settings */ - SettingsManager_LoadDisplay(p_State, json); + /* Load settings sections */ + SettingsManager_LoadDisplay(p_State, JSON); /* Extract provisioning settings */ - SettingsManager_LoadProvisioning(p_State, json); + SettingsManager_LoadProvisioning(p_State, JSON); /* Extract WiFi settings */ - SettingsManager_LoadWiFi(p_State, json); + SettingsManager_LoadWiFi(p_State, JSON); /* Extract system settings */ - SettingsManager_LoadSystem(p_State, json); + SettingsManager_LoadSystem(p_State, JSON); /* Extract Lepton settings */ - SettingsManager_LoadLepton(p_State, json); + SettingsManager_LoadLepton(p_State, JSON); /* Extract HTTP Server settings */ - SettingsManager_LoadHTTPServer(p_State, json); + SettingsManager_LoadHTTPServer(p_State, JSON); /* Extract VISA Server settings */ - SettingsManager_LoadVISAServer(p_State, json); + SettingsManager_LoadVISAServer(p_State, JSON); + + cJSON_Delete(JSON); + + return ESP_OK; +} + +esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State) +{ + uint8_t ConfigLoaded = 0; + esp_err_t Error; + esp_vfs_littlefs_conf_t LittleFS_Config = { + .base_path = "/littlefs", + .partition_label = "storage", + .partition = NULL, + .format_if_mount_failed = true, + .read_only = true, + .dont_mount = false, + .grow_on_mount = false + }; + + Error = nvs_get_u8(p_State->NVS_Handle, "config_loaded", &ConfigLoaded); + if ((Error == ESP_OK) && (ConfigLoaded == true)) { + ESP_LOGD(TAG, "Default config already loaded, skipping"); + return ESP_OK; + } + + ESP_LOGD(TAG, "Loading settings with priority: SD Card -> LittleFS -> Built-in defaults"); + + /* 1. Try SD card */ + Error = SettingsManager_Mount_SD_Card(); + if (Error == ESP_OK) { + Error = SettingsManager_Load_JSON(p_State, "/sdcard/settings.json"); + + /* Check for 8.3 filename match */ + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Falling back to 8.3 filename: SETTIN~1.JSO"); + Error = SettingsManager_Load_JSON(p_State, "/sdcard/SETTIN~1.JSO"); + } + + SettingsManager_Unmount_SD_Card(); + + if (Error == ESP_OK) { + ESP_LOGD(TAG, "Settings loaded from SD card"); + return ESP_OK; + } + ESP_LOGW(TAG, "SD card mounted but no valid settings.json found"); + } else { + ESP_LOGD(TAG, "SD card not available, trying LittleFS"); + } + + /* 2. Try LittleFS */ + Error = esp_vfs_littlefs_register(&LittleFS_Config); + if (Error == ESP_OK) { + Error = SettingsManager_Load_JSON(p_State, "/littlefs/settings.json"); + esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); + + if (Error == ESP_OK) { + ESP_LOGD(TAG, "Settings loaded from LittleFS"); + return ESP_OK; + } + ESP_LOGW(TAG, "LittleFS mounted but no valid settings.json found"); + } else { + ESP_LOGW(TAG, "Failed to mount LittleFS: %d!", Error); + } - cJSON_Delete(json); + /* 3. Fallback to built-in defaults */ + ESP_LOGW(TAG, "Using built-in default settings"); + SettingsManager_InitDefaults(p_State); /* Mark config as loaded */ Error = nvs_set_u8(p_State->NVS_Handle, "config_loaded", true); diff --git a/main/Application/Manager/Settings/Private/settingsLoader.h b/main/Application/Manager/Settings/Private/settingsLoader.h index 21f9f1f..e0b426a 100644 --- a/main/Application/Manager/Settings/Private/settingsLoader.h +++ b/main/Application/Manager/Settings/Private/settingsLoader.h @@ -44,16 +44,19 @@ #define SETTINGS_SYSTEM_DEFAULT_DEVICENAME "PyroVision-Device" #define SETTINGS_SYSTEM_DEFAULT_TIMEZONE "CET-1CEST,M3.5.0,M10.5.0/3" +#define SETTINGS_SYSTEM_DEFAULT_NTP_SERVER "pool.ntp.org" #define SETTINGS_PROVISIONING_DEFAULT_TIMEOUT 300 #define SETTINGS_PROVISIONING_DEFAULT_NAME "PyroVision-Provision" -#define SETTINGS_WIFI_DEFAULT_MAX_RETRIES 5 -#define SETTINGS_WIFI_DEFAULT_RETRY_INTERVAL 2000 -#define SETTINGS_WIFI_DEFAULT_AUTOCONNECT true +#define SETTINGS_WIFI_DEFAULT_SSID "" +#define SETTINGS_WIFI_DEFAULT_PASSWORD "" +#define SETTINGS_WIFI_DEFAULT_MAX_RETRIES 5 +#define SETTINGS_WIFI_DEFAULT_RETRY_INTERVAL 2000 +#define SETTINGS_WIFI_DEFAULT_AUTOCONNECT true -#define SETTINGS_DISPLAY_DEFAULT_BRIGHTNESS 80 -#define SETTINGS_DISPLAY_DEFAULT_TIMEOUT 0 +#define SETTINGS_DISPLAY_DEFAULT_BRIGHTNESS 80 +#define SETTINGS_DISPLAY_DEFAULT_TIMEOUT 0 /** @brief Settings Manager state. */ @@ -101,10 +104,10 @@ void SettingsManager_InitDefaultProvisioning(App_Settings_t *p_Settings); */ void SettingsManager_InitDefaultWiFi(App_Settings_t *p_Settings); -/** @brief Initialize System settings with factory defaults. - * @param p_State Pointer to Settings Manager state structure +/** @brief Initialize System settings with factory defaults. + * @param p_Settings Pointer to settings structure */ -void SettingsManager_InitDefaultSystem(SettingsManager_State_t *p_State); +void SettingsManager_InitDefaultSystem(App_Settings_t *p_Settings); /** @brief Initialize Lepton settings with factory defaults. * @param p_Settings Pointer to settings structure diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index 98b3fd9..9045ed5 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -37,10 +37,6 @@ #include "settingsManager.h" #include "Private/settingsLoader.h" -/** @brief Settings storage namespace in NVS. - */ -#define SETTINGS_NVS_NAMESPACE "pyrovision" - static const char *TAG = "settings_manager"; ESP_EVENT_DEFINE_BASE(SETTINGS_EVENTS); @@ -104,7 +100,7 @@ esp_err_t SettingsManager_Init(void) return ESP_ERR_NO_MEM; } - Error = nvs_open_from_partition("settings", SETTINGS_NVS_NAMESPACE, NVS_READWRITE, &_State.NVS_Handle); + Error = nvs_open_from_partition("settings", CONFIG_SETTINGS_NAMESPACE, NVS_READWRITE, &_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to open NVS handle: %d!", Error); @@ -200,8 +196,13 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) } if (RequiredSize != sizeof(App_Settings_t)) { - ESP_LOGW(TAG, "Settings size mismatch (expected %u, got %u), using defaults", + ESP_LOGW(TAG, "Settings size mismatch (expected %u, got %u), erasing and using defaults", sizeof(App_Settings_t), RequiredSize); + + /* Erase the old settings */ + nvs_erase_key(_State.NVS_Handle, "settings"); + nvs_commit(_State.NVS_Handle); + xSemaphoreGive(_State.Mutex); return ESP_ERR_INVALID_SIZE; diff --git a/main/Application/Manager/Settings/settingsTypes.h b/main/Application/Manager/Settings/settingsTypes.h index 929ca0d..7b58ae8 100644 --- a/main/Application/Manager/Settings/settingsTypes.h +++ b/main/Application/Manager/Settings/settingsTypes.h @@ -143,6 +143,7 @@ typedef struct { typedef struct { bool SDCard_AutoMount; /**< Automatically mount SD card. */ char Timezone[32]; /**< Timezone string (e.g., "CET-1CEST,M3.5.0,M10.5.0/3"). */ + char NTPServer[32]; /**< NTP server address. */ char DeviceName[32]; /**< Device name. */ uint8_t Reserved[100]; /**< Reserved for future use. */ } __attribute__((packed)) App_Settings_System_t; diff --git a/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c b/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c index 4fcb8b3..4544656 100644 --- a/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c +++ b/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c @@ -17094,7 +17094,8 @@ static const uint16_t unicode_list_30[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 16, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c b/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c index 38ee026..f3cf13a 100644 --- a/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c +++ b/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c @@ -1,129 +1,129 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision #include "../ui.h" #ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN + #define LV_ATTRIBUTE_MEM_ALIGN #endif // IMAGE DATA: assets/Logo_80x44.png const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_logo_80x44_png_data[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xFD, 0x23, 0xFD, 0x45, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xE4, 0xFB, 0x40, 0xFC, 0xA0, 0xFC, 0x47, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xFB, 0x22, 0xFB, 0xA0, 0xFB, 0x00, 0xFC, 0x80, 0xFC, 0xCA, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFD, 0x23, 0xFD, 0x43, 0xFD, 0x43, 0xFD, 0x4D, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFA, 0xA1, 0xFA, 0x20, 0xFB, 0xA0, 0xFB, 0xE0, 0xFB, 0x40, 0xFC, 0xAC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0xEF, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xFC, 0xC3, 0xF9, 0x01, 0xFA, 0x81, 0xFA, 0x20, 0xFB, 0x80, 0xFB, 0xC0, 0xFB, 0x00, 0xFC, 0x87, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0xAE, 0xFD, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFA, 0x02, 0xF9, 0x62, 0xF9, 0xE1, 0xF9, 0x80, 0xFA, - 0x00, 0xFB, 0x60, 0xFB, 0xA0, 0xFB, 0xE0, 0xFB, 0x64, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0xFC, 0x81, 0xFC, 0x81, 0xFC, 0xC1, 0xFC, 0x8F, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xF9, 0x63, 0xF8, 0xE2, 0xF8, 0x62, 0xF9, 0xC1, 0xF9, 0x60, 0xFA, 0xE0, 0xFA, 0x80, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x81, 0xFC, 0x00, 0x00, 0xCF, 0xFD, 0xC7, 0xFD, 0xE4, 0xFD, 0x8A, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFA, 0x84, 0xF8, 0x03, 0xF8, 0x63, 0xF8, 0xE2, 0xF8, 0x42, 0xF9, 0xC1, 0xF9, 0x40, 0xFA, 0xC0, 0xFA, 0x60, 0xFB, 0xA0, 0xFB, 0x20, 0xFC, 0x80, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x60, 0xFD, 0xC1, 0xFD, 0xC9, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA4, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xFC, 0xE7, 0xF8, 0x04, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x43, 0xF8, 0xC2, 0xF8, 0x41, 0xF9, 0xC0, 0xF9, 0x20, 0xFA, 0x80, 0xFA, 0xE0, 0xFA, 0x00, 0xFB, 0x60, 0xFB, 0xA0, 0xFB, 0xA0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0xA1, 0xFD, 0x0B, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xA6, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0x63, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xF9, 0xAB, 0xF8, 0x28, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x43, 0xF8, 0xA2, 0xF8, 0x21, 0xF9, 0xA0, 0xF9, 0x00, 0xFA, - 0x60, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x40, 0xFB, 0x60, 0xFC, 0xC0, 0xFC, 0x00, 0xFD, 0x81, 0xFD, 0x4D, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xFE, 0x25, 0xFE, 0x25, 0xFE, 0x25, 0xFE, 0x6D, 0xFE, 0x87, 0xFD, 0x41, 0xFD, 0x21, 0xFD, 0x23, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xBC, 0x5F, 0xB3, 0x1F, 0xC3, 0xBF, 0xCB, 0x3F, 0xDC, 0x9F, 0xF4, 0x3D, 0xFC, 0x7B, 0xFB, 0x97, 0xFA, - 0xD4, 0xF9, 0x31, 0xF9, 0xAF, 0xF8, 0x2E, 0xF8, 0x0C, 0xF8, 0x0A, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x43, 0xF8, 0xA2, 0xF8, 0x21, 0xF9, 0xA0, 0xF9, 0x00, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0xE0, 0xFA, 0x20, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0x40, 0xFD, 0x62, 0xFC, 0xA2, 0xFB, 0xC2, 0xFB, 0x81, 0xFD, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x67, 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, 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, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xC3, 0xBF, 0xC2, 0x7F, 0xCA, 0x1F, 0xE2, 0x7D, 0xF9, 0xD9, 0xF8, 0x76, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x0F, 0xF8, 0x2E, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x62, 0xF8, 0xE1, 0xF8, 0x20, 0xFA, 0x60, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x40, 0xFA, 0x60, 0xFA, 0x40, 0xFB, 0x80, 0xFC, 0xC0, 0xFC, 0x00, 0xFD, 0x20, 0xFC, 0xA0, 0xFB, 0xA0, 0xFB, 0x40, 0xFD, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x87, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x7F, 0xCB, 0x1F, 0xE2, 0x7E, 0xF9, 0xFA, 0xF8, 0x96, 0xF8, 0x74, 0xF8, 0x31, 0xF8, 0x30, 0xF8, 0x2E, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x61, 0xF8, 0xA1, 0xF8, 0x00, 0xF9, 0xC0, 0xF9, 0xA0, 0xFA, 0xC0, 0xFA, 0x80, 0xFA, 0x00, 0xFA, 0x20, 0xFA, 0x60, 0xFA, 0x20, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xE0, 0xFB, 0xA0, 0xFB, 0xC0, 0xFB, 0x40, 0xFD, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, - 0x87, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFD, 0x03, 0xFD, 0x03, 0xFD, 0xE3, 0xFC, 0x30, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xEF, 0x1F, 0xDF, 0x7F, 0xEF, 0x3F, 0xDF, 0x7F, 0xE7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xFE, 0xFE, 0xF9, 0x1B, 0xF9, 0xB7, 0xF8, 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x2A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x41, 0xF8, 0x00, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, - 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x00, 0xFA, 0x40, 0xFA, 0x20, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x20, 0xFC, 0xA0, 0xFC, 0x00, 0xFD, 0x00, 0xFD, 0xC0, 0xFC, 0xE0, 0xFC, 0x40, 0xFD, 0xC7, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0x0C, 0xFD, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x7F, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0xDF, 0xFF, 0xBF, 0xF7, 0x9F, 0xF7, 0x9F, 0xF7, 0xDF, 0xFF, 0xDE, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF9, 0xD8, 0xF8, - 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0xE5, 0xFA, 0x44, 0xFA, 0x41, 0xF8, 0x40, 0xF9, 0xE0, 0xF9, 0x44, 0xFB, 0x85, 0xFC, 0x60, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0xC0, 0xF9, 0x87, 0xFE, 0x24, 0xFD, 0x60, 0xFA, 0xA0, 0xFA, 0xE0, 0xFB, 0xA0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0x20, 0xFD, 0x84, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xCC, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0x5F, 0xD7, 0x7F, 0xDF, 0xBF, 0xE7, - 0xBF, 0xE7, 0xBF, 0xE7, 0xBF, 0xE7, 0x9F, 0xE7, 0x7F, 0xD7, 0xDF, 0xB6, 0xBF, 0xF7, 0x9E, 0xFF, 0x9F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0xF9, 0x75, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x68, 0xFD, 0x89, 0xFF, 0x83, 0xFA, 0x20, 0xF9, 0xA0, 0xF9, 0xE4, 0xFB, 0xE9, 0xFF, 0x25, 0xFD, 0x60, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xA6, 0xFE, 0xC7, 0xFF, 0x82, 0xFB, 0xA0, 0xFA, 0xC0, 0xFB, 0x60, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x84, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xFC, 0x62, 0xFC, 0x62, 0xFC, 0x42, 0xFC, 0x51, 0xFD, 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, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0x3F, 0xD7, 0xBF, 0xE7, 0xBF, 0xEF, 0x9F, 0xE7, 0x5F, 0xD7, 0x3F, 0xE7, 0x5F, 0xF7, 0xFF, 0xD6, 0xFF, 0xCE, 0x5F, 0xD7, 0x7F, 0xE7, 0x7F, 0xE7, 0x1F, 0xC7, 0xBF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7E, 0xFF, 0xF5, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x27, 0xF8, 0x26, 0xF8, 0x47, 0xFD, 0xE7, 0xFF, 0xE4, 0xFD, 0x80, 0xF8, 0x60, 0xF8, 0x63, 0xFB, 0xE8, 0xFF, 0x06, 0xFF, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0xC6, 0xFE, 0xE7, 0xFF, 0x24, 0xFD, 0xE0, 0xFA, 0xE0, 0xFA, 0x20, 0xFB, 0x80, 0xFB, 0x20, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x60, 0xFD, - 0x82, 0xFD, 0xC2, 0xFD, 0xE2, 0xFD, 0x22, 0xFE, 0x49, 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, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x5F, 0xD7, 0x7F, 0xDF, 0x3F, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x9F, 0xEF, 0xDF, 0xBE, 0xFF, 0x64, 0xFF, 0xC6, 0x7F, 0xDF, 0x7F, 0xD7, 0x9F, 0xF7, 0xDE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0xFC, 0x74, 0xF8, 0x31, 0xF8, 0x10, 0xF8, 0x0E, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x26, 0xF8, 0x65, 0xFE, 0xC5, 0xFF, 0x64, 0xFE, 0x60, 0xF8, 0x40, 0xF8, 0x04, 0xFD, - 0xE6, 0xFF, 0x26, 0xFF, 0x40, 0xF9, 0x20, 0xF9, 0x41, 0xFA, 0xA6, 0xFF, 0xE7, 0xFF, 0xA3, 0xFC, 0xE0, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x40, 0xFB, 0x20, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0x00, 0xFE, 0x47, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x9F, 0xEF, 0x5F, 0xCF, 0x7F, 0xD7, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0x7F, 0xEF, 0xBF, 0xAE, 0x3F, 0x5D, 0x3F, 0x2C, 0x7F, 0x6B, 0xBF, 0xE7, 0x7F, 0xD7, 0x5F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, - 0xFF, 0xFF, 0xB5, 0xF9, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x47, 0xFA, 0x45, 0xFF, 0xA5, 0xFF, 0x03, 0xFD, 0x60, 0xF8, 0xE0, 0xF8, 0x04, 0xFF, 0xC5, 0xFF, 0x24, 0xFE, 0x20, 0xF9, 0xE0, 0xF8, 0xA4, 0xFD, 0xA5, 0xFF, 0x45, 0xFF, 0x00, 0xFA, 0x20, 0xFA, 0xC0, 0xFA, 0x40, 0xFB, 0x80, 0xFB, 0xE0, 0xFB, 0x60, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0x20, 0xFD, 0x40, 0xFD, 0x80, 0xFD, 0xC0, 0xFD, 0x27, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xEF, 0xBF, 0xFF, 0x1F, 0xC7, 0x5F, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x5F, 0xD7, 0x3F, 0x8E, 0xDF, 0x24, 0xDF, 0x1B, 0xDF, 0x22, 0x9F, 0x31, 0xFF, 0xEF, 0x3F, 0xCF, 0xBF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0xFE, 0x74, 0xF8, 0x32, 0xF8, 0x30, 0xF8, 0x0E, 0xF8, 0x0B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x64, 0xFE, 0x43, 0xFF, 0xE3, 0xFE, 0xA0, 0xF8, 0x40, 0xF8, 0x62, 0xFD, 0x63, 0xFF, 0x44, 0xFF, 0x41, 0xFA, 0x00, 0xF9, 0x61, 0xFB, 0x64, 0xFF, 0x84, 0xFF, 0x62, 0xFC, 0x80, 0xF9, 0xA0, 0xF9, 0xE0, 0xFA, 0xA0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xA0, 0xFB, 0x00, 0xFC, 0x60, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x60, 0xFD, 0xA0, 0xFD, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0xDF, 0xB6, 0x3F, 0xCF, 0x3F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x3F, 0x5C, 0x9F, 0x23, 0xDF, 0x12, 0x3F, 0x12, 0x1F, 0x40, 0x00, 0xF8, 0x3F, 0xD7, 0x9F, 0xAE, 0x7E, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xF9, 0x33, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x66, 0xFD, 0x22, 0xFF, 0x22, 0xFF, 0x41, 0xFC, 0x41, 0xF8, 0x21, 0xFB, 0x03, 0xFF, 0x23, 0xFF, 0x42, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0x42, 0xFE, 0x63, 0xFF, 0x82, 0xFE, 0x00, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0xE0, 0xFA, 0x80, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x60, 0xFD, 0xA0, 0xFD, 0xC0, 0xFD, - 0x41, 0xFE, 0x81, 0xFE, 0xA2, 0xFE, 0xC1, 0xFE, 0x82, 0xFE, 0x63, 0xFE, 0x83, 0xFE, 0x23, 0xFE, 0x02, 0xFA, 0x02, 0xFA, 0xE2, 0xF9, 0x82, 0xF9, 0x46, 0xFA, 0x08, 0xFB, 0xE8, 0xFA, 0xE8, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xE7, 0x9F, 0xF7, 0x7F, 0xD7, 0xBF, 0xB6, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xE7, 0x3F, 0xDF, 0x3F, 0xEF, 0x5F, 0xFF, 0xBF, 0x2A, 0x1F, 0x42, 0x1F, 0xF8, 0x1F, 0x50, 0x5F, 0xAD, 0x3F, 0xCF, 0xBF, 0xCE, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0xFB, 0x53, 0xF8, 0x51, 0xF8, 0x2E, 0xF8, 0x2A, 0xF8, 0x27, 0xF9, 0x02, 0xFF, 0x01, 0xFF, 0x41, 0xFE, 0x21, 0xF8, 0x40, 0xF8, 0xC1, 0xFD, 0x02, 0xFF, 0x82, 0xFE, - 0xA0, 0xF8, 0xE0, 0xF8, 0x00, 0xFB, 0x02, 0xFF, 0x22, 0xFF, 0x21, 0xFC, 0xE0, 0xF9, 0x20, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x60, 0xFC, 0xC0, 0xFE, 0xC0, 0xFE, 0xE0, 0xFE, 0x61, 0xFF, 0xE2, 0xFF, 0xE2, 0xFF, 0xE2, 0xFF, 0x81, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0xE0, 0xFD, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x80, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, 0xDF, 0xF7, 0xFF, 0xBE, 0x7F, 0xCF, 0x9F, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x7F, 0xDF, 0xFF, 0x64, 0x3F, 0x11, 0x9F, 0xE6, 0xFD, 0xFE, 0x1F, 0xF8, 0x1F, 0x30, 0x1F, 0x18, 0x1F, 0x18, 0x7F, 0xDF, 0x9F, 0xB6, 0x9F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, - 0xDF, 0xFF, 0xFF, 0xFF, 0x7E, 0xFF, 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2C, 0xF8, 0x66, 0xFD, 0xE1, 0xFE, 0xE1, 0xFE, 0x40, 0xFC, 0x80, 0xF8, 0xA0, 0xF8, 0x61, 0xFE, 0xC1, 0xFE, 0xC1, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0xE0, 0xFB, 0xC1, 0xFE, 0xE1, 0xFE, 0x60, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x80, 0xFA, 0x40, 0xFC, 0xC0, 0xFE, 0xC0, 0xFE, 0xC0, 0xFE, 0x61, 0xFF, 0xC2, 0xFF, 0xC2, 0xFF, 0xC2, 0xFF, 0x61, 0xFE, 0x20, 0xFE, 0x40, 0xFE, 0xC0, 0xFD, 0x00, 0xFA, 0x00, 0xFA, 0xC0, 0xF9, 0x80, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x7F, 0xF7, 0x9F, 0xF7, 0x1F, 0xCF, 0x3F, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, - 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x1F, 0x63, 0x1F, 0x30, 0x1F, 0x08, 0xBF, 0xC5, 0x7F, 0x93, 0x1F, 0x10, 0x1F, 0x08, 0x5F, 0x08, 0x3F, 0xCF, 0x9F, 0xDF, 0xBF, 0xFF, 0x3F, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0xE6, 0xFD, 0xC2, 0xFE, 0xA1, 0xFE, 0x21, 0xFC, 0x60, 0xF8, 0xA0, 0xF8, 0x21, 0xFE, 0xA1, 0xFE, 0xE1, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0x20, 0xFB, 0xA1, 0xFE, 0xA1, 0xFE, 0xC0, 0xFC, 0x20, 0xFA, 0x60, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0x00, 0xFC, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0xC1, 0xFE, 0x22, 0xFF, 0x02, 0xFF, 0x22, 0xFF, 0x21, 0xFE, 0xE0, 0xFD, 0x00, 0xFE, 0x80, 0xFD, 0xE0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF9, 0x60, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5D, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x1F, 0x74, 0xBF, 0xF7, 0x5F, 0xD7, 0xDF, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF7, 0xFF, 0x21, 0x5F, 0x11, 0x7F, 0x08, 0x7F, 0x29, 0xBF, 0x94, 0x7F, 0x08, 0x9F, 0x10, 0x1F, 0x11, 0x5F, 0x4A, 0xBF, 0xDF, 0x9F, 0xF7, 0x5F, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0xF9, 0x54, 0xF8, 0x53, 0xF8, 0x50, 0xF8, 0x49, 0xFC, 0xA1, 0xFE, 0x81, 0xFE, 0xA1, 0xFD, 0x40, 0xF8, 0x41, 0xF8, 0x61, 0xFD, 0x60, 0xFE, 0x41, 0xFE, 0x40, 0xFB, 0xE0, 0xF8, 0x00, 0xF9, 0x01, 0xFE, 0x61, 0xFE, 0x00, 0xFE, 0xA0, 0xFA, 0x80, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0xC0, 0xFA, 0x00, 0xFB, 0x20, 0xFB, 0xE0, 0xFB, 0xA0, 0xFC, 0xC0, 0xFC, - 0x00, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0xA0, 0xFD, 0xC0, 0xFD, 0xC1, 0xFD, 0x44, 0xFD, 0x04, 0xFA, 0xE4, 0xF9, 0xE4, 0xF9, 0xC5, 0xF9, 0x4C, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0xBF, 0xF7, 0x1F, 0xCF, 0xDF, 0x8D, 0x9F, 0xB6, 0x7F, 0x9E, 0x5F, 0x8E, 0x9F, 0x6D, 0xBF, 0xF7, 0xBF, 0x9E, 0xBF, 0xAE, 0x3F, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xFF, 0x08, 0x9F, 0x09, 0xDF, 0x09, 0x1F, 0x11, 0x5F, 0x09, 0xBF, 0x63, 0x1F, 0x11, 0x7F, 0x11, 0xDF, 0x19, 0x9F, 0x19, 0xBF, 0xDF, 0x5F, 0xE7, 0xBF, 0xF7, 0xFE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0xF9, 0x75, 0xF8, 0x54, 0xF8, 0x52, 0xF8, 0x4F, 0xF8, 0x23, 0xFE, 0x20, 0xFE, 0x00, 0xFE, 0x41, 0xFC, 0x01, 0xF8, 0xE1, 0xF9, 0x01, 0xFE, 0x20, 0xFE, - 0xC0, 0xFD, 0x20, 0xFA, 0x00, 0xF9, 0x81, 0xFB, 0x21, 0xFE, 0x00, 0xFE, 0x81, 0xFD, 0x80, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0xC0, 0xFA, 0x20, 0xFB, 0x20, 0xFB, 0xA0, 0xFB, 0x60, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0xC1, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0xFB, 0x62, 0xFB, 0x61, 0xFB, 0x44, 0xFB, 0x00, 0x00, 0xFD, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x5F, 0xBE, 0x9F, 0xFF, 0x3F, 0xCF, 0xBF, 0x85, 0xBF, 0x65, 0x1F, 0x66, 0xDF, 0x44, 0x9F, 0x2B, 0x9F, 0xEF, 0x9F, 0x12, 0x1F, 0x00, 0x7F, 0x62, 0x1F, 0x20, 0x5F, 0x10, 0x5F, 0x11, 0x5F, 0x12, 0x5F, 0x12, 0x3F, 0x1A, 0x7F, 0x1A, 0xBF, 0x53, 0x3F, 0x1A, 0x5F, 0x22, 0x5F, 0x2A, 0xDF, 0x21, 0xBF, 0xE7, 0x5F, 0xDF, 0x9F, 0xF7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7A, 0xF9, 0x97, 0xF8, 0x75, 0xF8, 0x53, 0xF8, 0x51, 0xF8, 0x4E, 0xFA, 0xA2, 0xFD, 0x80, 0xFD, 0x40, 0xFD, 0xE1, 0xF9, 0x00, 0xF8, 0xA2, 0xFB, 0xA0, 0xFD, 0xC0, 0xFD, 0xE0, 0xFC, 0x00, 0xF9, 0x01, 0xF8, 0x21, 0xFC, 0xA0, 0xFD, 0xA0, 0xFD, 0x60, 0xFC, 0x20, 0xF9, 0x40, 0xF9, 0x60, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xE0, 0xFA, 0x60, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x43, 0xFB, 0x00, 0x00, 0x7C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x1F, 0x53, 0x5F, 0xF7, 0xFF, 0xBE, 0x9F, 0xA6, 0x5F, 0x34, 0x7F, 0x24, 0x1F, 0x23, 0x9F, 0x19, 0x3D, 0xFF, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x40, - 0x1F, 0x10, 0xFF, 0x10, 0x5F, 0x12, 0xDF, 0x12, 0x7F, 0x12, 0xDF, 0x1A, 0x1F, 0x2B, 0xDF, 0x53, 0xFF, 0x2A, 0xFF, 0x2A, 0xFF, 0x32, 0x7F, 0x22, 0xBF, 0xE7, 0x9F, 0xEF, 0xBF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7B, 0xF9, 0x98, 0xF8, 0x76, 0xF8, 0x75, 0xF8, 0x53, 0xF8, 0x51, 0xF8, 0x4B, 0xFB, 0x00, 0xFD, 0x20, 0xFD, 0x81, 0xFC, 0x02, 0xF8, 0x03, 0xF8, 0x81, 0xFC, 0x60, 0xFD, 0x60, 0xFD, 0x61, 0xFB, 0x01, 0xF8, 0x01, 0xF8, 0xA0, 0xFC, 0x60, 0xFD, 0x40, 0xFD, 0x60, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0xA0, 0xF9, 0xE0, 0xF9, 0x20, 0xFA, 0xC0, 0xFA, 0xC0, 0xFB, 0x00, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0xFB, 0x01, 0xFB, 0x01, 0xFB, 0x24, 0xFB, 0x00, 0x00, - 0x9C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0xDF, 0xDE, 0x5F, 0xEF, 0xFF, 0xBE, 0x3F, 0xC7, 0x3F, 0x33, 0x5F, 0x22, 0x1F, 0x41, 0x1F, 0xF8, 0x5B, 0xFE, 0xFF, 0xFD, 0x1F, 0x00, 0x1F, 0xF8, 0xBF, 0x10, 0xDF, 0x11, 0x9F, 0x12, 0xDF, 0x12, 0xDF, 0x22, 0x1F, 0x23, 0xFF, 0x4B, 0x7F, 0x43, 0x5F, 0x33, 0x5F, 0x3B, 0x3F, 0x3B, 0x1F, 0xCF, 0xBF, 0xE7, 0xDF, 0xFF, 0xFF, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xF9, 0xDA, 0xF8, 0xB8, 0xF8, 0x76, 0xF8, 0x74, 0xF8, 0x51, 0xF8, 0x2F, 0xF8, 0x83, 0xFC, 0xE0, 0xFC, 0xA0, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x43, 0xF8, 0x00, 0xFD, 0x00, 0xFD, 0x60, 0xFC, 0x01, 0xF8, 0x01, 0xF8, 0x61, 0xFA, 0x20, 0xFD, 0x20, 0xFD, 0xA0, 0xFA, 0x00, 0xF9, 0x20, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, 0x00, 0xFA, 0xA0, 0xFA, - 0xA0, 0xFB, 0xE0, 0xFB, 0x20, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0x5F, 0xA6, 0x3F, 0xC7, 0xBF, 0x1A, 0xBF, 0xAA, 0x00, 0xF8, 0x00, 0xF8, 0x1F, 0xF8, 0xBE, 0xFE, 0x1F, 0x6A, 0x7F, 0x08, 0xFF, 0x28, 0x9F, 0x21, 0x1F, 0x22, 0xFF, 0x2A, 0x7F, 0x2B, 0xFF, 0x43, 0x3F, 0x54, 0x9F, 0x43, 0x9F, 0x43, 0x7F, 0x43, 0x1F, 0x43, 0x9F, 0xE7, 0x7F, 0xDF, 0xBF, 0xFF, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFD, 0x1E, 0xF9, 0xDC, 0xF8, 0xBA, 0xF8, 0x97, 0xF8, 0x75, 0xF8, 0x73, 0xF8, 0x70, 0xF8, 0x06, 0xFC, 0xA0, 0xFC, 0x60, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x03, 0xF8, - 0x80, 0xFC, 0xC0, 0xFC, 0x20, 0xFC, 0x01, 0xF8, 0x01, 0xF8, 0x81, 0xF8, 0xE0, 0xFC, 0xE0, 0xFC, 0x80, 0xFA, 0xE0, 0xF8, 0x00, 0xF9, 0x40, 0xF9, 0xC0, 0xF9, 0x00, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0xE1, 0xFB, 0x43, 0xFC, 0x63, 0xFC, 0x63, 0xFC, 0x44, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFB, 0x1C, 0xFC, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x5F, 0xE7, 0xFF, 0xE6, 0x1F, 0xBF, 0xDF, 0x8D, 0xBF, 0x52, 0x00, 0xF8, 0x1F, 0xF8, 0x1F, 0x20, 0xDF, 0x51, 0xFF, 0xEC, 0x3F, 0xAB, 0x9F, 0x39, 0x5F, 0x32, 0xDF, 0x32, 0x3F, 0x3B, 0x3F, 0x64, 0x5F, 0x64, 0xBF, 0x53, 0xDF, 0x53, 0x9F, 0x53, 0x7F, 0x53, 0x5F, 0x3B, 0xDF, 0xEF, 0x3F, 0xCF, 0x9F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x3F, 0xF9, 0x1D, 0xF9, 0xFB, 0xF8, 0xB9, 0xF8, 0x97, 0xF8, 0x94, 0xF8, 0x71, 0xF8, 0xA6, 0xFB, 0x40, 0xFC, 0x00, 0xFC, 0x04, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x60, 0xFC, 0x80, 0xFC, 0xA0, 0xFB, 0x01, 0xF8, 0x01, 0xF8, 0x61, 0xF9, 0xA0, 0xFC, 0x80, 0xFC, 0xE0, 0xF8, 0x20, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x60, 0xFB, 0x80, 0xFB, 0xC2, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xFB, 0xDC, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x5F, 0xF7, 0x9F, 0xFF, 0x7F, 0xA6, 0xFF, 0xBE, 0x9F, 0x1B, 0x1F, 0x80, 0x1F, 0x48, 0x1F, 0x68, 0x7F, 0x90, 0x7F, 0x88, 0x1F, 0xBB, - 0xFF, 0xAB, 0xDF, 0x93, 0x1F, 0x84, 0x3F, 0x84, 0x9F, 0x6B, 0xBF, 0x73, 0x1F, 0x7C, 0x3F, 0x84, 0xDF, 0x7B, 0x3F, 0x63, 0xDF, 0xEF, 0xBF, 0xEF, 0xBF, 0xF7, 0xBF, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xDA, 0x7F, 0xF9, 0x3E, 0xF9, 0x1D, 0xF9, 0xDB, 0xF8, 0xB9, 0xF8, 0x96, 0xF8, 0x73, 0xF8, 0xA4, 0xFB, 0x00, 0xFC, 0x82, 0xFB, 0x06, 0xF8, 0x06, 0xF8, 0x25, 0xF9, 0x20, 0xFC, 0x40, 0xFC, 0x81, 0xF9, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0xFB, 0x60, 0xFC, 0xE0, 0xFB, 0x80, 0xF8, 0x00, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0xE0, 0xFA, 0x00, 0xFB, 0x00, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x42, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0x40, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0xFC, 0xBD, 0xFB, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xE6, 0x7F, 0xF7, 0xFF, 0xBE, 0x1F, 0xBF, 0x1F, 0x23, 0xBF, 0xD8, 0x7F, 0xF0, 0xBF, 0xE8, 0x5F, 0xF1, 0x7F, 0xF1, 0x1F, 0xE2, 0x1F, 0xD2, 0x7F, 0xBA, 0xDF, 0xB2, 0x3F, 0xA3, 0x9F, 0xA3, 0x3F, 0xCE, 0xDF, 0xFF, 0xBF, 0x9C, 0xBF, 0xEF, 0xFF, 0xF7, 0x5F, 0xDF, 0xBF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xCB, 0x1F, 0xDA, 0xBF, 0xF1, 0x7F, 0xF9, 0x3E, 0xF9, 0xFC, 0xF8, 0xDA, 0xF8, 0xD8, 0xF8, 0xB1, 0xF9, 0xC0, 0xFB, 0xC0, 0xFB, 0xA6, 0xF9, 0x08, 0xF8, 0x07, 0xF8, 0x23, 0xFB, 0xE0, 0xFB, 0x60, 0xFB, 0x02, 0xF8, 0x01, 0xF8, 0x01, 0xF8, 0x80, 0xFB, 0xE0, 0xFB, 0xE0, 0xF9, 0x60, 0xF8, 0x00, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x60, 0xFA, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, - 0x80, 0xF9, 0x60, 0xF9, 0x41, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x20, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xFB, 0xFE, 0xFB, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0x7F, 0xF7, 0xBF, 0xCE, 0x1F, 0xC7, 0xBF, 0xB6, 0xBF, 0x3A, 0x3E, 0xF9, 0xBB, 0xF8, 0x1A, 0xF9, 0x3B, 0xF9, 0xBC, 0xF9, 0xFE, 0xF9, 0x5F, 0xF2, 0xBF, 0xEA, 0xFF, 0xD2, 0x3F, 0xCB, 0xFF, 0xCC, 0x5F, 0xEF, 0x9F, 0xE7, 0xFF, 0xFF, 0x9F, 0xE7, 0xDF, 0xFF, 0x3F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x9F, 0xBA, 0x3F, 0xD2, 0xFF, 0xE1, 0x7F, 0xF1, 0x5F, 0xF9, 0x3E, 0xF9, 0x1C, 0xF9, 0xD9, 0xF8, 0x47, 0xFB, 0xA0, 0xFB, 0xC6, 0xFA, 0x2A, 0xF8, 0x09, 0xF8, 0x27, 0xF9, 0x80, 0xFB, - 0x60, 0xFB, 0x82, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x20, 0xFA, 0x40, 0xFB, 0x60, 0xFA, 0x41, 0xF8, 0x41, 0xF8, 0xC0, 0xF9, 0x60, 0xFA, 0x80, 0xFA, 0x40, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x62, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xF9, 0xA6, 0xF9, 0xA6, 0xF9, 0xE7, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0xBF, 0xFB, 0x3F, 0xFD, 0xDF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0x7F, 0xE7, 0xBF, 0xFF, 0xFF, 0xD6, 0x1F, 0xC7, 0xFF, 0xC6, 0x3F, 0x5D, 0x3F, 0xBA, 0x39, 0xF9, 0xF8, 0xF8, 0x19, 0xF9, 0x7B, 0xF9, 0xDD, 0xF9, 0x5E, 0xFA, 0xBF, 0xEA, 0xDF, 0xDA, 0x5F, 0x73, 0xDF, 0xF7, 0xFF, 0xF7, 0x9F, 0xE7, 0xDF, 0xFF, 0x5F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xA2, 0x7F, 0xB2, 0x3F, 0xC2, 0xFF, 0xD9, 0xDF, 0xE9, 0x7F, 0xF9, 0x5F, 0xF9, 0x3D, 0xF9, 0x58, 0xF9, 0x09, 0xFB, 0xC9, 0xFA, 0x2E, 0xF8, 0x0C, 0xF8, 0x0A, 0xF8, 0x67, 0xF9, 0x84, 0xFA, 0x44, 0xF9, 0x03, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x01, 0xF8, 0x61, 0xF8, 0x21, 0xF8, 0x42, 0xF8, 0x42, 0xF8, 0x41, 0xF9, 0xE0, 0xF9, 0x40, 0xFA, 0x80, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xFA, 0x08, 0xFA, 0xE7, 0xF9, 0x69, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xF3, 0xBF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x5F, 0xE7, 0xBF, 0xFF, 0xBF, 0xD6, 0xBF, 0xBE, 0x1F, 0xCF, 0xFF, 0xC6, 0xBF, 0x8D, 0x5F, 0x1B, - 0x9F, 0xAA, 0x1F, 0xFA, 0x7F, 0xEA, 0xFF, 0x42, 0xDF, 0xBE, 0xFF, 0xF7, 0xFF, 0xF7, 0xDF, 0xF7, 0xBF, 0xE7, 0xDF, 0xF7, 0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x9C, 0xBF, 0x9A, 0x7F, 0xAA, 0x3F, 0xBA, 0x1F, 0xD2, 0xFF, 0xE9, 0xBF, 0xF1, 0x7F, 0xF9, 0x5E, 0xF9, 0x1B, 0xF9, 0xB7, 0xF8, 0x53, 0xF8, 0x30, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x03, 0xF8, 0x02, 0xF8, 0x22, 0xF8, 0x21, 0xF8, 0x22, 0xF8, 0x22, 0xF8, 0x40, 0xF9, 0xC0, 0xF9, 0x00, 0xFA, 0x60, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xF8, 0x80, 0xF8, 0x80, 0xF8, 0xE3, 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, 0x7F, 0xF5, 0x7F, 0xEB, 0x7F, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x1F, 0xEF, 0x1F, 0xEF, 0x7F, 0xBE, 0xBF, 0xBE, 0x3F, 0xD7, 0x7F, 0xDF, 0x7F, 0xE7, 0xDF, 0xEF, 0xDF, 0xF7, 0xFF, 0xF7, 0xFF, 0xF7, 0xFF, 0xF7, 0xBF, 0xEF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x8C, 0x1F, 0x7B, 0xDF, 0x92, 0x7F, 0xA2, 0x5F, 0xB2, 0x3F, 0xD2, 0xFF, 0xE9, 0xDF, 0xF9, 0x9F, 0xF9, 0x7E, 0xF9, 0x1C, 0xF9, 0xD8, 0xF8, 0x74, 0xF8, 0x30, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x80, 0xF8, 0x80, 0xF8, 0x40, 0xF8, 0x21, 0xF8, 0x40, 0xF8, 0x60, 0xF8, 0x80, 0xF8, 0xC0, 0xF8, 0x21, 0xF9, 0x07, 0xFB, 0x28, 0xFB, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0xE3, 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, 0x3F, 0xEC, 0x5F, 0xE3, 0x7F, 0xDB, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x8D, 0x1F, 0xEF, 0x5F, 0xEF, 0x1F, 0xEF, 0xFF, 0xCE, 0x3F, 0xCF, 0x7F, 0xE7, 0x9F, 0xE7, 0x9F, 0xE7, 0x9F, 0xF7, 0xBF, 0xFF, 0xDF, 0xFF, 0x7F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7C, 0x5F, 0x5B, 0x3F, 0x73, 0xFF, 0x8A, 0x9F, 0x9A, 0x5F, 0xB2, 0x3F, 0xCA, 0x1F, 0xE2, 0x1F, 0xFA, 0xDF, 0xF9, 0x7E, 0xF9, 0x3B, 0xF9, 0xF8, 0xF8, 0xB5, 0xF8, 0x51, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, - 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x80, 0xF8, 0xA0, 0xF8, 0x40, 0xF8, 0x20, 0xF8, 0x40, 0xF8, 0x60, 0xF8, 0x80, 0xF8, 0xA0, 0xF8, 0x23, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0xC2, 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, 0x5F, 0xDC, 0x1F, 0xCB, 0x3F, 0xC3, 0xBF, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x5F, 0xEF, 0x5F, 0xB6, 0x5F, 0xEF, 0xBF, 0xFF, 0xBF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x9F, 0xE7, 0xBF, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x5B, 0x7F, 0x4B, 0x7F, 0x53, 0x5F, 0x6B, - 0x3F, 0x7B, 0xFF, 0x9A, 0x5F, 0xAB, 0x5F, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xFC, 0xDA, 0xFA, 0xB6, 0xF9, 0xF2, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x24, 0xF8, 0x61, 0xF8, 0x81, 0xF8, 0x21, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x4C, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xFB, 0x6D, 0xFB, 0xCF, 0xFB, 0x30, 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, 0xDF, 0xD4, 0x1F, 0xBB, 0x1F, 0xB3, 0x1F, 0xB4, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0x9F, 0x94, 0x1F, 0x5B, 0x3F, 0x4B, 0x9F, 0x5B, 0xDF, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xF9, 0xEA, 0xF8, 0x48, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x01, 0xF8, 0x00, 0xF8, 0x20, 0xF8, 0x60, 0xF8, 0xA1, 0xF8, 0x8A, 0xFA, 0x00, 0x00, 0xE8, 0xFA, 0x63, 0xFA, 0x63, 0xFA, 0x09, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xAB, 0xFF, 0xA2, 0x1F, 0xA3, 0x7F, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xAD, 0xDF, 0x7B, 0x1F, 0xE7, 0xFF, 0xFF, 0x5F, 0xEF, 0x1F, 0xA5, 0x1F, 0x94, 0x9F, 0x9B, 0x5F, 0xAB, 0x5F, 0xBB, 0x3F, 0xC3, 0x9F, 0xD3, 0x1F, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xFB, 0xA8, 0xF9, 0xE6, 0xF8, 0xA4, 0xF8, 0x63, 0xF8, 0x63, 0xF8, 0x62, 0xF8, 0xA3, 0xF8, 0x04, 0xF9, 0x49, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFA, 0x20, 0xFA, 0x40, 0xFA, - 0x85, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xBC, 0x3F, 0x9B, 0xDF, 0x82, 0x1F, 0x73, 0x9F, 0x73, 0xDF, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xCE, 0x5F, 0x6C, 0xDF, 0x4B, 0x9F, 0x43, 0x7F, 0x4B, 0x7F, 0x63, 0x5F, 0x6B, 0x3F, 0x73, 0x3F, 0x83, 0x1F, 0x93, 0xDF, 0xA2, 0x9F, 0xB2, 0x5F, 0xC2, 0x3F, 0xD2, 0x3F, 0xE2, 0x3F, 0xEA, 0x7F, 0xFA, 0x7D, 0xFA, 0x3B, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 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, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x65, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xAC, 0x5F, 0x7B, 0x3F, 0x63, 0x5F, 0x53, 0x5F, 0x4B, 0x5F, 0x43, 0x7F, 0x3B, 0x7F, 0x3B, 0x9F, 0x33, 0x9F, 0x33, 0x9F, 0x2B, 0x9F, 0x2B, 0x9F, 0x2B, 0x7F, 0x2B, 0x9F, 0x2B, 0x9F, 0x33, 0x9F, 0x3B, 0x7F, 0x4B, 0x7F, 0x5B, 0x7F, 0x6B, 0x5F, 0x73, 0x3F, 0x83, - 0x1F, 0x93, 0xFF, 0xA2, 0xDF, 0xB2, 0x9F, 0xC2, 0x9F, 0xD2, 0x7F, 0xE2, 0x5F, 0xF2, 0x3E, 0xFA, 0xBB, 0xF9, 0x78, 0xF9, 0x56, 0xF9, 0xF4, 0xF9, 0x56, 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, 0xCD, 0xFB, 0xEE, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x8C, 0xDF, 0x5B, 0x7F, 0x4B, - 0x7F, 0x3B, 0x7F, 0x33, 0x9F, 0x2B, 0x9F, 0x2B, 0x7F, 0x2B, 0x9F, 0x2B, 0x9F, 0x2B, 0x9F, 0x33, 0xBF, 0x3B, 0xDF, 0x43, 0x1F, 0x54, 0x5F, 0x6C, 0x3F, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0xFD,0x23,0xFD,0x45,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xE4,0xFB,0x40,0xFC,0xA0,0xFC,0x47,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0xFB,0x22,0xFB,0xA0,0xFB,0x00,0xFC,0x80,0xFC,0xCA,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFD,0x23,0xFD,0x43,0xFD,0x43,0xFD,0x4D,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xFA,0xA1,0xFA,0x20,0xFB,0xA0,0xFB,0xE0,0xFB,0x40,0xFC,0xAC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFD,0x00,0xFD,0x00,0xFD,0x20,0xFD,0xEF,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xFC,0xC3,0xF9,0x01,0xFA,0x81,0xFA,0x20,0xFB,0x80,0xFB,0xC0,0xFB,0x00,0xFC,0x87,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0xFC,0xA0,0xFC,0xA0,0xFC,0xE0,0xFC,0xAE,0xFD,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xFA,0x02,0xF9,0x62,0xF9,0xE1,0xF9,0x80,0xFA, + 0x00,0xFB,0x60,0xFB,0xA0,0xFB,0xE0,0xFB,0x64,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0xFC,0x81,0xFC,0x81,0xFC,0xC1,0xFC,0x8F,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0xF9,0x63,0xF8,0xE2,0xF8,0x62,0xF9,0xC1,0xF9,0x60,0xFA,0xE0,0xFA,0x80,0xFB,0xC0,0xFB,0x40,0xFC,0x81,0xFC,0x00,0x00,0xCF,0xFD,0xC7,0xFD,0xE4,0xFD,0x8A,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0xFA,0x84,0xF8,0x03,0xF8,0x63,0xF8,0xE2,0xF8,0x42,0xF9,0xC1,0xF9,0x40,0xFA,0xC0,0xFA,0x60,0xFB,0xA0,0xFB,0x20,0xFC,0x80,0xFC,0xE0,0xFC,0x20,0xFD,0x60,0xFD,0xC1,0xFD,0xC9,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xFD,0xA1,0xFD,0xA1,0xFD,0xA4,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xFC,0xE7,0xF8,0x04,0xF8,0x04,0xF8,0x03,0xF8,0x43,0xF8,0xC2,0xF8,0x41,0xF9,0xC0,0xF9,0x20,0xFA,0x80,0xFA,0xE0,0xFA,0x00,0xFB,0x60,0xFB,0xA0,0xFB,0xA0,0xFC,0xE0,0xFC,0x20,0xFD,0xA1,0xFD,0x0B,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xA6,0xFD,0x80,0xFD,0x60,0xFD,0x63,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xF9,0xAB,0xF8,0x28,0xF8,0x06,0xF8,0x05,0xF8,0x05,0xF8,0x04,0xF8,0x43,0xF8,0xA2,0xF8,0x21,0xF9,0xA0,0xF9,0x00,0xFA, + 0x60,0xFA,0xA0,0xFA,0xC0,0xFA,0x00,0xFB,0x40,0xFB,0x60,0xFC,0xC0,0xFC,0x00,0xFD,0x81,0xFD,0x4D,0xFE,0x00,0x00,0x00,0x00,0x2A,0xFE,0x25,0xFE,0x25,0xFE,0x25,0xFE,0x6D,0xFE,0x87,0xFD,0x41,0xFD,0x21,0xFD,0x23,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xBC,0x5F,0xB3,0x1F,0xC3,0xBF,0xCB,0x3F,0xDC,0x9F,0xF4,0x3D,0xFC,0x7B,0xFB,0x97,0xFA, + 0xD4,0xF9,0x31,0xF9,0xAF,0xF8,0x2E,0xF8,0x0C,0xF8,0x0A,0xF8,0x09,0xF8,0x07,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x43,0xF8,0xA2,0xF8,0x21,0xF9,0xA0,0xF9,0x00,0xFA,0x40,0xFA,0x80,0xFA,0xA0,0xFA,0xC0,0xFA,0xE0,0xFA,0x20,0xFC,0xA0,0xFC,0xE0,0xFC,0x40,0xFD,0x62,0xFC,0xA2,0xFB,0xC2,0xFB,0x81,0xFD,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x67,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,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,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xC3,0xBF,0xC2,0x7F,0xCA,0x1F,0xE2,0x7D,0xF9,0xD9,0xF8,0x76,0xF8,0x53,0xF8,0x31,0xF8,0x0F,0xF8,0x2E,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x62,0xF8,0xE1,0xF8,0x20,0xFA,0x60,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x40,0xFA,0x60,0xFA,0x40,0xFB,0x80,0xFC,0xC0,0xFC,0x00,0xFD,0x20,0xFC,0xA0,0xFB,0xA0,0xFB,0x40,0xFD,0x40,0xFE,0x40,0xFE,0x40,0xFE,0x87,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x7F,0xCB,0x1F,0xE2,0x7E,0xF9,0xFA,0xF8,0x96,0xF8,0x74,0xF8,0x31,0xF8,0x30,0xF8,0x2E,0xF8,0x2D,0xF8,0x2B,0xF8,0x0A,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x61,0xF8,0xA1,0xF8,0x00,0xF9,0xC0,0xF9,0xA0,0xFA,0xC0,0xFA,0x80,0xFA,0x00,0xFA,0x20,0xFA,0x60,0xFA,0x20,0xFC,0x80,0xFC,0xA0,0xFC,0xE0,0xFB,0xA0,0xFB,0xC0,0xFB,0x40,0xFD,0x40,0xFE,0x40,0xFE,0x40,0xFE, + 0x87,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xFD,0x03,0xFD,0x03,0xFD,0xE3,0xFC,0x30,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xEF,0x1F,0xDF,0x7F,0xEF,0x3F,0xDF,0x7F,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xFE,0xFE,0xF9,0x1B,0xF9,0xB7,0xF8,0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x2A,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x41,0xF8,0x00,0xF9,0x80,0xF9,0xC0,0xF9, + 0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x00,0xFA,0x40,0xFA,0x20,0xFB,0x20,0xFB,0x40,0xFB,0x20,0xFC,0xA0,0xFC,0x00,0xFD,0x00,0xFD,0xC0,0xFC,0xE0,0xFC,0x40,0xFD,0xC7,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFC,0xE0,0xFC,0xC0,0xFC,0xC0,0xFC,0x0C,0xFD,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xDF,0xFF,0x7F,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0xDF,0xFF,0xBF,0xF7,0x9F,0xF7,0x9F,0xF7,0xDF,0xFF,0xDE,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xF9,0xD8,0xF8, + 0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x09,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0xE5,0xFA,0x44,0xFA,0x41,0xF8,0x40,0xF9,0xE0,0xF9,0x44,0xFB,0x85,0xFC,0x60,0xF9,0x80,0xF9,0xA0,0xF9,0xC0,0xF9,0x87,0xFE,0x24,0xFD,0x60,0xFA,0xA0,0xFA,0xE0,0xFB,0xA0,0xFC,0xE0,0xFC,0xC0,0xFC,0xA0,0xFC,0xC0,0xFC,0x20,0xFD,0x84,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0xFC,0xA0,0xFC,0x80,0xFC,0x80,0xFC,0xCC,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xEF,0xDF,0xFF,0xDF,0xFF,0x5F,0xD7,0x7F,0xDF,0xBF,0xE7, + 0xBF,0xE7,0xBF,0xE7,0xBF,0xE7,0x9F,0xE7,0x7F,0xD7,0xDF,0xB6,0xBF,0xF7,0x9E,0xFF,0x9F,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x98,0xF9,0x75,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x0A,0xF8,0x08,0xF8,0x07,0xF8,0x06,0xF8,0x68,0xFD,0x89,0xFF,0x83,0xFA,0x20,0xF9,0xA0,0xF9,0xE4,0xFB,0xE9,0xFF,0x25,0xFD,0x60,0xF9,0x80,0xF9,0x80,0xF9,0xA6,0xFE,0xC7,0xFF,0x82,0xFB,0xA0,0xFA,0xC0,0xFB,0x60,0xFC,0x80,0xFC,0xA0,0xFC,0xC0,0xFC,0xE0,0xFC,0x20,0xFD,0x84,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,0xFC,0x62,0xFC,0x62,0xFC,0x42,0xFC,0x51,0xFD,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,0xDF,0xFF,0xDF,0xFF,0xBF,0xFF,0xBF,0xFF,0x3F,0xD7,0xBF,0xE7,0xBF,0xEF,0x9F,0xE7,0x5F,0xD7,0x3F,0xE7,0x5F,0xF7,0xFF,0xD6,0xFF,0xCE,0x5F,0xD7,0x7F,0xE7,0x7F,0xE7,0x1F,0xC7,0xBF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x7E,0xFF,0xF5,0xF8,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0x2D,0xF8,0x2C,0xF8,0x0A,0xF8,0x08,0xF8,0x27,0xF8,0x26,0xF8,0x47,0xFD,0xE7,0xFF,0xE4,0xFD,0x80,0xF8,0x60,0xF8,0x63,0xFB,0xE8,0xFF,0x06,0xFF,0x40,0xF9,0x40,0xF9,0x40,0xF9,0xC6,0xFE,0xE7,0xFF,0x24,0xFD,0xE0,0xFA,0xE0,0xFA,0x20,0xFB,0x80,0xFB,0x20,0xFC,0x00,0xFD,0x20,0xFD,0x60,0xFD, + 0x82,0xFD,0xC2,0xFD,0xE2,0xFD,0x22,0xFE,0x49,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,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBF,0xF7,0x5F,0xD7,0x7F,0xDF,0x3F,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x9F,0xEF,0xDF,0xBE,0xFF,0x64,0xFF,0xC6,0x7F,0xDF,0x7F,0xD7,0x9F,0xF7,0xDE,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0xFC,0x74,0xF8,0x31,0xF8,0x10,0xF8,0x0E,0xF8,0x2C,0xF8,0x0A,0xF8,0x09,0xF8,0x07,0xF8,0x26,0xF8,0x65,0xFE,0xC5,0xFF,0x64,0xFE,0x60,0xF8,0x40,0xF8,0x04,0xFD, + 0xE6,0xFF,0x26,0xFF,0x40,0xF9,0x20,0xF9,0x41,0xFA,0xA6,0xFF,0xE7,0xFF,0xA3,0xFC,0xE0,0xFA,0xC0,0xFA,0x00,0xFB,0x40,0xFB,0x20,0xFC,0x00,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x80,0xFD,0xA0,0xFD,0x00,0xFE,0x47,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0x9F,0xEF,0x5F,0xCF,0x7F,0xD7,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0x7F,0xEF,0xBF,0xAE,0x3F,0x5D,0x3F,0x2C,0x7F,0x6B,0xBF,0xE7,0x7F,0xD7,0x5F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, + 0xFF,0xFF,0xB5,0xF9,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x47,0xFA,0x45,0xFF,0xA5,0xFF,0x03,0xFD,0x60,0xF8,0xE0,0xF8,0x04,0xFF,0xC5,0xFF,0x24,0xFE,0x20,0xF9,0xE0,0xF8,0xA4,0xFD,0xA5,0xFF,0x45,0xFF,0x00,0xFA,0x20,0xFA,0xC0,0xFA,0x40,0xFB,0x80,0xFB,0xE0,0xFB,0x60,0xFC,0xA0,0xFC,0xC0,0xFC,0x20,0xFD,0x40,0xFD,0x80,0xFD,0xC0,0xFD,0x27,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xEF,0xBF,0xFF,0x1F,0xC7,0x5F,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xBF,0xF7,0x5F,0xD7,0x3F,0x8E,0xDF,0x24,0xDF,0x1B,0xDF,0x22,0x9F,0x31,0xFF,0xEF,0x3F,0xCF,0xBF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1B,0xFE,0x74,0xF8,0x32,0xF8,0x30,0xF8,0x0E,0xF8,0x0B,0xF8,0x0A,0xF8,0x08,0xF8,0x64,0xFE,0x43,0xFF,0xE3,0xFE,0xA0,0xF8,0x40,0xF8,0x62,0xFD,0x63,0xFF,0x44,0xFF,0x41,0xFA,0x00,0xF9,0x61,0xFB,0x64,0xFF,0x84,0xFF,0x62,0xFC,0x80,0xF9,0xA0,0xF9,0xE0,0xFA,0xA0,0xFB,0xE0,0xFB,0xE0,0xFB,0xA0,0xFB,0x00,0xFC,0x60,0xFC,0x00,0xFD,0x20,0xFD,0x60,0xFD,0xA0,0xFD,0x07,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFB,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA, + 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0xDF,0xB6,0x3F,0xCF,0x3F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xBF,0xF7,0x3F,0x5C,0x9F,0x23,0xDF,0x12,0x3F,0x12,0x1F,0x40,0x00,0xF8,0x3F,0xD7,0x9F,0xAE,0x7E,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0xF9,0x33,0xF8,0x31,0xF8,0x2F,0xF8,0x2C,0xF8,0x0A,0xF8,0x66,0xFD,0x22,0xFF,0x22,0xFF,0x41,0xFC,0x41,0xF8,0x21,0xFB,0x03,0xFF,0x23,0xFF,0x42,0xFD,0xC0,0xF8,0xE0,0xF8,0x42,0xFE,0x63,0xFF,0x82,0xFE,0x00,0xF9,0x60,0xF9,0x80,0xF9,0xE0,0xFA,0x80,0xFB,0xC0,0xFB,0x40,0xFC,0x60,0xFD,0xA0,0xFD,0xC0,0xFD, + 0x41,0xFE,0x81,0xFE,0xA2,0xFE,0xC1,0xFE,0x82,0xFE,0x63,0xFE,0x83,0xFE,0x23,0xFE,0x02,0xFA,0x02,0xFA,0xE2,0xF9,0x82,0xF9,0x46,0xFA,0x08,0xFB,0xE8,0xFA,0xE8,0xFA,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xE7,0x9F,0xF7,0x7F,0xD7,0xBF,0xB6,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xE7,0x3F,0xDF,0x3F,0xEF,0x5F,0xFF,0xBF,0x2A,0x1F,0x42,0x1F,0xF8,0x1F,0x50,0x5F,0xAD,0x3F,0xCF,0xBF,0xCE,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x17,0xFB,0x53,0xF8,0x51,0xF8,0x2E,0xF8,0x2A,0xF8,0x27,0xF9,0x02,0xFF,0x01,0xFF,0x41,0xFE,0x21,0xF8,0x40,0xF8,0xC1,0xFD,0x02,0xFF,0x82,0xFE, + 0xA0,0xF8,0xE0,0xF8,0x00,0xFB,0x02,0xFF,0x22,0xFF,0x21,0xFC,0xE0,0xF9,0x20,0xFA,0x40,0xFA,0x80,0xFA,0xC0,0xFA,0x00,0xFB,0x60,0xFC,0xC0,0xFE,0xC0,0xFE,0xE0,0xFE,0x61,0xFF,0xE2,0xFF,0xE2,0xFF,0xE2,0xFF,0x81,0xFE,0x40,0xFE,0x40,0xFE,0xE0,0xFD,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x80,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xBE,0xFF,0xDF,0xF7,0xFF,0xBE,0x7F,0xCF,0x9F,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0x7F,0xDF,0xFF,0x64,0x3F,0x11,0x9F,0xE6,0xFD,0xFE,0x1F,0xF8,0x1F,0x30,0x1F,0x18,0x1F,0x18,0x7F,0xDF,0x9F,0xB6,0x9F,0xF7,0xFF,0xFF,0xFF,0xFF, + 0xDF,0xFF,0xFF,0xFF,0x7E,0xFF,0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2C,0xF8,0x66,0xFD,0xE1,0xFE,0xE1,0xFE,0x40,0xFC,0x80,0xF8,0xA0,0xF8,0x61,0xFE,0xC1,0xFE,0xC1,0xFD,0xC0,0xF8,0xE0,0xF8,0xE0,0xFB,0xC1,0xFE,0xE1,0xFE,0x60,0xFA,0x40,0xFA,0x80,0xFA,0xA0,0xFA,0x60,0xFA,0x60,0xFA,0x80,0xFA,0x40,0xFC,0xC0,0xFE,0xC0,0xFE,0xC0,0xFE,0x61,0xFF,0xC2,0xFF,0xC2,0xFF,0xC2,0xFF,0x61,0xFE,0x20,0xFE,0x40,0xFE,0xC0,0xFD,0x00,0xFA,0x00,0xFA,0xC0,0xF9,0x80,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x7F,0xF7,0x9F,0xF7,0x1F,0xCF,0x3F,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xF7, + 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x1F,0x63,0x1F,0x30,0x1F,0x08,0xBF,0xC5,0x7F,0x93,0x1F,0x10,0x1F,0x08,0x5F,0x08,0x3F,0xCF,0x9F,0xDF,0xBF,0xFF,0x3F,0xDF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0xF8,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0xE6,0xFD,0xC2,0xFE,0xA1,0xFE,0x21,0xFC,0x60,0xF8,0xA0,0xF8,0x21,0xFE,0xA1,0xFE,0xE1,0xFD,0xC0,0xF8,0xE0,0xF8,0x20,0xFB,0xA1,0xFE,0xA1,0xFE,0xC0,0xFC,0x20,0xFA,0x60,0xFA,0x80,0xFA,0x60,0xFA,0x40,0xFA,0x80,0xFA,0x00,0xFC,0x40,0xFE,0x40,0xFE,0x40,0xFE,0xC1,0xFE,0x22,0xFF,0x02,0xFF,0x22,0xFF,0x21,0xFE,0xE0,0xFD,0x00,0xFE,0x80,0xFD,0xE0,0xF9,0xC0,0xF9,0xA0,0xF9,0x60,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00, + 0x5D,0xFC,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x1F,0x74,0xBF,0xF7,0x5F,0xD7,0xDF,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFF,0x21,0x5F,0x11,0x7F,0x08,0x7F,0x29,0xBF,0x94,0x7F,0x08,0x9F,0x10,0x1F,0x11,0x5F,0x4A,0xBF,0xDF,0x9F,0xF7,0x5F,0xEF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x57,0xF9,0x54,0xF8,0x53,0xF8,0x50,0xF8,0x49,0xFC,0xA1,0xFE,0x81,0xFE,0xA1,0xFD,0x40,0xF8,0x41,0xF8,0x61,0xFD,0x60,0xFE,0x41,0xFE,0x40,0xFB,0xE0,0xF8,0x00,0xF9,0x01,0xFE,0x61,0xFE,0x00,0xFE,0xA0,0xFA,0x80,0xF9,0x80,0xF9,0xA0,0xF9,0xC0,0xFA,0x00,0xFB,0x20,0xFB,0xE0,0xFB,0xA0,0xFC,0xC0,0xFC, + 0x00,0xFD,0x20,0xFD,0x40,0xFD,0x60,0xFD,0xA0,0xFD,0xC0,0xFD,0xC1,0xFD,0x44,0xFD,0x04,0xFA,0xE4,0xF9,0xE4,0xF9,0xC5,0xF9,0x4C,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x3D,0xFC,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x3F,0xBE,0xBF,0xF7,0x1F,0xCF,0xDF,0x8D,0x9F,0xB6,0x7F,0x9E,0x5F,0x8E,0x9F,0x6D,0xBF,0xF7,0xBF,0x9E,0xBF,0xAE,0x3F,0xE7,0xBF,0xF7,0xBF,0xF7,0xFF,0x08,0x9F,0x09,0xDF,0x09,0x1F,0x11,0x5F,0x09,0xBF,0x63,0x1F,0x11,0x7F,0x11,0xDF,0x19,0x9F,0x19,0xBF,0xDF,0x5F,0xE7,0xBF,0xF7,0xFE,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x78,0xF9,0x75,0xF8,0x54,0xF8,0x52,0xF8,0x4F,0xF8,0x23,0xFE,0x20,0xFE,0x00,0xFE,0x41,0xFC,0x01,0xF8,0xE1,0xF9,0x01,0xFE,0x20,0xFE, + 0xC0,0xFD,0x20,0xFA,0x00,0xF9,0x81,0xFB,0x21,0xFE,0x00,0xFE,0x81,0xFD,0x80,0xF9,0x20,0xF9,0x40,0xF9,0xC0,0xFA,0x20,0xFB,0x20,0xFB,0xA0,0xFB,0x60,0xFC,0xA0,0xFC,0xE0,0xFC,0x00,0xFD,0x40,0xFD,0x60,0xFD,0x80,0xFD,0xA0,0xFD,0xC1,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC9,0xFB,0x62,0xFB,0x61,0xFB,0x44,0xFB,0x00,0x00,0xFD,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x5F,0xBE,0x9F,0xFF,0x3F,0xCF,0xBF,0x85,0xBF,0x65,0x1F,0x66,0xDF,0x44,0x9F,0x2B,0x9F,0xEF,0x9F,0x12,0x1F,0x00,0x7F,0x62,0x1F,0x20,0x5F,0x10,0x5F,0x11,0x5F,0x12,0x5F,0x12,0x3F,0x1A,0x7F,0x1A,0xBF,0x53,0x3F,0x1A,0x5F,0x22,0x5F,0x2A,0xDF,0x21,0xBF,0xE7,0x5F,0xDF,0x9F,0xF7,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7A,0xF9,0x97,0xF8,0x75,0xF8,0x53,0xF8,0x51,0xF8,0x4E,0xFA,0xA2,0xFD,0x80,0xFD,0x40,0xFD,0xE1,0xF9,0x00,0xF8,0xA2,0xFB,0xA0,0xFD,0xC0,0xFD,0xE0,0xFC,0x00,0xF9,0x01,0xF8,0x21,0xFC,0xA0,0xFD,0xA0,0xFD,0x60,0xFC,0x20,0xF9,0x40,0xF9,0x60,0xFA,0xA0,0xFA,0xA0,0xFA,0xE0,0xFA,0x60,0xFB,0xC0,0xFB,0x40,0xFC,0x80,0xFC,0xA0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0x20,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xFB,0x20,0xFB,0x20,0xFB,0x43,0xFB,0x00,0x00,0x7C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x1F,0x53,0x5F,0xF7,0xFF,0xBE,0x9F,0xA6,0x5F,0x34,0x7F,0x24,0x1F,0x23,0x9F,0x19,0x3D,0xFF,0x1F,0x00,0x1F,0x00,0x1F,0x40, + 0x1F,0x10,0xFF,0x10,0x5F,0x12,0xDF,0x12,0x7F,0x12,0xDF,0x1A,0x1F,0x2B,0xDF,0x53,0xFF,0x2A,0xFF,0x2A,0xFF,0x32,0x7F,0x22,0xBF,0xE7,0x9F,0xEF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7B,0xF9,0x98,0xF8,0x76,0xF8,0x75,0xF8,0x53,0xF8,0x51,0xF8,0x4B,0xFB,0x00,0xFD,0x20,0xFD,0x81,0xFC,0x02,0xF8,0x03,0xF8,0x81,0xFC,0x60,0xFD,0x60,0xFD,0x61,0xFB,0x01,0xF8,0x01,0xF8,0xA0,0xFC,0x60,0xFD,0x40,0xFD,0x60,0xF9,0x20,0xF9,0x40,0xF9,0x60,0xF9,0xA0,0xF9,0xE0,0xF9,0x20,0xFA,0xC0,0xFA,0xC0,0xFB,0x00,0xFC,0x40,0xFC,0x60,0xFC,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0xFB,0x01,0xFB,0x01,0xFB,0x24,0xFB,0x00,0x00, + 0x9C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0xDF,0xDE,0x5F,0xEF,0xFF,0xBE,0x3F,0xC7,0x3F,0x33,0x5F,0x22,0x1F,0x41,0x1F,0xF8,0x5B,0xFE,0xFF,0xFD,0x1F,0x00,0x1F,0xF8,0xBF,0x10,0xDF,0x11,0x9F,0x12,0xDF,0x12,0xDF,0x22,0x1F,0x23,0xFF,0x4B,0x7F,0x43,0x5F,0x33,0x5F,0x3B,0x3F,0x3B,0x1F,0xCF,0xBF,0xE7,0xDF,0xFF,0xFF,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xF9,0xDA,0xF8,0xB8,0xF8,0x76,0xF8,0x74,0xF8,0x51,0xF8,0x2F,0xF8,0x83,0xFC,0xE0,0xFC,0xA0,0xFC,0x03,0xF8,0x03,0xF8,0x43,0xF8,0x00,0xFD,0x00,0xFD,0x60,0xFC,0x01,0xF8,0x01,0xF8,0x61,0xFA,0x20,0xFD,0x20,0xFD,0xA0,0xFA,0x00,0xF9,0x20,0xF9,0x60,0xF9,0x80,0xF9,0xC0,0xF9,0x00,0xFA,0xA0,0xFA, + 0xA0,0xFB,0xE0,0xFB,0x20,0xFC,0x40,0xFC,0x60,0xFC,0x80,0xFC,0x80,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0x7F,0xEF,0x5F,0xA6,0x3F,0xC7,0xBF,0x1A,0xBF,0xAA,0x00,0xF8,0x00,0xF8,0x1F,0xF8,0xBE,0xFE,0x1F,0x6A,0x7F,0x08,0xFF,0x28,0x9F,0x21,0x1F,0x22,0xFF,0x2A,0x7F,0x2B,0xFF,0x43,0x3F,0x54,0x9F,0x43,0x9F,0x43,0x7F,0x43,0x1F,0x43,0x9F,0xE7,0x7F,0xDF,0xBF,0xFF,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xFD,0x1E,0xF9,0xDC,0xF8,0xBA,0xF8,0x97,0xF8,0x75,0xF8,0x73,0xF8,0x70,0xF8,0x06,0xFC,0xA0,0xFC,0x60,0xFC,0x03,0xF8,0x03,0xF8,0x03,0xF8, + 0x80,0xFC,0xC0,0xFC,0x20,0xFC,0x01,0xF8,0x01,0xF8,0x81,0xF8,0xE0,0xFC,0xE0,0xFC,0x80,0xFA,0xE0,0xF8,0x00,0xF9,0x40,0xF9,0xC0,0xF9,0x00,0xFB,0x20,0xFB,0x40,0xFB,0x80,0xFB,0xA0,0xFB,0xE1,0xFB,0x43,0xFC,0x63,0xFC,0x63,0xFC,0x44,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xFB,0x1C,0xFC,0xDF,0xFF,0xFF,0xFF,0xDF,0xFF,0x5F,0xE7,0xFF,0xE6,0x1F,0xBF,0xDF,0x8D,0xBF,0x52,0x00,0xF8,0x1F,0xF8,0x1F,0x20,0xDF,0x51,0xFF,0xEC,0x3F,0xAB,0x9F,0x39,0x5F,0x32,0xDF,0x32,0x3F,0x3B,0x3F,0x64,0x5F,0x64,0xBF,0x53,0xDF,0x53,0x9F,0x53,0x7F,0x53,0x5F,0x3B,0xDF,0xEF,0x3F,0xCF,0x9F,0xF7,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x3F,0xF9,0x1D,0xF9,0xFB,0xF8,0xB9,0xF8,0x97,0xF8,0x94,0xF8,0x71,0xF8,0xA6,0xFB,0x40,0xFC,0x00,0xFC,0x04,0xF8,0x05,0xF8,0x04,0xF8,0x60,0xFC,0x80,0xFC,0xA0,0xFB,0x01,0xF8,0x01,0xF8,0x61,0xF9,0xA0,0xFC,0x80,0xFC,0xE0,0xF8,0x20,0xF9,0x80,0xF9,0xC0,0xF9,0x20,0xFA,0x20,0xFB,0x40,0xFB,0x40,0xFB,0x60,0xFB,0x80,0xFB,0xC2,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xF8,0x60,0xF8,0x60,0xF8,0x60,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0xFB,0xDC,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x5F,0xF7,0x9F,0xFF,0x7F,0xA6,0xFF,0xBE,0x9F,0x1B,0x1F,0x80,0x1F,0x48,0x1F,0x68,0x7F,0x90,0x7F,0x88,0x1F,0xBB, + 0xFF,0xAB,0xDF,0x93,0x1F,0x84,0x3F,0x84,0x9F,0x6B,0xBF,0x73,0x1F,0x7C,0x3F,0x84,0xDF,0x7B,0x3F,0x63,0xDF,0xEF,0xBF,0xEF,0xBF,0xF7,0xBF,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xDA,0x7F,0xF9,0x3E,0xF9,0x1D,0xF9,0xDB,0xF8,0xB9,0xF8,0x96,0xF8,0x73,0xF8,0xA4,0xFB,0x00,0xFC,0x82,0xFB,0x06,0xF8,0x06,0xF8,0x25,0xF9,0x20,0xFC,0x40,0xFC,0x81,0xF9,0x01,0xF8,0x01,0xF8,0x01,0xFB,0x60,0xFC,0xE0,0xFB,0x80,0xF8,0x00,0xFA,0xA0,0xFA,0xC0,0xFA,0xA0,0xFA,0xE0,0xFA,0x00,0xFB,0x00,0xFB,0x20,0xFB,0x20,0xFB,0x42,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xF8,0x20,0xF8,0x20,0xF8,0x40,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7E,0xFC,0xBD,0xFB,0x7F,0xFE,0xFF,0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xE6,0x7F,0xF7,0xFF,0xBE,0x1F,0xBF,0x1F,0x23,0xBF,0xD8,0x7F,0xF0,0xBF,0xE8,0x5F,0xF1,0x7F,0xF1,0x1F,0xE2,0x1F,0xD2,0x7F,0xBA,0xDF,0xB2,0x3F,0xA3,0x9F,0xA3,0x3F,0xCE,0xDF,0xFF,0xBF,0x9C,0xBF,0xEF,0xFF,0xF7,0x5F,0xDF,0xBF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xCB,0x1F,0xDA,0xBF,0xF1,0x7F,0xF9,0x3E,0xF9,0xFC,0xF8,0xDA,0xF8,0xD8,0xF8,0xB1,0xF9,0xC0,0xFB,0xC0,0xFB,0xA6,0xF9,0x08,0xF8,0x07,0xF8,0x23,0xFB,0xE0,0xFB,0x60,0xFB,0x02,0xF8,0x01,0xF8,0x01,0xF8,0x80,0xFB,0xE0,0xFB,0xE0,0xF9,0x60,0xF8,0x00,0xFA,0xA0,0xFA,0xC0,0xFA,0x60,0xFA,0x80,0xF9,0x80,0xF9,0x80,0xF9, + 0x80,0xF9,0x60,0xF9,0x41,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xF8,0x00,0xF8,0x00,0xF8,0x20,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBE,0xFB,0xFE,0xFB,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xDF,0xFF,0x7F,0xF7,0xBF,0xCE,0x1F,0xC7,0xBF,0xB6,0xBF,0x3A,0x3E,0xF9,0xBB,0xF8,0x1A,0xF9,0x3B,0xF9,0xBC,0xF9,0xFE,0xF9,0x5F,0xF2,0xBF,0xEA,0xFF,0xD2,0x3F,0xCB,0xFF,0xCC,0x5F,0xEF,0x9F,0xE7,0xFF,0xFF,0x9F,0xE7,0xDF,0xFF,0x3F,0xE7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x9F,0xBA,0x3F,0xD2,0xFF,0xE1,0x7F,0xF1,0x5F,0xF9,0x3E,0xF9,0x1C,0xF9,0xD9,0xF8,0x47,0xFB,0xA0,0xFB,0xC6,0xFA,0x2A,0xF8,0x09,0xF8,0x27,0xF9,0x80,0xFB, + 0x60,0xFB,0x82,0xF8,0x02,0xF8,0x02,0xF8,0x20,0xFA,0x40,0xFB,0x60,0xFA,0x41,0xF8,0x41,0xF8,0xC0,0xF9,0x60,0xFA,0x80,0xFA,0x40,0xFA,0x00,0xFA,0x00,0xFA,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x62,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xF9,0xA6,0xF9,0xA6,0xF9,0xE7,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFC,0xBF,0xFB,0x3F,0xFD,0xDF,0xFF,0xDF,0xFF,0xDE,0xFF,0x7F,0xE7,0xBF,0xFF,0xFF,0xD6,0x1F,0xC7,0xFF,0xC6,0x3F,0x5D,0x3F,0xBA,0x39,0xF9,0xF8,0xF8,0x19,0xF9,0x7B,0xF9,0xDD,0xF9,0x5E,0xFA,0xBF,0xEA,0xDF,0xDA,0x5F,0x73,0xDF,0xF7,0xFF,0xF7,0x9F,0xE7,0xDF,0xFF,0x5F,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xA2,0x7F,0xB2,0x3F,0xC2,0xFF,0xD9,0xDF,0xE9,0x7F,0xF9,0x5F,0xF9,0x3D,0xF9,0x58,0xF9,0x09,0xFB,0xC9,0xFA,0x2E,0xF8,0x0C,0xF8,0x0A,0xF8,0x67,0xF9,0x84,0xFA,0x44,0xF9,0x03,0xF8,0x02,0xF8,0x02,0xF8,0x01,0xF8,0x61,0xF8,0x21,0xF8,0x42,0xF8,0x42,0xF8,0x41,0xF9,0xE0,0xF9,0x40,0xFA,0x80,0xFA,0xC0,0xFA,0x00,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xFA,0x08,0xFA,0xE7,0xF9,0x69,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0xF3,0xBF,0xF3,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x5F,0xE7,0xBF,0xFF,0xBF,0xD6,0xBF,0xBE,0x1F,0xCF,0xFF,0xC6,0xBF,0x8D,0x5F,0x1B, + 0x9F,0xAA,0x1F,0xFA,0x7F,0xEA,0xFF,0x42,0xDF,0xBE,0xFF,0xF7,0xFF,0xF7,0xDF,0xF7,0xBF,0xE7,0xDF,0xF7,0x7F,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x9C,0xBF,0x9A,0x7F,0xAA,0x3F,0xBA,0x1F,0xD2,0xFF,0xE9,0xBF,0xF1,0x7F,0xF9,0x5E,0xF9,0x1B,0xF9,0xB7,0xF8,0x53,0xF8,0x30,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x03,0xF8,0x03,0xF8,0x02,0xF8,0x22,0xF8,0x21,0xF8,0x22,0xF8,0x22,0xF8,0x40,0xF9,0xC0,0xF9,0x00,0xFA,0x60,0xFA,0xA0,0xFA,0xC0,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xF8,0x80,0xF8,0x80,0xF8,0xE3,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,0x7F,0xF5,0x7F,0xEB,0x7F,0xE3,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xBF,0xF7,0x1F,0xEF,0x1F,0xEF,0x7F,0xBE,0xBF,0xBE,0x3F,0xD7,0x7F,0xDF,0x7F,0xE7,0xDF,0xEF,0xDF,0xF7,0xFF,0xF7,0xFF,0xF7,0xFF,0xF7,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF,0xD6,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x8C,0x1F,0x7B,0xDF,0x92,0x7F,0xA2,0x5F,0xB2,0x3F,0xD2,0xFF,0xE9,0xDF,0xF9,0x9F,0xF9,0x7E,0xF9,0x1C,0xF9,0xD8,0xF8,0x74,0xF8,0x30,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x80,0xF8,0x80,0xF8,0x40,0xF8,0x21,0xF8,0x40,0xF8,0x60,0xF8,0x80,0xF8,0xC0,0xF8,0x21,0xF9,0x07,0xFB,0x28,0xFB,0x00,0x00, + 0x00,0x00,0x00,0x00,0x60,0xF8,0x60,0xF8,0x60,0xF8,0xE3,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,0x3F,0xEC,0x5F,0xE3,0x7F,0xDB,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x8D,0x1F,0xEF,0x5F,0xEF,0x1F,0xEF,0xFF,0xCE,0x3F,0xCF,0x7F,0xE7,0x9F,0xE7,0x9F,0xE7,0x9F,0xF7,0xBF,0xFF,0xDF,0xFF,0x7F,0xE7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7C,0x5F,0x5B,0x3F,0x73,0xFF,0x8A,0x9F,0x9A,0x5F,0xB2,0x3F,0xCA,0x1F,0xE2,0x1F,0xFA,0xDF,0xF9,0x7E,0xF9,0x3B,0xF9,0xF8,0xF8,0xB5,0xF8,0x51,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8, + 0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x80,0xF8,0xA0,0xF8,0x40,0xF8,0x20,0xF8,0x40,0xF8,0x60,0xF8,0x80,0xF8,0xA0,0xF8,0x23,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xF8,0x20,0xF8,0x20,0xF8,0xC2,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,0x5F,0xDC,0x1F,0xCB,0x3F,0xC3,0xBF,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x5F,0xEF,0x5F,0xB6,0x5F,0xEF,0xBF,0xFF,0xBF,0xFF,0xDF,0xFF,0xDF,0xFF,0x9F,0xE7,0xBF,0x95,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x5B,0x7F,0x4B,0x7F,0x53,0x5F,0x6B, + 0x3F,0x7B,0xFF,0x9A,0x5F,0xAB,0x5F,0xC4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xFC,0xDA,0xFA,0xB6,0xF9,0xF2,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x07,0xF8,0x06,0xF8,0x05,0xF8,0x24,0xF8,0x61,0xF8,0x81,0xF8,0x21,0xF8,0x20,0xF8,0x20,0xF8,0x60,0xF8,0x60,0xF8,0x60,0xF8,0x4C,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0xFB,0x6D,0xFB,0xCF,0xFB,0x30,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,0xDF,0xD4,0x1F,0xBB,0x1F,0xB3,0x1F,0xB4,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xFF,0xFF,0x9F,0x94,0x1F,0x5B,0x3F,0x4B,0x9F,0x5B,0xDF,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xF9,0xEA,0xF8,0x48,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x03,0xF8,0x02,0xF8,0x02,0xF8,0x01,0xF8,0x00,0xF8,0x20,0xF8,0x60,0xF8,0xA1,0xF8,0x8A,0xFA,0x00,0x00,0xE8,0xFA,0x63,0xFA,0x63,0xFA,0x09,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xAB,0xFF,0xA2,0x1F,0xA3,0x7F,0xAC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xAD,0xDF,0x7B,0x1F,0xE7,0xFF,0xFF,0x5F,0xEF,0x1F,0xA5,0x1F,0x94,0x9F,0x9B,0x5F,0xAB,0x5F,0xBB,0x3F,0xC3,0x9F,0xD3,0x1F,0xE4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFB,0xA8,0xF9,0xE6,0xF8,0xA4,0xF8,0x63,0xF8,0x63,0xF8,0x62,0xF8,0xA3,0xF8,0x04,0xF9,0x49,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFA,0x20,0xFA,0x40,0xFA, + 0x85,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xBC,0x3F,0x9B,0xDF,0x82,0x1F,0x73,0x9F,0x73,0xDF,0x94,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xCE,0x5F,0x6C,0xDF,0x4B,0x9F,0x43,0x7F,0x4B,0x7F,0x63,0x5F,0x6B,0x3F,0x73,0x3F,0x83,0x1F,0x93,0xDF,0xA2,0x9F,0xB2,0x5F,0xC2,0x3F,0xD2,0x3F,0xE2,0x3F,0xEA,0x7F,0xFA,0x7D,0xFA,0x3B,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,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,0xFA,0x20,0xFA,0x20,0xFA,0x65,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDF,0xAC,0x5F,0x7B,0x3F,0x63,0x5F,0x53,0x5F,0x4B,0x5F,0x43,0x7F,0x3B,0x7F,0x3B,0x9F,0x33,0x9F,0x33,0x9F,0x2B,0x9F,0x2B,0x9F,0x2B,0x7F,0x2B,0x9F,0x2B,0x9F,0x33,0x9F,0x3B,0x7F,0x4B,0x7F,0x5B,0x7F,0x6B,0x5F,0x73,0x3F,0x83, + 0x1F,0x93,0xFF,0xA2,0xDF,0xB2,0x9F,0xC2,0x9F,0xD2,0x7F,0xE2,0x5F,0xF2,0x3E,0xFA,0xBB,0xF9,0x78,0xF9,0x56,0xF9,0xF4,0xF9,0x56,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,0xCD,0xFB,0xEE,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0x8C,0xDF,0x5B,0x7F,0x4B, + 0x7F,0x3B,0x7F,0x33,0x9F,0x2B,0x9F,0x2B,0x7F,0x2B,0x9F,0x2B,0x9F,0x2B,0x9F,0x33,0xBF,0x3B,0xDF,0x43,0x1F,0x54,0x5F,0x6C,0x3F,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + //alpha channel data: - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xAC, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x9A, 0xEF, 0xFD, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xD9, 0xFE, 0xFE, 0xFE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xA9, 0xAA, 0xAB, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xF7, 0xFE, 0xFE, 0xFE, 0xFD, 0x48, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFE, 0xFE, 0xFD, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xC6, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0x6D, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xFE, 0xFE, 0xFD, 0x3C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xE4, 0xFD, 0xFE, 0xFD, - 0xFE, 0xFE, 0xFE, 0xFE, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xD6, 0xD5, 0xD4, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xF5, 0xFE, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xEA, 0x00, 0x37, 0x6E, 0xAA, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC8, 0xFA, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF9, 0xFC, 0xFE, 0xFE, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0xD7, 0xD9, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xA2, 0xEC, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7D, 0xFE, 0xFE, 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, 0x68, 0xA9, 0xDA, 0xE9, 0xF2, 0xF8, 0xFA, 0xFB, 0xFD, 0xFD, 0xFD, 0xFE, - 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x44, 0x00, 0x00, 0x55, 0x87, 0x88, 0x8B, 0x43, 0x6F, 0xE5, 0xE3, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x62, 0x67, 0x53, 0x41, 0x37, 0x37, 0x42, 0x53, - 0x66, 0x80, 0xA0, 0xC1, 0xD1, 0xD8, 0xDE, 0xE5, 0xEE, 0xF6, 0xF8, 0xFA, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xD0, 0xCE, 0xD0, 0xE4, 0xFE, 0xFE, 0xFE, 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, 0x00, 0x00, 0x69, 0x9E, 0xBB, - 0xC8, 0xCE, 0xCC, 0xC1, 0xA6, 0x79, 0x00, 0x00, 0x00, 0x60, 0x8D, 0xA1, 0x96, 0x90, 0x98, 0xA1, 0xAA, 0xB3, 0xBE, 0xC7, 0xCE, 0xD3, 0xDA, 0xE1, 0xE9, 0xF1, 0xF7, 0xF8, 0xFB, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAF, 0xE9, 0xFC, 0xFB, 0xF4, 0xEA, 0xE8, 0xEA, 0xF1, 0xF6, 0xF7, 0xEC, 0xBD, 0x5F, 0x1E, 0x1E, 0x53, 0x85, 0x8C, 0x97, 0xA1, 0xAB, 0xB2, 0xBB, 0xC2, 0xC8, 0xCD, 0xD5, 0xDD, 0xE4, 0xED, 0xF3, 0xF7, 0xFB, 0xFD, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, - 0x71, 0x00, 0x00, 0x00, 0x7F, 0xBE, 0xBE, 0xBF, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xE8, 0xF6, 0xDB, 0xA8, 0x69, 0x2D, 0x25, 0x2D, 0x26, 0x29, 0x5E, 0x99, 0xCE, 0xEE, 0xEB, 0xB2, 0x3C, 0x1E, 0x26, 0x6C, 0x91, 0x9C, 0xA7, 0xAF, 0xB7, 0xBD, 0xC3, 0xCA, 0xD0, 0xD7, 0xDE, 0xE8, 0xF0, 0xF5, 0xFA, 0xFC, 0xFE, 0xFD, - 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x6F, 0x00, 0x00, 0x00, 0xA9, 0xFE, 0xFE, 0xFD, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xD8, 0xF2, 0xC4, 0x70, 0x31, 0x4C, 0x4D, 0x4F, 0x49, 0x48, 0x45, 0x4B, 0x4D, 0x48, 0x27, 0x69, 0xC2, 0xE4, 0xD9, 0x71, 0x1E, 0x1E, 0x64, 0x97, - 0xA3, 0xAC, 0xB3, 0xB9, 0xBF, 0xC6, 0xCC, 0xD2, 0xDA, 0xE3, 0xED, 0xF4, 0xFA, 0xFD, 0xFE, 0xFD, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFD, 0xF6, 0xF2, 0xFB, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0x9D, 0x00, 0x00, 0x00, 0xA9, 0xFE, 0xFE, 0xFD, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xEF, 0xE6, 0x89, 0x2C, 0x4E, 0x4B, 0x2E, 0x3F, 0x4A, - 0x4F, 0x4C, 0x48, 0x40, 0x31, 0x21, 0x34, 0x42, 0x28, 0x86, 0xDD, 0xE2, 0x84, 0x1E, 0x1E, 0x6E, 0x9E, 0xA8, 0xAE, 0xB4, 0xBA, 0xC0, 0xC5, 0xCC, 0xD3, 0xDC, 0xEC, 0xFC, 0xEE, 0xFA, 0xFD, 0xFD, 0xFE, 0xEC, 0xF5, 0xFC, 0xFD, 0xFD, 0xFD, 0xDC, 0xF3, 0xFC, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xA9, 0x00, 0x00, 0x00, 0x87, 0xC9, 0xC9, 0xC7, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xEF, 0xD8, 0x5B, 0x42, 0x4B, 0x34, 0x52, 0x58, 0x41, 0x2C, 0x29, 0x27, 0x1E, 0x1E, 0x26, 0x31, 0x31, 0x21, 0x38, 0x39, 0x61, 0xD3, 0xDC, 0x7A, 0x1E, 0x20, 0x80, 0xA1, 0xA9, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCD, 0xD4, 0xE5, 0xFE, 0xE4, 0xE8, 0xFA, 0xFB, 0xFE, 0xEF, 0xDF, 0xFA, 0xFD, 0xFD, 0xFE, 0xE1, 0xEA, 0xFC, 0xFC, 0xFD, 0xFD, 0xFC, 0xFD, 0xFC, - 0xE0, 0xCA, 0xCB, 0xCC, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xE7, 0xD7, 0x4A, 0x4B, 0x3C, 0x42, 0x52, 0x35, 0x7B, 0xBF, 0xAA, 0x95, 0x6D, 0x49, 0x35, 0x22, 0x10, 0x16, 0x2E, 0x28, 0x29, 0x3B, 0x55, 0xD2, 0xD6, 0x56, 0x1E, 0x35, 0x96, 0xA3, 0xA8, 0xAD, 0xB3, 0xB9, 0xC0, 0xC7, 0xCE, 0xEB, 0xFE, 0xE4, 0xD7, 0xF5, 0xF7, - 0xFE, 0xEE, 0xD4, 0xF6, 0xFC, 0xFE, 0xFE, 0xDE, 0xE8, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFB, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xF0, 0xF0, 0xE6, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xE0, 0x66, 0x3C, 0x39, 0x3F, 0x44, 0x4B, 0xD1, 0xFE, 0xFF, 0xE6, 0x95, 0x66, 0x43, 0x2F, 0x20, 0x17, 0x11, 0x07, 0x20, 0x2C, 0x24, 0x3B, 0x68, 0xD4, 0xB8, 0x1F, - 0x1E, 0x67, 0x9B, 0xA0, 0xA7, 0xAD, 0xB4, 0xBA, 0xC1, 0xCB, 0xFA, 0xFD, 0xD1, 0xD3, 0xF0, 0xFA, 0xFD, 0xDC, 0xD3, 0xF5, 0xFB, 0xFE, 0xF5, 0xDA, 0xF0, 0xFB, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFD, 0xFD, 0xFC, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFE, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0x8F, 0xE9, 0x9F, 0x26, 0x3C, 0x36, 0x3D, 0x45, 0xE9, 0xFF, 0xFF, 0xFF, 0xF1, - 0x8F, 0x5A, 0x38, 0x26, 0x1A, 0x14, 0x11, 0x0E, 0x05, 0x1C, 0x28, 0x2E, 0x2C, 0x9E, 0xD2, 0x7B, 0x1E, 0x26, 0x8C, 0x99, 0xA0, 0xA6, 0xAD, 0xB3, 0xB8, 0xE9, 0xFE, 0xED, 0xC1, 0xDF, 0xF6, 0xFE, 0xF7, 0xC3, 0xDE, 0xF8, 0xFD, 0xFD, 0xE5, 0xE6, 0xF9, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xFE, 0xFE, 0xF0, - 0x00, 0x00, 0x00, 0xD2, 0xD7, 0x35, 0x43, 0x27, 0x3D, 0x27, 0xB3, 0xFD, 0xFE, 0xFE, 0xFE, 0xD1, 0x9F, 0x81, 0x5A, 0x37, 0x11, 0x10, 0x0E, 0x0B, 0x04, 0x01, 0x20, 0x21, 0x35, 0x3C, 0xC4, 0xB5, 0x1E, 0x1E, 0x6A, 0x91, 0x98, 0xA0, 0xA4, 0xA3, 0xC4, 0xFE, 0xFB, 0xB0, 0xC1, 0xEA, 0xFE, 0xFE, 0xCC, 0xC5, 0xEC, 0xFB, 0xFE, 0xE8, 0xE0, 0xF2, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, - 0xFE, 0xFD, 0xFD, 0xFC, 0xC4, 0xB9, 0xBA, 0xBB, 0xC1, 0xC3, 0xC5, 0xC8, 0x78, 0x6C, 0x6A, 0x65, 0x00, 0x00, 0x6C, 0xE3, 0xA1, 0x28, 0x33, 0x38, 0x24, 0x7E, 0xB4, 0xD1, 0xF0, 0xEC, 0xE7, 0xC7, 0x88, 0x54, 0x36, 0x2B, 0x2A, 0x17, 0x06, 0x04, 0x01, 0x03, 0x06, 0x28, 0x20, 0x2F, 0x97, 0xC1, 0x5F, 0x1E, 0x42, 0x79, 0x74, 0x75, 0x76, 0x77, 0xF0, 0xFE, 0xCE, 0x99, 0xC9, 0xF0, 0xFE, 0xEF, - 0xBE, 0xDA, 0xF1, 0xFE, 0xFE, 0xCF, 0xEB, 0xFC, 0xFE, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xDE, 0x5F, 0x3C, 0x24, 0x35, 0x1B, 0x90, 0x97, 0x98, 0x93, 0xBD, 0xA1, 0x81, 0x5A, 0x32, 0x1B, 0x10, 0x0E, 0x1D, 0x17, 0x01, 0x05, 0x0A, 0x09, 0x20, 0x22, 0x38, 0x62, 0xBC, - 0x8B, 0x1E, 0x1F, 0x5E, 0x61, 0x67, 0x6D, 0x9C, 0xFE, 0xFE, 0xAE, 0xB7, 0xC6, 0xF5, 0xFE, 0xDF, 0xD1, 0xED, 0xF6, 0xFE, 0xFE, 0xC5, 0xF1, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xD2, 0x20, 0x3C, 0x2B, 0x27, 0x44, 0x77, 0x73, 0x71, 0x81, 0x82, 0x5F, 0x35, - 0xC9, 0xEE, 0x66, 0x10, 0x05, 0x11, 0x1F, 0x07, 0x0B, 0x13, 0x1A, 0x15, 0x2A, 0x37, 0x1F, 0xB4, 0x9D, 0x1E, 0x1E, 0x55, 0x5E, 0x61, 0x66, 0xA4, 0xFE, 0xFE, 0xB4, 0xB7, 0xC4, 0xF5, 0xFE, 0xE7, 0xD0, 0xED, 0xF3, 0xFE, 0xFE, 0xD5, 0xEF, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0x7F, 0x00, 0x00, 0x00, - 0x58, 0x00, 0xC8, 0xBE, 0x10, 0x39, 0x2D, 0x1B, 0x49, 0x54, 0x4E, 0x49, 0x73, 0x39, 0x29, 0x4E, 0xF2, 0xF8, 0x6A, 0x2A, 0x18, 0x14, 0x1D, 0x22, 0x13, 0x1E, 0x28, 0x0E, 0x31, 0x34, 0x27, 0xA5, 0xAA, 0x1E, 0x1E, 0x4D, 0x5C, 0x5D, 0x62, 0x81, 0xFC, 0xFE, 0xD6, 0xA1, 0xB3, 0xDF, 0xFE, 0xFC, 0xD5, 0xE0, 0xE1, 0xEF, 0xFE, 0xF8, 0xE2, 0xF1, 0xF9, 0xFC, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, - 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, 0xF9, 0xA7, 0xA1, 0x9C, 0x96, 0x8F, 0x48, 0x00, 0x00, 0x00, 0x7C, 0x00, 0xCD, 0xB2, 0x1A, 0x2F, 0x2D, 0x12, 0x1D, 0x1F, 0x1D, 0x1A, 0x43, 0x20, 0x06, 0x29, 0x44, 0x4A, 0x23, 0x37, 0x3A, 0x16, 0x2F, 0x32, 0x20, 0x2B, 0x35, 0x19, 0x34, 0x33, 0x33, 0x9B, 0xAF, 0x1F, 0x1E, 0x4B, 0x5C, 0x5D, 0x61, 0x62, 0xCC, 0xFE, 0xFC, 0xA9, 0x9D, 0xB0, 0xF2, 0xFE, - 0xF7, 0xD8, 0xD2, 0xAC, 0xF7, 0xFE, 0xF5, 0xD7, 0xF2, 0xFA, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFD, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xD4, 0xD5, 0x95, 0x00, 0x97, 0x00, 0xCA, 0xB1, 0x18, 0x2B, 0x2B, 0x11, 0x15, 0x19, 0x17, 0x12, 0x2C, 0x10, 0x01, 0x0A, 0x0D, 0x20, 0x36, 0x4D, 0x4C, 0x25, 0x44, 0x46, 0x33, 0x3D, 0x47, 0x20, 0x39, 0x34, 0x35, 0x98, - 0xAF, 0x20, 0x1E, 0x4D, 0x5E, 0x60, 0x63, 0x64, 0x69, 0xE4, 0xFE, 0xF4, 0x9F, 0xAF, 0xA1, 0xF8, 0xFE, 0xF0, 0xCC, 0x9E, 0xB4, 0xFC, 0xFE, 0xE3, 0xDF, 0xF6, 0xFC, 0xFC, 0xFC, 0xFB, 0xFD, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFC, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x6E, 0xFE, 0xFE, 0xB1, 0x00, 0xA5, 0x00, 0xC0, 0xB8, 0x10, 0x2D, 0x28, 0x16, 0x0F, 0x14, 0x10, 0x0A, 0x1E, 0x04, 0x01, 0x04, - 0x1A, 0x31, 0x4A, 0x62, 0x3C, 0x41, 0x54, 0x58, 0x4B, 0x53, 0x5D, 0x1D, 0x42, 0x38, 0x2F, 0x9D, 0xAC, 0x1F, 0x1E, 0x55, 0x62, 0x64, 0x66, 0x67, 0x65, 0x7C, 0xF7, 0xFE, 0xC8, 0x80, 0x86, 0xBB, 0xFE, 0xFE, 0xA3, 0x99, 0x9A, 0xD2, 0xFE, 0xFA, 0xD1, 0xEA, 0xF6, 0xF9, 0xFC, 0xFB, 0xFC, 0xFC, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xDA, 0xD9, 0x99, 0x00, - 0xB8, 0x00, 0xAE, 0xC5, 0x1A, 0x2E, 0x24, 0x1E, 0x0A, 0x0E, 0x08, 0x01, 0x17, 0x0C, 0x06, 0x01, 0x16, 0x36, 0x4A, 0x3A, 0x35, 0x64, 0x73, 0x5E, 0x67, 0x6E, 0x6B, 0x22, 0x48, 0x3C, 0x1F, 0xA9, 0xA2, 0x1E, 0x1E, 0x5F, 0x66, 0x68, 0x69, 0x69, 0x69, 0x67, 0xCC, 0xFE, 0xEA, 0x73, 0x89, 0x8A, 0xF5, 0xFE, 0xBE, 0x93, 0x9F, 0xA7, 0xFD, 0xFE, 0xD4, 0xE1, 0xF5, 0xF7, 0xFB, 0xFC, 0xFC, 0xFC, - 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFD, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x95, 0xC8, 0x5D, 0x2D, 0x1D, 0x29, 0x09, 0x03, 0x02, 0x02, 0x01, 0x1F, 0x0C, 0x11, 0x11, 0x15, 0x23, 0x43, 0x67, 0x77, 0x81, 0x7A, 0x85, 0x8B, 0x5F, 0x3A, 0x41, 0x3F, 0x3A, 0xB1, 0x8F, 0x1E, 0x28, 0x69, 0x6A, 0x6C, 0x6C, 0x6B, 0x6D, 0x6C, 0xB1, 0xFE, 0xF2, 0x75, 0x8A, 0x8E, - 0xE5, 0xFE, 0xC2, 0x90, 0xA3, 0xA2, 0xFB, 0xFE, 0xD1, 0xDF, 0xF5, 0xF7, 0xFA, 0xFD, 0xFD, 0xFD, 0xFE, 0xFD, 0xE9, 0xAE, 0xAC, 0xAA, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x6D, 0x64, 0xC3, 0x8E, 0x21, 0x20, 0x2C, 0x16, 0x03, 0x02, 0x02, 0x07, 0x09, 0x20, 0x23, 0x23, 0x34, 0x46, 0x5A, 0x79, 0x85, 0x89, 0x9B, 0xA2, 0x97, 0x22, 0x50, 0x2F, 0x3A, 0x73, 0xB2, - 0x71, 0x1E, 0x4B, 0x6C, 0x6E, 0x6F, 0x6F, 0x6E, 0x70, 0x70, 0xB7, 0xFE, 0xE8, 0x79, 0x8C, 0x92, 0xE9, 0xFE, 0xB7, 0x96, 0xA9, 0xAD, 0xFD, 0xFA, 0xC5, 0xE2, 0xF6, 0xF9, 0xFB, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xD7, 0x00, 0x00, 0x00, 0x00, 0xC7, 0xF6, 0xF6, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xB0, 0x20, 0xB1, 0xB4, 0x23, 0x2A, 0x1E, 0x28, 0x09, 0x02, 0x07, 0x0E, 0x11, 0x12, 0x1D, - 0x31, 0x41, 0x55, 0x66, 0x6D, 0x8B, 0xAB, 0xB2, 0xB8, 0x5C, 0x44, 0x4F, 0x3B, 0x20, 0xA7, 0xB5, 0x38, 0x1E, 0x84, 0x6E, 0x70, 0x71, 0x72, 0x72, 0x73, 0x76, 0xD6, 0xFE, 0xC4, 0x80, 0x92, 0x9D, 0xFB, 0xF9, 0x9A, 0xA1, 0xAF, 0xCA, 0xFE, 0xE3, 0xC2, 0xEB, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xD7, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xFD, 0xFD, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x54, 0xDD, 0x29, 0x80, 0xBE, 0x81, 0x1F, 0x28, 0x28, 0x24, 0x08, 0x0D, 0x13, 0x18, 0x1F, 0x28, 0x30, 0x3A, 0x4D, 0x65, 0x81, 0x9B, 0xCB, 0xF5, 0x8B, 0x3D, 0x68, 0x39, 0x46, 0x66, 0xBD, 0x94, 0x1E, 0x4E, 0xA2, 0x7D, 0x73, 0x74, 0x75, 0x76, 0x76, 0x8A, 0xF9, 0xF5, 0x87, 0x8F, 0x9C, 0xCD, 0xFE, 0xD2, 0xA2, 0xB1, 0xB4, 0xEF, 0xFA, 0xBC, 0xCA, 0xF2, 0xFD, 0xFE, 0xFC, 0xFA, 0xFB, 0xFD, - 0xFD, 0xFC, 0xD6, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFD, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x93, 0x29, 0xB0, 0xBA, 0x47, 0x2F, 0x20, 0x2D, 0x20, 0x09, 0x14, 0x23, 0x2D, 0x37, 0x43, 0x4E, 0x5D, 0x6F, 0x86, 0xA1, 0xB0, 0x85, 0x41, 0x7A, 0x48, 0x57, 0x29, 0xAD, 0xB8, 0x48, 0x1E, 0x93, 0xA5, 0x95, 0x7A, 0x78, 0x79, 0x7A, 0x7C, 0xD7, 0xFE, 0xB0, 0x8C, 0xA2, 0xB0, 0xF9, - 0xED, 0xAA, 0xB3, 0xC0, 0xD5, 0xFC, 0xCC, 0xBA, 0xD7, 0xF2, 0xFD, 0xFD, 0xFD, 0xFC, 0xFA, 0xE9, 0xE7, 0xE6, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x69, 0x7A, 0x78, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xCF, 0x3C, 0x65, 0xBC, 0xA8, 0x28, 0x35, 0x1E, 0x29, 0x28, 0x11, 0x12, 0x2A, 0x42, 0x58, 0x64, 0x70, 0x79, 0x79, 0x63, 0x20, 0x5F, 0x82, 0x50, 0x5F, 0x30, 0x96, 0xBE, 0x86, 0x1E, - 0x6E, 0xB1, 0xA9, 0xA2, 0x88, 0x7E, 0x7D, 0x7E, 0x89, 0xD4, 0xC3, 0x90, 0xA2, 0xAE, 0xBD, 0xD9, 0xBE, 0xBB, 0xC4, 0xC8, 0xC9, 0xCA, 0xD0, 0xC8, 0xD1, 0xEE, 0xFD, 0xFD, 0xFD, 0xFE, 0xEA, 0x00, 0x00, 0x00, 0x55, 0x63, 0x6E, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0xAB, 0x1E, 0x85, 0xBA, 0x9E, 0x23, 0x2E, 0x20, 0x24, 0x2E, 0x25, 0x18, 0x11, - 0x19, 0x22, 0x25, 0x16, 0x22, 0x54, 0x78, 0x75, 0x45, 0x62, 0x31, 0x87, 0xC2, 0xA7, 0x24, 0x4A, 0xB2, 0xB4, 0xAE, 0xA7, 0x9F, 0x85, 0x80, 0x82, 0x85, 0x8C, 0x96, 0xA4, 0xAD, 0xB5, 0xBB, 0xC3, 0xC7, 0xC9, 0xCB, 0xCE, 0xD1, 0xD0, 0xDE, 0xCF, 0xD5, 0xEF, 0xFE, 0xFE, 0xFE, 0xFD, 0xE8, 0x00, 0x00, 0x00, 0xF4, 0xFE, 0xFE, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x35, 0xBD, 0x8C, 0x1F, 0x91, 0xB8, 0x9F, 0x36, 0x25, 0x2E, 0x1E, 0x26, 0x34, 0x37, 0x3C, 0x45, 0x55, 0x68, 0x79, 0x6A, 0x43, 0x51, 0x56, 0x28, 0x99, 0xC7, 0xAE, 0x39, 0x42, 0xB5, 0xBD, 0xB7, 0xB2, 0xAC, 0xA6, 0x97, 0x83, 0x85, 0x8A, 0x91, 0x9A, 0xA6, 0xB1, 0xBA, 0xBF, 0xC6, 0xCB, 0xCD, 0xCF, 0xD6, 0xF2, 0xF2, 0xEF, 0xF1, 0xF6, 0xF9, 0xFC, 0xFD, 0xD5, 0x6C, 0x64, 0x00, - 0x00, 0x00, 0xF1, 0xFE, 0xFE, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xBA, 0x83, 0x20, 0x86, 0xB2, 0xAA, 0x67, 0x14, 0x2A, 0x2F, 0x2C, 0x25, 0x29, 0x31, 0x35, 0x37, 0x43, 0x4F, 0x50, 0x36, 0x5E, 0xBC, 0xD0, 0xAE, 0x3A, 0x4A, 0xBC, 0xC9, 0xC1, 0xBA, 0xB4, 0xAD, 0xA4, 0x9B, 0x8D, 0x87, 0x8E, 0x95, 0x9B, 0xA8, 0xB5, 0xBE, 0xC3, 0xC8, - 0xCD, 0xD0, 0xD3, 0xDC, 0xFB, 0xFD, 0xF6, 0xF6, 0xF9, 0xF9, 0xFB, 0xFD, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xFC, 0xFC, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xB0, 0x8C, 0x25, 0x63, 0xA8, 0xB4, 0xA0, 0x6E, 0x25, 0x1C, 0x2C, 0x38, 0x43, 0x49, 0x47, 0x36, 0x18, 0x69, 0xB2, 0xD7, 0xD4, 0x93, 0x24, 0x71, 0xC3, 0xCE, 0xBB, - 0x9B, 0x79, 0x5B, 0x37, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x4C, 0x69, 0x8B, 0xB2, 0xC2, 0xC6, 0xCC, 0xD0, 0xD3, 0xD7, 0xDF, 0xF4, 0xF6, 0xF3, 0xF6, 0xF9, 0xFA, 0xFC, 0xE9, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x3F, 0x3D, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x99, 0x99, 0x48, 0x32, 0x81, 0xAA, 0xB2, 0xB2, 0xA0, 0x8D, - 0x80, 0x79, 0x7F, 0x92, 0xAA, 0xCC, 0xDC, 0xD8, 0xAE, 0x59, 0x3E, 0x8E, 0xA2, 0x7D, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x98, 0xBB, 0xD2, 0xD8, 0xDD, 0xE3, 0xE8, 0xEC, 0xF1, 0xF8, 0xFB, 0xFA, 0xD1, 0x57, 0x00, 0x67, 0xA7, 0xA9, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x9A, 0x76, 0x3B, 0x2A, 0x6B, 0x92, 0xAE, 0xBC, 0xBF, 0xC0, 0xC5, 0xCC, 0xD0, 0xBB, 0x95, 0x54, 0x1E, 0x32, 0x50, 0x22, 0x1E, 0x21, 0x36, 0x48, 0x55, 0x59, 0x56, 0x52, 0x49, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x75, 0x9A, 0xB5, 0xC5, 0xCA, 0xCD, 0xC2, 0xA5, 0x5D, 0x00, 0x00, 0x00, 0x9D, 0xFE, 0xFE, - 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x71, 0x8F, 0x7C, 0x5D, 0x38, 0x1F, 0x34, 0x59, 0x66, 0x67, 0x55, 0x27, 0x1E, 0x1E, 0x25, 0x45, 0x60, 0x6E, 0x77, 0x7D, 0x86, 0x86, 0x85, 0x85, 0x82, 0x7F, 0x7C, 0x77, 0x73, 0x6F, 0x65, 0x58, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xFD, 0xFC, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x61, 0x81, 0x92, 0x8D, 0x88, 0x89, 0x8A, 0x8A, 0x8B, 0x8D, 0x93, 0x9A, 0xA1, 0xA0, 0x9B, 0x94, 0x8E, 0x88, 0x83, 0x78, 0x72, - 0x72, 0x70, 0x6D, 0x69, 0x66, 0x65, 0x63, 0x62, 0x69, 0x71, 0x6F, 0x5D, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x62, 0x7C, - 0x94, 0xA1, 0xA8, 0xA8, 0xA7, 0xA4, 0x9F, 0x92, 0x81, 0x70, 0x5E, 0x4A, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0xAC,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x9A,0xEF,0xFD,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xD9,0xFE,0xFE,0xFE,0x53,0x00,0x00,0x00,0x00,0x6C,0xA9,0xAA,0xAB,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xF7,0xFE,0xFE,0xFE,0xFD,0x48,0x00,0x00,0x00,0x00,0xA2,0xFE,0xFE,0xFD,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xC6,0xFE,0xFD,0xFD,0xFE,0xFE,0xFD,0x6D,0x00,0x00,0x00,0x00,0xA1,0xFE,0xFE,0xFD,0x3C,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xE4,0xFD,0xFE,0xFD, + 0xFE,0xFE,0xFE,0xFE,0xA3,0x00,0x00,0x00,0x00,0x8A,0xD6,0xD5,0xD4,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xF5,0xFE,0xFC,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xEA,0x00,0x37,0x6E,0xAA,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0xC8,0xFA,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xF9,0xFC,0xFE,0xFE,0x5D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0xD7,0xD9,0xA4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xA2,0xEC,0xFA,0xFB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x4C,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x7D,0xFE,0xFE,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,0x68,0xA9,0xDA,0xE9,0xF2,0xF8,0xFA,0xFB,0xFD,0xFD,0xFD,0xFE, + 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x44,0x00,0x00,0x55,0x87,0x88,0x8B,0x43,0x6F,0xE5,0xE3,0xA8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x62,0x67,0x53,0x41,0x37,0x37,0x42,0x53, + 0x66,0x80,0xA0,0xC1,0xD1,0xD8,0xDE,0xE5,0xEE,0xF6,0xF8,0xFA,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xD0,0xCE,0xD0,0xE4,0xFE,0xFE,0xFE,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,0x00,0x00,0x69,0x9E,0xBB, + 0xC8,0xCE,0xCC,0xC1,0xA6,0x79,0x00,0x00,0x00,0x60,0x8D,0xA1,0x96,0x90,0x98,0xA1,0xAA,0xB3,0xBE,0xC7,0xCE,0xD3,0xDA,0xE1,0xE9,0xF1,0xF7,0xF8,0xFB,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAF,0xE9,0xFC,0xFB,0xF4,0xEA,0xE8,0xEA,0xF1,0xF6,0xF7,0xEC,0xBD,0x5F,0x1E,0x1E,0x53,0x85,0x8C,0x97,0xA1,0xAB,0xB2,0xBB,0xC2,0xC8,0xCD,0xD5,0xDD,0xE4,0xED,0xF3,0xF7,0xFB,0xFD,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, + 0x71,0x00,0x00,0x00,0x7F,0xBE,0xBE,0xBF,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xE8,0xF6,0xDB,0xA8,0x69,0x2D,0x25,0x2D,0x26,0x29,0x5E,0x99,0xCE,0xEE,0xEB,0xB2,0x3C,0x1E,0x26,0x6C,0x91,0x9C,0xA7,0xAF,0xB7,0xBD,0xC3,0xCA,0xD0,0xD7,0xDE,0xE8,0xF0,0xF5,0xFA,0xFC,0xFE,0xFD, + 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x6F,0x00,0x00,0x00,0xA9,0xFE,0xFE,0xFD,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0xD8,0xF2,0xC4,0x70,0x31,0x4C,0x4D,0x4F,0x49,0x48,0x45,0x4B,0x4D,0x48,0x27,0x69,0xC2,0xE4,0xD9,0x71,0x1E,0x1E,0x64,0x97, + 0xA3,0xAC,0xB3,0xB9,0xBF,0xC6,0xCC,0xD2,0xDA,0xE3,0xED,0xF4,0xFA,0xFD,0xFE,0xFD,0xFC,0xFC,0xFD,0xFD,0xFE,0xFD,0xF6,0xF2,0xFB,0xFD,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0x9D,0x00,0x00,0x00,0xA9,0xFE,0xFE,0xFD,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xEF,0xE6,0x89,0x2C,0x4E,0x4B,0x2E,0x3F,0x4A, + 0x4F,0x4C,0x48,0x40,0x31,0x21,0x34,0x42,0x28,0x86,0xDD,0xE2,0x84,0x1E,0x1E,0x6E,0x9E,0xA8,0xAE,0xB4,0xBA,0xC0,0xC5,0xCC,0xD3,0xDC,0xEC,0xFC,0xEE,0xFA,0xFD,0xFD,0xFE,0xEC,0xF5,0xFC,0xFD,0xFD,0xFD,0xDC,0xF3,0xFC,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xA9,0x00,0x00,0x00,0x87,0xC9,0xC9,0xC7,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x99,0xEF,0xD8,0x5B,0x42,0x4B,0x34,0x52,0x58,0x41,0x2C,0x29,0x27,0x1E,0x1E,0x26,0x31,0x31,0x21,0x38,0x39,0x61,0xD3,0xDC,0x7A,0x1E,0x20,0x80,0xA1,0xA9,0xAD,0xB3,0xB9,0xBF,0xC5,0xCD,0xD4,0xE5,0xFE,0xE4,0xE8,0xFA,0xFB,0xFE,0xEF,0xDF,0xFA,0xFD,0xFD,0xFE,0xE1,0xEA,0xFC,0xFC,0xFD,0xFD,0xFC,0xFD,0xFC, + 0xE0,0xCA,0xCB,0xCC,0x5D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xE7,0xD7,0x4A,0x4B,0x3C,0x42,0x52,0x35,0x7B,0xBF,0xAA,0x95,0x6D,0x49,0x35,0x22,0x10,0x16,0x2E,0x28,0x29,0x3B,0x55,0xD2,0xD6,0x56,0x1E,0x35,0x96,0xA3,0xA8,0xAD,0xB3,0xB9,0xC0,0xC7,0xCE,0xEB,0xFE,0xE4,0xD7,0xF5,0xF7, + 0xFE,0xEE,0xD4,0xF6,0xFC,0xFE,0xFE,0xDE,0xE8,0xFC,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFB,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xF0,0xF0,0xE6,0x00,0x00,0x00,0x00,0xD1,0xE0,0x66,0x3C,0x39,0x3F,0x44,0x4B,0xD1,0xFE,0xFF,0xE6,0x95,0x66,0x43,0x2F,0x20,0x17,0x11,0x07,0x20,0x2C,0x24,0x3B,0x68,0xD4,0xB8,0x1F, + 0x1E,0x67,0x9B,0xA0,0xA7,0xAD,0xB4,0xBA,0xC1,0xCB,0xFA,0xFD,0xD1,0xD3,0xF0,0xFA,0xFD,0xDC,0xD3,0xF5,0xFB,0xFE,0xF5,0xDA,0xF0,0xFB,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFD,0xFD,0xFC,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xFE,0xFE,0xF0,0x00,0x00,0x00,0x8F,0xE9,0x9F,0x26,0x3C,0x36,0x3D,0x45,0xE9,0xFF,0xFF,0xFF,0xF1, + 0x8F,0x5A,0x38,0x26,0x1A,0x14,0x11,0x0E,0x05,0x1C,0x28,0x2E,0x2C,0x9E,0xD2,0x7B,0x1E,0x26,0x8C,0x99,0xA0,0xA6,0xAD,0xB3,0xB8,0xE9,0xFE,0xED,0xC1,0xDF,0xF6,0xFE,0xF7,0xC3,0xDE,0xF8,0xFD,0xFD,0xE5,0xE6,0xF9,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFC,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xFE,0xFE,0xF0, + 0x00,0x00,0x00,0xD2,0xD7,0x35,0x43,0x27,0x3D,0x27,0xB3,0xFD,0xFE,0xFE,0xFE,0xD1,0x9F,0x81,0x5A,0x37,0x11,0x10,0x0E,0x0B,0x04,0x01,0x20,0x21,0x35,0x3C,0xC4,0xB5,0x1E,0x1E,0x6A,0x91,0x98,0xA0,0xA4,0xA3,0xC4,0xFE,0xFB,0xB0,0xC1,0xEA,0xFE,0xFE,0xCC,0xC5,0xEC,0xFB,0xFE,0xE8,0xE0,0xF2,0xFD,0xFD,0xFE,0xFE,0xFD,0xFD,0xFD,0xFE, + 0xFE,0xFD,0xFD,0xFC,0xC4,0xB9,0xBA,0xBB,0xC1,0xC3,0xC5,0xC8,0x78,0x6C,0x6A,0x65,0x00,0x00,0x6C,0xE3,0xA1,0x28,0x33,0x38,0x24,0x7E,0xB4,0xD1,0xF0,0xEC,0xE7,0xC7,0x88,0x54,0x36,0x2B,0x2A,0x17,0x06,0x04,0x01,0x03,0x06,0x28,0x20,0x2F,0x97,0xC1,0x5F,0x1E,0x42,0x79,0x74,0x75,0x76,0x77,0xF0,0xFE,0xCE,0x99,0xC9,0xF0,0xFE,0xEF, + 0xBE,0xDA,0xF1,0xFE,0xFE,0xCF,0xEB,0xFC,0xFE,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0xA2,0xDE,0x5F,0x3C,0x24,0x35,0x1B,0x90,0x97,0x98,0x93,0xBD,0xA1,0x81,0x5A,0x32,0x1B,0x10,0x0E,0x1D,0x17,0x01,0x05,0x0A,0x09,0x20,0x22,0x38,0x62,0xBC, + 0x8B,0x1E,0x1F,0x5E,0x61,0x67,0x6D,0x9C,0xFE,0xFE,0xAE,0xB7,0xC6,0xF5,0xFE,0xDF,0xD1,0xED,0xF6,0xFE,0xFE,0xC5,0xF1,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0x7E,0x00,0x00,0x00,0x00,0x00,0xBB,0xD2,0x20,0x3C,0x2B,0x27,0x44,0x77,0x73,0x71,0x81,0x82,0x5F,0x35, + 0xC9,0xEE,0x66,0x10,0x05,0x11,0x1F,0x07,0x0B,0x13,0x1A,0x15,0x2A,0x37,0x1F,0xB4,0x9D,0x1E,0x1E,0x55,0x5E,0x61,0x66,0xA4,0xFE,0xFE,0xB4,0xB7,0xC4,0xF5,0xFE,0xE7,0xD0,0xED,0xF3,0xFE,0xFE,0xD5,0xEF,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFC,0xFE,0xFE,0xFE,0xFE,0x7F,0x00,0x00,0x00, + 0x58,0x00,0xC8,0xBE,0x10,0x39,0x2D,0x1B,0x49,0x54,0x4E,0x49,0x73,0x39,0x29,0x4E,0xF2,0xF8,0x6A,0x2A,0x18,0x14,0x1D,0x22,0x13,0x1E,0x28,0x0E,0x31,0x34,0x27,0xA5,0xAA,0x1E,0x1E,0x4D,0x5C,0x5D,0x62,0x81,0xFC,0xFE,0xD6,0xA1,0xB3,0xDF,0xFE,0xFC,0xD5,0xE0,0xE1,0xEF,0xFE,0xF8,0xE2,0xF1,0xF9,0xFC,0xFE,0xFD,0xFD,0xFD,0xFE,0xFE, + 0xFE,0xFD,0xFD,0xFD,0xFD,0xFE,0xF9,0xA7,0xA1,0x9C,0x96,0x8F,0x48,0x00,0x00,0x00,0x7C,0x00,0xCD,0xB2,0x1A,0x2F,0x2D,0x12,0x1D,0x1F,0x1D,0x1A,0x43,0x20,0x06,0x29,0x44,0x4A,0x23,0x37,0x3A,0x16,0x2F,0x32,0x20,0x2B,0x35,0x19,0x34,0x33,0x33,0x9B,0xAF,0x1F,0x1E,0x4B,0x5C,0x5D,0x61,0x62,0xCC,0xFE,0xFC,0xA9,0x9D,0xB0,0xF2,0xFE, + 0xF7,0xD8,0xD2,0xAC,0xF7,0xFE,0xF5,0xD7,0xF2,0xFA,0xFE,0xFD,0xFD,0xFD,0xFE,0xFD,0xFD,0xFD,0xFD,0xFD,0xFC,0xFD,0xF3,0x00,0x00,0x00,0x00,0x5D,0xD4,0xD5,0x95,0x00,0x97,0x00,0xCA,0xB1,0x18,0x2B,0x2B,0x11,0x15,0x19,0x17,0x12,0x2C,0x10,0x01,0x0A,0x0D,0x20,0x36,0x4D,0x4C,0x25,0x44,0x46,0x33,0x3D,0x47,0x20,0x39,0x34,0x35,0x98, + 0xAF,0x20,0x1E,0x4D,0x5E,0x60,0x63,0x64,0x69,0xE4,0xFE,0xF4,0x9F,0xAF,0xA1,0xF8,0xFE,0xF0,0xCC,0x9E,0xB4,0xFC,0xFE,0xE3,0xDF,0xF6,0xFC,0xFC,0xFC,0xFB,0xFD,0xFC,0xFD,0xFD,0xFD,0xFD,0xFC,0xFC,0xF0,0x00,0x00,0x00,0x00,0x6E,0xFE,0xFE,0xB1,0x00,0xA5,0x00,0xC0,0xB8,0x10,0x2D,0x28,0x16,0x0F,0x14,0x10,0x0A,0x1E,0x04,0x01,0x04, + 0x1A,0x31,0x4A,0x62,0x3C,0x41,0x54,0x58,0x4B,0x53,0x5D,0x1D,0x42,0x38,0x2F,0x9D,0xAC,0x1F,0x1E,0x55,0x62,0x64,0x66,0x67,0x65,0x7C,0xF7,0xFE,0xC8,0x80,0x86,0xBB,0xFE,0xFE,0xA3,0x99,0x9A,0xD2,0xFE,0xFA,0xD1,0xEA,0xF6,0xF9,0xFC,0xFB,0xFC,0xFC,0xFE,0xFD,0xFD,0xFD,0xFD,0xFD,0xF0,0x00,0x00,0x00,0x00,0x5D,0xDA,0xD9,0x99,0x00, + 0xB8,0x00,0xAE,0xC5,0x1A,0x2E,0x24,0x1E,0x0A,0x0E,0x08,0x01,0x17,0x0C,0x06,0x01,0x16,0x36,0x4A,0x3A,0x35,0x64,0x73,0x5E,0x67,0x6E,0x6B,0x22,0x48,0x3C,0x1F,0xA9,0xA2,0x1E,0x1E,0x5F,0x66,0x68,0x69,0x69,0x69,0x67,0xCC,0xFE,0xEA,0x73,0x89,0x8A,0xF5,0xFE,0xBE,0x93,0x9F,0xA7,0xFD,0xFE,0xD4,0xE1,0xF5,0xF7,0xFB,0xFC,0xFC,0xFC, + 0xFE,0xFD,0xFE,0xFE,0xFE,0xFD,0xF1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0x00,0x95,0xC8,0x5D,0x2D,0x1D,0x29,0x09,0x03,0x02,0x02,0x01,0x1F,0x0C,0x11,0x11,0x15,0x23,0x43,0x67,0x77,0x81,0x7A,0x85,0x8B,0x5F,0x3A,0x41,0x3F,0x3A,0xB1,0x8F,0x1E,0x28,0x69,0x6A,0x6C,0x6C,0x6B,0x6D,0x6C,0xB1,0xFE,0xF2,0x75,0x8A,0x8E, + 0xE5,0xFE,0xC2,0x90,0xA3,0xA2,0xFB,0xFE,0xD1,0xDF,0xF5,0xF7,0xFA,0xFD,0xFD,0xFD,0xFE,0xFD,0xE9,0xAE,0xAC,0xAA,0x9F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0x6D,0x64,0xC3,0x8E,0x21,0x20,0x2C,0x16,0x03,0x02,0x02,0x07,0x09,0x20,0x23,0x23,0x34,0x46,0x5A,0x79,0x85,0x89,0x9B,0xA2,0x97,0x22,0x50,0x2F,0x3A,0x73,0xB2, + 0x71,0x1E,0x4B,0x6C,0x6E,0x6F,0x6F,0x6E,0x70,0x70,0xB7,0xFE,0xE8,0x79,0x8C,0x92,0xE9,0xFE,0xB7,0x96,0xA9,0xAD,0xFD,0xFA,0xC5,0xE2,0xF6,0xF9,0xFB,0xFE,0xFE,0xFE,0xFE,0xFD,0xD7,0x00,0x00,0x00,0x00,0xC7,0xF6,0xF6,0xE1,0x00,0x00,0x00,0x00,0x00,0xA0,0xB0,0x20,0xB1,0xB4,0x23,0x2A,0x1E,0x28,0x09,0x02,0x07,0x0E,0x11,0x12,0x1D, + 0x31,0x41,0x55,0x66,0x6D,0x8B,0xAB,0xB2,0xB8,0x5C,0x44,0x4F,0x3B,0x20,0xA7,0xB5,0x38,0x1E,0x84,0x6E,0x70,0x71,0x72,0x72,0x73,0x76,0xD6,0xFE,0xC4,0x80,0x92,0x9D,0xFB,0xF9,0x9A,0xA1,0xAF,0xCA,0xFE,0xE3,0xC2,0xEB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFD,0xFD,0xD7,0x00,0x00,0x00,0x00,0xCE,0xFD,0xFD,0xE6,0x00,0x00,0x00,0x00,0x00, + 0x54,0xDD,0x29,0x80,0xBE,0x81,0x1F,0x28,0x28,0x24,0x08,0x0D,0x13,0x18,0x1F,0x28,0x30,0x3A,0x4D,0x65,0x81,0x9B,0xCB,0xF5,0x8B,0x3D,0x68,0x39,0x46,0x66,0xBD,0x94,0x1E,0x4E,0xA2,0x7D,0x73,0x74,0x75,0x76,0x76,0x8A,0xF9,0xF5,0x87,0x8F,0x9C,0xCD,0xFE,0xD2,0xA2,0xB1,0xB4,0xEF,0xFA,0xBC,0xCA,0xF2,0xFD,0xFE,0xFC,0xFA,0xFB,0xFD, + 0xFD,0xFC,0xD6,0x00,0x00,0x00,0x00,0xD0,0xFE,0xFD,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x93,0x29,0xB0,0xBA,0x47,0x2F,0x20,0x2D,0x20,0x09,0x14,0x23,0x2D,0x37,0x43,0x4E,0x5D,0x6F,0x86,0xA1,0xB0,0x85,0x41,0x7A,0x48,0x57,0x29,0xAD,0xB8,0x48,0x1E,0x93,0xA5,0x95,0x7A,0x78,0x79,0x7A,0x7C,0xD7,0xFE,0xB0,0x8C,0xA2,0xB0,0xF9, + 0xED,0xAA,0xB3,0xC0,0xD5,0xFC,0xCC,0xBA,0xD7,0xF2,0xFD,0xFD,0xFD,0xFC,0xFA,0xE9,0xE7,0xE6,0xC3,0x00,0x00,0x00,0x00,0x69,0x7A,0x78,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xCF,0x3C,0x65,0xBC,0xA8,0x28,0x35,0x1E,0x29,0x28,0x11,0x12,0x2A,0x42,0x58,0x64,0x70,0x79,0x79,0x63,0x20,0x5F,0x82,0x50,0x5F,0x30,0x96,0xBE,0x86,0x1E, + 0x6E,0xB1,0xA9,0xA2,0x88,0x7E,0x7D,0x7E,0x89,0xD4,0xC3,0x90,0xA2,0xAE,0xBD,0xD9,0xBE,0xBB,0xC4,0xC8,0xC9,0xCA,0xD0,0xC8,0xD1,0xEE,0xFD,0xFD,0xFD,0xFE,0xEA,0x00,0x00,0x00,0x55,0x63,0x6E,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA7,0xAB,0x1E,0x85,0xBA,0x9E,0x23,0x2E,0x20,0x24,0x2E,0x25,0x18,0x11, + 0x19,0x22,0x25,0x16,0x22,0x54,0x78,0x75,0x45,0x62,0x31,0x87,0xC2,0xA7,0x24,0x4A,0xB2,0xB4,0xAE,0xA7,0x9F,0x85,0x80,0x82,0x85,0x8C,0x96,0xA4,0xAD,0xB5,0xBB,0xC3,0xC7,0xC9,0xCB,0xCE,0xD1,0xD0,0xDE,0xCF,0xD5,0xEF,0xFE,0xFE,0xFE,0xFD,0xE8,0x00,0x00,0x00,0xF4,0xFE,0xFE,0xC2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x35,0xBD,0x8C,0x1F,0x91,0xB8,0x9F,0x36,0x25,0x2E,0x1E,0x26,0x34,0x37,0x3C,0x45,0x55,0x68,0x79,0x6A,0x43,0x51,0x56,0x28,0x99,0xC7,0xAE,0x39,0x42,0xB5,0xBD,0xB7,0xB2,0xAC,0xA6,0x97,0x83,0x85,0x8A,0x91,0x9A,0xA6,0xB1,0xBA,0xBF,0xC6,0xCB,0xCD,0xCF,0xD6,0xF2,0xF2,0xEF,0xF1,0xF6,0xF9,0xFC,0xFD,0xD5,0x6C,0x64,0x00, + 0x00,0x00,0xF1,0xFE,0xFE,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xBA,0x83,0x20,0x86,0xB2,0xAA,0x67,0x14,0x2A,0x2F,0x2C,0x25,0x29,0x31,0x35,0x37,0x43,0x4F,0x50,0x36,0x5E,0xBC,0xD0,0xAE,0x3A,0x4A,0xBC,0xC9,0xC1,0xBA,0xB4,0xAD,0xA4,0x9B,0x8D,0x87,0x8E,0x95,0x9B,0xA8,0xB5,0xBE,0xC3,0xC8, + 0xCD,0xD0,0xD3,0xDC,0xFB,0xFD,0xF6,0xF6,0xF9,0xF9,0xFB,0xFD,0xAE,0x00,0x00,0x00,0x00,0x00,0xEF,0xFC,0xFC,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xB0,0x8C,0x25,0x63,0xA8,0xB4,0xA0,0x6E,0x25,0x1C,0x2C,0x38,0x43,0x49,0x47,0x36,0x18,0x69,0xB2,0xD7,0xD4,0x93,0x24,0x71,0xC3,0xCE,0xBB, + 0x9B,0x79,0x5B,0x37,0x00,0x00,0x00,0x00,0x1C,0x4C,0x69,0x8B,0xB2,0xC2,0xC6,0xCC,0xD0,0xD3,0xD7,0xDF,0xF4,0xF6,0xF3,0xF6,0xF9,0xFA,0xFC,0xE9,0x45,0x00,0x00,0x00,0x00,0x00,0x3D,0x3F,0x3D,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x99,0x99,0x48,0x32,0x81,0xAA,0xB2,0xB2,0xA0,0x8D, + 0x80,0x79,0x7F,0x92,0xAA,0xCC,0xDC,0xD8,0xAE,0x59,0x3E,0x8E,0xA2,0x7D,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x98,0xBB,0xD2,0xD8,0xDD,0xE3,0xE8,0xEC,0xF1,0xF8,0xFB,0xFA,0xD1,0x57,0x00,0x67,0xA7,0xA9,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x9A,0x76,0x3B,0x2A,0x6B,0x92,0xAE,0xBC,0xBF,0xC0,0xC5,0xCC,0xD0,0xBB,0x95,0x54,0x1E,0x32,0x50,0x22,0x1E,0x21,0x36,0x48,0x55,0x59,0x56,0x52,0x49,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x75,0x9A,0xB5,0xC5,0xCA,0xCD,0xC2,0xA5,0x5D,0x00,0x00,0x00,0x9D,0xFE,0xFE, + 0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x71,0x8F,0x7C,0x5D,0x38,0x1F,0x34,0x59,0x66,0x67,0x55,0x27,0x1E,0x1E,0x25,0x45,0x60,0x6E,0x77,0x7D,0x86,0x86,0x85,0x85,0x82,0x7F,0x7C,0x77,0x73,0x6F,0x65,0x58,0x42,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xFD,0xFC,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2D,0x61,0x81,0x92,0x8D,0x88,0x89,0x8A,0x8A,0x8B,0x8D,0x93,0x9A,0xA1,0xA0,0x9B,0x94,0x8E,0x88,0x83,0x78,0x72, + 0x72,0x70,0x6D,0x69,0x66,0x65,0x63,0x62,0x69,0x71,0x6F,0x5D,0x2D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x62,0x7C, + 0x94,0xA1,0xA8,0xA8,0xA7,0xA4,0x9F,0x92,0x81,0x70,0x5E,0x4A,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + }; const lv_image_dsc_t ui_img_logo_80x44_png = { .header.w = 80, diff --git a/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c b/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c index bc3ae45..0aadb66 100644 --- a/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c +++ b/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c @@ -1,291 +1,291 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision #include "../ui.h" #ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN + #define LV_ATTRIBUTE_MEM_ALIGN #endif // IMAGE DATA: assets/Text_218x40.png const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_text_218x40_png_data[] = { - 0xE1, 0x18, 0xE2, 0x10, 0x02, 0x19, 0x02, 0x11, 0xC1, 0x00, 0xA1, 0x00, 0xC1, 0x08, 0x02, 0x19, 0x22, 0x21, 0x22, 0x19, 0x22, 0x21, 0x22, 0x21, 0x42, 0x21, 0x42, 0x21, 0x02, 0x21, 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, 0xE6, 0x08, 0xE5, 0x10, 0xA4, 0x00, 0x23, 0x00, 0x23, 0x00, 0x84, 0x00, 0xC5, 0x10, 0x46, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x10, 0x26, 0x19, 0x46, 0x21, 0x46, 0x21, 0x67, 0x21, 0xA7, 0x29, 0xA8, 0x29, 0xE5, 0x10, 0x92, 0x94, 0x9A, 0xD6, 0xFB, 0xDE, 0xFB, 0xDE, - 0xFB, 0xDE, 0xFB, 0xDE, 0xDB, 0xDE, 0x14, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0x31, 0x79, 0xCE, 0x1C, 0xE7, 0x3C, 0xE7, 0x5D, 0xE7, 0x5D, 0xEF, 0x3D, 0xE7, 0x39, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xCD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x41, 0xDD, 0x41, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x62, 0xDD, 0x61, 0xDD, 0x02, 0xCD, 0xA3, 0xBC, 0xA2, 0x93, 0xA1, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xBE, 0xDB, 0xDE, 0xDB, 0xDE, 0xBB, 0xD6, 0xBB, 0xD6, 0xDB, 0xDE, 0xDB, 0xDE, 0x39, 0xC6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6B, 0x7A, 0xCE, 0xDB, 0xDE, 0xDB, 0xDE, 0xDB, 0xDE, 0xDB, 0xDE, 0xFB, 0xDE, 0xBA, 0xD6, 0xCC, 0x52, 0x38, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x73, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xED, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, - 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x21, 0xFE, 0x41, 0xFE, 0x21, 0xF6, 0xA1, 0xE5, 0x61, 0xB4, 0x21, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xEF, 0xF0, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xAD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDE, 0x93, 0x8C, 0x1C, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x7C, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x21, 0xFE, 0x21, 0xFE, 0x21, 0xFE, 0x41, 0xFE, 0x81, 0xE5, 0x21, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8C, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xD6, 0x00, 0x00, 0xFB, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x6B, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0xE1, 0xF5, 0x21, 0xBC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0x1C, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAF, 0x73, 0x3D, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xD3, 0x9C, 0x00, 0x00, 0xB7, 0xAD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x4A, 0x5D, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0x7A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0x61, 0xED, 0x61, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0x0C, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0xEC, 0x5A, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, - 0x39, 0xC6, 0xD3, 0x94, 0x76, 0xAD, 0x7A, 0xCE, 0xF4, 0x9C, 0x6A, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x8C, 0x7A, 0xCE, 0xDB, 0xD6, 0x7A, 0xC6, 0x5A, 0xC6, 0x76, 0xAD, 0x29, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0x21, 0xDD, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x01, 0xE5, 0x21, 0xE5, 0xA0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0x61, 0xCC, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7B, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x92, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0xF8, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0xCE, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xED, 0xA0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xA1, 0xFD, 0xC2, 0x82, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x41, 0x81, 0xA3, 0xE1, 0xD4, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x21, 0xED, 0x62, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x31, 0x41, 0x6A, 0xA2, 0xB3, 0x82, 0xAB, 0x61, 0x72, 0x01, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0xC3, 0x7A, 0x22, 0x93, 0x82, 0xA3, 0x81, 0xA3, 0x61, 0x9B, 0x41, 0x72, 0x81, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x3A, 0xFC, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0xE4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x6B, 0xDB, 0xDE, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x14, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x42, 0xCF, 0x73, 0xF3, 0x9C, 0xF4, 0x9C, 0x14, 0xA5, 0xD3, 0x9C, 0xB3, 0x94, 0x6A, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x08, 0x88, 0x31, 0x6E, 0x6B, 0xB3, 0x94, 0xF4, 0x9C, 0xF4, 0x9C, 0xB3, 0x94, 0x31, 0x84, 0x4A, 0x4A, 0xAC, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x8B, 0x01, 0x6B, 0x00, 0x8B, 0x01, 0x2B, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xB3, 0x94, 0x14, 0x9D, 0x14, 0xA5, 0xB3, 0x94, 0x11, 0x7C, 0xC8, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xED, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0xC1, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x62, 0xE1, 0xD4, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x82, 0xA3, 0x22, 0xAC, 0xA0, 0xD4, 0xA0, 0xD4, 0xA0, 0xD4, 0xA1, 0xCC, 0xA1, 0xCC, 0xA1, 0xCC, 0x61, 0xC4, 0x03, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xC4, 0x81, 0xD4, 0x81, 0xCC, 0x60, 0xCC, - 0x60, 0xCC, 0x80, 0xCC, 0xA0, 0xCC, 0x22, 0xB4, 0x00, 0x00, 0x03, 0xAC, 0xA1, 0xCC, 0xA0, 0xCC, 0xA1, 0xCC, 0xA1, 0xD4, 0x80, 0xD4, 0xE1, 0xB3, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x72, 0x01, 0xB4, 0x01, 0xE5, 0x61, 0xF5, 0xA1, 0xFD, 0x81, 0xFD, 0x60, 0xF5, 0xA1, 0xD4, 0x62, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6A, 0xC1, 0xA3, 0xE1, 0xD4, 0x41, 0xED, 0xA1, 0xF5, 0xC1, 0xFD, 0xC1, 0xFD, 0xC1, 0xFD, 0xC1, 0xFD, 0xA1, 0xF5, 0x61, 0xED, 0xC1, 0xD4, 0xA1, 0xA3, 0x21, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDE, 0xEF, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x31, 0x84, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0x9A, 0xCE, 0x9A, 0xD6, 0x9A, 0xD6, 0xBA, 0xD6, 0xBA, 0xD6, 0x9A, 0xD6, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x6B, 0x96, 0xB5, 0xBA, 0xD6, 0x7D, 0xEF, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0xDB, 0xDE, 0x59, 0xCE, 0xB3, 0x94, 0x0D, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7C, 0x39, 0xC6, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7B, 0x55, 0xA5, 0x9A, 0xD6, - 0x3D, 0xE7, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x7D, 0xEF, 0xBA, 0xD6, 0x18, 0xC6, 0x52, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x4A, 0xB7, 0xB5, 0x9A, 0xCE, 0x9A, 0xD6, 0x9A, 0xD6, 0x9A, 0xD6, 0x7A, 0xCE, 0x14, 0xA5, 0x00, 0x00, 0xF0, 0x7B, 0x76, 0xAD, 0xDB, 0xDE, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x5D, 0xE7, 0xBB, 0xD6, 0x35, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xED, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0xA1, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x7A, 0x61, 0xF5, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, - 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x42, 0xCC, 0xE1, 0x8A, 0x80, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x60, 0xF5, 0x42, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xDC, 0x80, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x81, 0xA3, 0x00, 0x00, 0x62, 0xC4, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x00, 0xED, 0x81, 0x08, 0xC2, 0xAB, 0x01, 0xE5, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0xC1, 0xE4, 0x81, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x92, 0xE1, 0xB3, 0x01, 0xE5, 0x80, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, - 0xC1, 0xFD, 0xC1, 0xFD, 0xA1, 0xFD, 0x01, 0xDD, 0x81, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x84, 0x7E, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x71, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xC6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xBD, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x35, 0xA5, 0xFC, 0xDE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x9E, 0xF7, 0xDB, 0xDE, 0x51, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x31, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0x3C, 0xE7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xEF, 0xF8, 0xBD, 0x30, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x4A, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x92, 0x8C, 0xBB, 0xD6, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xBE, 0xF7, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x21, 0xED, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0xA2, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x62, 0xA1, 0xDC, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x41, 0xCC, 0xE1, 0x9A, 0xC1, 0xDC, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x21, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x93, 0x40, 0xF5, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0xE1, 0xE4, 0x41, 0x39, 0x00, 0x00, 0x22, 0xC4, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0xE1, 0xEC, - 0xE1, 0x8A, 0x20, 0xF5, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x61, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x49, 0x01, 0xC4, 0x20, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x81, 0xFD, 0xA1, 0xFD, 0x61, 0xF5, 0xE1, 0xBB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBA, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xF7, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x29, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x55, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xD7, 0xB5, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x76, 0xAD, 0x9E, 0xEF, 0xDF, 0xFF, 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, 0x5D, 0xEF, 0x71, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x46, 0x21, 0x7E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF8, 0xBD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, - 0xFC, 0xDE, 0x55, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x4A, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0xD6, 0xFC, 0xDE, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xF7, 0xB6, 0xB5, 0x00, 0x00, 0x01, 0xED, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0xA2, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x41, 0x61, 0xD4, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x41, 0xD4, 0x00, 0x00, 0xA1, 0xB3, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, - 0x81, 0xDC, 0x61, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xC4, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x41, 0xCC, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xC3, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x01, 0xFD, 0xA1, 0xE4, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0xC1, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x61, 0x49, 0x01, 0xC4, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x61, 0xFD, 0x61, 0xFD, 0x41, 0xFD, 0xC1, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB6, 0xB5, - 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDB, 0xD6, 0x31, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x5B, 0x9E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x3D, 0xE7, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xB5, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xA5, 0x7D, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0xDE, 0xAB, 0x52, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, - 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xBD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x9A, 0xD6, 0x2A, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0x2D, 0x63, 0xE0, 0xEC, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x20, 0xFD, 0x81, 0x82, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x72, 0x61, 0xDC, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0x01, 0xCC, 0x00, 0x00, 0x01, 0x62, 0xA0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0xE0, 0xF4, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xDC, 0x20, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x22, 0x9B, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBB, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x81, 0xB3, 0x00, 0x00, 0x00, 0x00, - 0x82, 0xAB, 0x00, 0xF5, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0xE0, 0xF4, 0x81, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x7C, 0x7D, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xEF, 0x8E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xCE, 0xBF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x7A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xBD, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xD6, - 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0xBA, 0xD6, 0xFB, 0xDE, 0x1C, 0xDF, 0x9A, 0xD6, 0xDB, 0xDE, 0x9E, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0xD3, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0x7E, 0xEF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x7D, 0xEF, 0x7D, 0xEF, 0xDF, 0xF7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xF7, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, - 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x96, 0xAD, 0xA0, 0xEC, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x59, 0xA0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0xA1, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x41, 0xD4, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0x81, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x82, 0xE0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, - 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x81, 0xE4, 0x62, 0x82, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xBB, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC1, 0xF4, 0xC1, 0xEC, 0xA1, 0xEC, 0xA0, 0xF4, 0xA0, 0xF4, 0xA1, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x81, 0xE4, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0xE0, 0xFC, 0x21, 0xD4, 0x62, 0xAB, 0x02, 0x9B, 0xE2, 0x92, 0xA1, 0xBB, 0x81, 0xDC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x01, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xD6, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xBD, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x3C, 0xE7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0x14, 0xA5, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x88, 0x29, 0x8C, 0x52, 0xAF, 0x73, 0x7A, 0xCE, 0x3C, 0xE7, 0xDF, 0xF7, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x21, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, - 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xF7, 0x39, 0xC6, 0xB3, 0x94, 0x8A, 0x52, 0x6A, 0x4A, 0x72, 0x8C, 0xF8, 0xBD, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFB, 0xDE, 0xEC, 0x5A, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xDB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xBE, 0xF7, 0xBB, 0xD6, 0xD7, 0xB5, 0xB7, 0xB5, 0x18, 0xBE, 0x38, 0xC6, 0x1C, 0xDF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x59, 0xC6, 0xA1, 0xEC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC3, 0xC0, 0xFC, 0xC0, 0xFC, - 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x01, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x62, 0xA3, 0xC0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE0, 0xD3, 0x81, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xAB, 0x00, 0xFD, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x21, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xBB, 0xA0, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE1, 0xD3, 0x63, 0xB3, 0x83, 0x72, 0x62, 0x39, 0x61, 0x41, 0x81, 0x82, 0x20, 0xA3, 0xE1, 0x51, 0x00, 0x00, 0xC1, 0x9A, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x61, 0xB3, 0x22, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x31, 0xA1, 0xC3, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0x80, 0xF4, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xAD, 0xBE, 0xEF, 0xBE, 0xF7, 0xBE, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBA, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x52, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0x7D, 0xEF, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xBD, 0xDF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x08, 0x9E, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFB, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0xD7, 0xB5, 0x0C, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0xBA, 0xD6, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xF7, 0x96, 0xB5, 0x49, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA5, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x92, 0x8C, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xBB, 0xD6, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xEF, 0x76, 0xAD, 0x4E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0xDB, 0xD6, 0xDF, 0xF7, - 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9A, 0xCE, 0x81, 0xEC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x49, 0x60, 0xBB, 0x60, 0xF4, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x20, 0xEC, 0x01, 0x7A, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x51, 0x20, 0xE4, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xF4, 0x20, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xE1, 0xCB, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xE1, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xBB, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, - 0x40, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0xA0, 0xCB, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xC3, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x00, 0xE4, 0x21, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x69, 0x21, 0xE4, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x41, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x84, 0x7E, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x5D, 0xE7, 0xCC, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xB5, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xD7, 0xB5, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDB, 0xD6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBF, 0xF7, 0xBA, 0xD6, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xF7, 0xBF, 0xF7, 0xFC, 0xDE, 0x8F, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xCE, 0xDF, 0xF7, - 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xBB, 0xD6, 0xBF, 0xF7, 0xDF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x3D, 0xE7, 0x41, 0xEC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x62, 0xBB, 0xC1, 0xC3, 0xA1, 0xC3, 0xA0, 0xC3, 0x81, 0xC3, 0x80, 0xC3, 0x80, 0xC3, 0x61, 0xCB, 0xE0, 0xE3, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x40, 0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBB, 0x60, 0xFC, 0x60, 0xFC, - 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x7A, 0x20, 0xE4, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x00, 0xE4, 0xC1, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBB, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0xC0, 0xE3, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xDB, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC3, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x61, 0xFC, 0x81, 0xCB, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xCE, 0x9E, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0xBF, 0xF7, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xEF, 0x9A, 0xCE, 0x35, 0xA5, 0x0C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x21, 0x5D, 0xE7, 0xBE, 0xEF, - 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBA, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xC6, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xB5, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x4A, 0xBB, 0xCE, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xF7, 0x7E, 0xEF, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x4A, 0x3C, 0xDF, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xEF, 0x3D, 0xE7, 0x01, 0xEC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, - 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xC0, 0xF3, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x82, 0x20, 0xF4, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0xA0, 0xD3, 0x81, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x92, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xFC, 0x61, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xBB, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x40, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xC1, 0xE3, 0x20, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x01, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB3, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0xA1, 0xDB, 0x82, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x32, 0xFC, 0xD6, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x5D, 0xDF, 0xF0, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xAD, 0xBE, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x9A, 0xCE, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x9E, 0xEF, 0x5D, 0xE7, 0xBB, 0xD6, 0x18, 0xBE, 0xB3, 0x94, 0x33, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x21, 0x5D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBA, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x87, 0x21, 0xDB, 0xD6, 0x7E, 0xEF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xEF, 0x14, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x9D, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x1C, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x42, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, - 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0x3D, 0xE7, 0xAB, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xBF, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x1C, 0xDF, 0xC1, 0xEB, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC1, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x10, 0x81, 0xD3, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xF4, 0xC1, 0x79, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x28, 0x81, 0xCB, 0x60, 0xFC, 0x60, 0xFC, - 0x60, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x40, 0xF4, 0x61, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xBA, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0x60, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xEB, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x81, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xA2, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x81, 0xDB, 0xC2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x73, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x1C, 0xD7, 0x0A, 0x2A, - 0x00, 0x00, 0x00, 0x00, 0x93, 0x8C, 0x5E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9B, 0xCE, 0xAB, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xA5, 0x9E, 0xEF, 0x9E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x84, 0x7D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0x9E, 0xEF, 0xDB, 0xD6, 0x59, 0xC6, 0x72, 0x8C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x64, 0x5E, 0xE7, 0x9E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xBB, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x21, 0x9A, 0xCE, 0x5D, 0xE7, 0x5E, 0xE7, 0x7E, 0xE7, - 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x76, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x42, 0x5D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x1C, 0xDF, 0xC5, 0x08, 0x00, 0x00, 0x4A, 0x42, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x3D, 0xDF, 0x4A, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xD6, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x1C, 0xDF, 0xA1, 0xE3, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, - 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xF3, 0xA1, 0xBA, 0xE1, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xBA, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x01, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x42, 0x51, 0xC1, 0xDB, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0xA1, 0xDB, 0x21, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x41, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x39, 0xA1, 0xF3, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x92, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xA1, 0xE3, 0xA2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x5B, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB5, 0x7E, 0xE7, 0x7E, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xA5, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x42, 0xD7, 0xB5, 0x5D, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, - 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x5D, 0xE7, 0x7A, 0xCE, 0x31, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0x4B, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x42, 0x7A, 0xC6, 0x5D, 0xDF, 0x5D, 0xDF, 0x5D, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x3D, 0xDF, 0x39, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x21, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x3D, 0xDF, 0xA8, 0x29, 0x00, 0x00, 0x4A, 0x42, 0x9A, 0xCE, 0x9E, 0xE7, 0x9E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x1D, 0xDF, 0x6B, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xDB, 0xD6, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0xFC, 0xD6, 0x81, 0xEB, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x01, 0xE3, 0x61, 0xB2, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x69, 0xC0, 0xEB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x41, 0xD3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x00, 0xF4, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x01, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0x80, 0xFB, 0x80, 0xFB, - 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x00, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0xEB, 0xA0, 0xFB, 0xA0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xE1, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x92, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x81, 0xE3, 0xA2, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB6, 0x3E, 0xDF, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0xB7, 0xAD, 0x00, 0x00, 0x29, 0x3A, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x3D, 0xDF, 0x72, 0x84, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xA5, 0x7E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7E, 0xDF, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x42, 0x15, 0x9D, 0xDB, 0xCE, 0x5E, 0xE7, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xFC, 0xD6, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x19, 0xFC, 0xD6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7A, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x42, 0x7A, 0xC6, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xD7, 0x18, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x21, 0x1D, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x1D, 0xD7, 0x09, 0x32, 0x00, 0x00, 0x8B, 0x4A, 0x7A, 0xC6, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x1D, 0xD7, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xCE, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xFC, 0xD6, 0x61, 0xEB, 0xA0, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0xE0, 0xF2, 0xA0, 0xDA, 0xA1, 0xD2, 0x22, 0xAA, 0xA2, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x21, 0xD3, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0x80, 0xEB, 0x01, 0x51, 0x00, 0x00, 0xE2, 0xBA, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xF3, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0xE0, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xEB, 0x80, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x92, 0x80, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, - 0x21, 0xDB, 0x42, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x74, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x39, 0xB6, 0x46, 0x19, 0xD0, 0x6B, 0xFD, 0xCE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x5E, 0xD7, 0x9B, 0xC6, 0xEB, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xA5, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xD8, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x63, 0x76, 0xA5, 0x7A, 0xC6, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xDC, 0xCE, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x26, 0x19, - 0xDC, 0xCE, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x5D, 0xDF, 0x5E, 0xDF, 0x5A, 0xBE, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x31, 0x39, 0xBE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x1D, 0xD7, 0x19, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x29, 0x1D, 0xD7, 0x5E, 0xDF, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0xFC, 0xCE, 0x87, 0x21, 0x00, 0x00, 0x8B, 0x4A, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x1C, 0xD7, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xDB, 0xCE, 0x41, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, - 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0xA2, 0x89, 0x82, 0x79, 0xA2, 0x89, 0xC1, 0x99, 0xC1, 0x99, 0xA1, 0x91, 0xA1, 0x91, 0xA2, 0x91, 0x42, 0x69, 0x03, 0x59, 0xE2, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAA, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x41, 0xB2, 0x00, 0x00, 0x21, 0xD3, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0x40, 0xE3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xBA, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xC0, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0xC1, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xA2, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0xE1, 0xDA, 0xA2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x29, 0x7B, 0xBE, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xBC, 0xC6, 0xD0, 0x6B, 0x56, 0x9D, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xD7, 0x3D, 0xD7, 0xB7, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x9D, 0x5E, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0xD8, 0xAD, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x4A, 0xAF, 0x63, 0xB7, 0xA5, 0x7A, 0xBE, 0xBB, 0xCE, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xDF, 0x56, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x26, 0x19, 0xBC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x3D, 0xD7, 0x39, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xD7, 0x1D, 0xD7, 0x15, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x8C, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0xBB, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x4A, 0x5A, 0xBE, - 0x5E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x1C, 0xD7, 0x8C, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xC6, 0x3E, 0xD7, 0x3E, 0xD7, 0x3D, 0xD7, 0x3D, 0xDF, 0x5D, 0xDF, 0xBB, 0xCE, 0x21, 0xEB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x82, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x71, 0x20, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0xA0, 0xCA, 0x63, 0x51, 0x40, 0xF3, 0x60, 0xFB, - 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x60, 0xFB, 0xA1, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xBA, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0x80, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xD2, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAA, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xA1, 0xDA, 0x82, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xA5, 0xFD, 0xCE, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, - 0xFD, 0xC6, 0xFD, 0xC6, 0x15, 0x95, 0xF9, 0xAD, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xDC, 0xC6, 0x11, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x9D, 0x3E, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x7C, 0xB4, 0x8C, 0x19, 0xB6, 0xFC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x39, 0xB6, 0x09, 0x3A, 0x00, 0x00, 0x05, 0x19, 0x9C, 0xC6, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0x19, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB6, 0xFD, 0xCE, - 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0xB7, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x94, 0x1D, 0xD7, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x3A, 0x3A, 0xBE, 0x3E, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0xFC, 0xCE, 0xED, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7B, 0xBE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0xBB, 0xC6, 0x01, 0xE3, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xFA, 0x62, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xD2, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xC0, 0xE2, 0x41, 0x9A, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xF3, 0x81, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0x40, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xCA, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x80, 0xDA, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x28, 0x81, 0xCA, 0x00, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x42, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x74, 0xBC, 0xBE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xB8, 0x9D, 0x1A, 0xAE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDC, 0xC6, 0x19, 0xAE, 0xC8, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x95, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x97, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x8C, 0xDC, 0xC6, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0x3A, 0xB6, 0xF1, 0x73, 0x00, 0x00, 0x26, 0x19, 0x7B, 0xBE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x9D, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xA5, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3A, 0x19, 0xB6, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xFC, 0xCE, 0xED, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xBE, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xBB, 0xC6, 0xC1, 0xEA, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x42, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xA1, 0xC0, 0xF2, 0xE0, 0xFA, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xF2, 0x61, 0xBA, 0x00, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0x60, 0xDA, 0x81, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xBA, - 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB9, 0xA0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x80, 0xF2, 0x61, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0xC0, 0xF2, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA2, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x19, 0x1A, 0xAE, 0xBD, 0xBE, 0xBD, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x7B, 0xB6, 0x9C, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x15, 0x95, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x8C, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0x97, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x84, 0xF5, 0x84, 0xC8, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x5B, 0xB6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0x3A, 0xB6, 0x11, 0x74, 0x00, 0x00, 0x26, 0x19, 0x7B, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0x6B, 0xBC, 0xBE, 0xBD, 0xC6, 0xDC, 0xC6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x9C, 0xBE, 0x12, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x6F, 0x5B, 0x5A, 0xB6, 0xDC, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0x32, 0x74, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x31, 0x19, 0xAE, 0xFD, 0xCE, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xCE, 0x1D, 0xCF, 0xDC, 0xC6, 0x8C, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xB6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0x9B, 0xBE, 0x81, 0xEA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x21, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x49, 0x41, 0xDA, 0xC0, 0xFA, 0xC0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xF2, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x00, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xB9, 0x60, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0xC0, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x58, 0x40, 0xEA, 0x80, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x20, 0xDA, 0x61, 0x99, 0xE1, 0x58, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x48, 0x81, 0x89, 0x60, 0xDA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, - 0x60, 0xFA, 0x00, 0xDA, 0x01, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x9D, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x7B, 0xB6, 0xF1, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x84, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xC6, 0xDD, 0xBE, 0x77, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x63, 0x1A, 0xAE, 0x9C, 0xB6, 0x98, 0x9D, 0x93, 0x7C, 0x0E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x73, 0x7C, 0x9C, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xDD, 0xBE, 0x97, 0x9D, 0x09, 0x32, - 0x00, 0x00, 0x05, 0x19, 0x3B, 0xAE, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0xB8, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x3A, 0xF9, 0xA5, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x1A, 0xAE, 0x73, 0x7C, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x31, 0xF1, 0x6B, 0xD8, 0xA5, 0x9C, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBD, 0xBE, 0x3A, 0xAE, 0x09, 0x32, 0x00, 0x00, 0x00, 0x00, 0x09, 0x32, 0xF9, 0xAD, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xBC, 0xBE, 0x4B, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0xAE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xC6, 0xDD, 0xBE, 0x5B, 0xB6, 0x41, 0xEA, 0x60, 0xFA, - 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB1, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x41, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB9, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xA0, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xB9, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x40, 0xF2, 0x20, 0xDA, 0x41, 0xDA, 0x41, 0xD2, 0x41, 0xE2, 0x80, 0xF2, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x20, 0xFA, 0x80, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x84, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0xD9, 0xA5, 0xC8, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x84, 0xBC, 0xBE, 0x9C, 0xB6, 0x9C, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, - 0xBD, 0xBE, 0x56, 0x95, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x4B, 0x98, 0x9D, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7B, 0xB6, 0xD9, 0xA5, 0x77, 0x95, 0x57, 0x95, 0x52, 0x74, 0x52, 0x74, 0xF5, 0x8C, 0xB8, 0xA5, 0x5B, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x36, 0x95, 0x00, 0x00, 0x00, 0x00, 0x05, 0x11, 0x3A, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x98, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x84, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xB6, 0xF9, 0xA5, 0xB8, 0xA5, 0xB8, 0xA5, 0xD9, 0xA5, 0x7B, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xBE, 0x9C, 0xB6, 0x16, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE9, 0x31, 0xD9, 0xA5, 0xBD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0x9B, 0xB6, 0x2A, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF9, 0xA5, 0xBC, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0x1A, 0xAE, 0x21, 0xE2, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x79, 0x40, 0xEA, 0x60, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, - 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x20, 0xE2, 0xC1, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xB9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0x80, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x69, 0x01, 0xE2, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0xC0, 0xD9, 0xA1, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x11, 0xFA, 0x9D, - 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x37, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x7C, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x36, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x15, 0x8D, 0x7B, 0xB6, 0x7B, 0xB6, 0x7B, 0xB6, 0x7B, 0xAE, 0x5B, 0xAE, 0x7B, 0xAE, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xBE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x1A, 0xA6, 0x90, 0x63, 0x00, 0x00, 0x00, 0x00, 0x26, 0x11, 0x1A, 0xA6, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x78, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x09, 0x98, 0x9D, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0xD9, 0x9D, 0x8B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x29, 0xB9, 0x9D, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0xBC, 0xB6, 0xBC, 0xBE, 0x5B, 0xAE, 0x2A, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xF9, 0xA5, 0x9C, 0xB6, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0xD9, 0x9D, 0xE1, 0xE1, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x00, 0xFA, 0xE1, 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, 0x22, 0x00, 0xC1, 0xD1, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0xC0, 0xD1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xB1, 0xA0, 0xF9, 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0x60, 0xD1, 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, 0x91, 0xE1, 0xE1, 0x00, 0xFA, 0x20, 0xFA, 0x20, 0xFA, - 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xA0, 0xE1, 0xE1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x8D, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x32, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x7C, 0x7C, 0xAE, 0x5B, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0xF5, 0x84, 0x00, 0x00, 0x00, 0x00, 0x57, 0x95, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, - 0x5B, 0xAE, 0x7B, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x1A, 0xA6, 0x94, 0x7C, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x22, 0xFA, 0xA5, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x77, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x4B, 0x98, 0x95, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x98, 0x95, 0xB1, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x29, 0x98, 0x9D, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x3B, 0xAE, 0x2A, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xD9, 0x9D, 0x7C, 0xAE, 0x7C, 0xAE, 0x5C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0xB9, 0x9D, 0xA0, 0xE1, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xE2, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xA1, 0x00, 0xFA, 0x00, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x21, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x41, 0xB9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xD1, 0x00, 0x00, 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, 0x81, 0xC1, 0xD9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA1, 0xD9, 0xE1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x6C, 0xFA, 0x9D, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0xFA, 0x9D, 0xFA, 0x9D, 0xB9, 0x95, 0x4B, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x7C, 0x5B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x5B, 0xA6, 0x5B, 0xAE, 0xD5, 0x84, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x32, 0xB5, 0x7C, 0xB9, 0x9D, 0x3B, 0xA6, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x3B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0xD9, 0x9D, 0x74, 0x74, 0x4B, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x44, 0xFA, 0x9D, 0x1B, 0xA6, 0x1B, 0xA6, 0x1B, 0xA6, 0x1B, 0x9E, 0x1B, 0xA6, 0x57, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0x4A, 0x37, 0x8D, 0x1B, 0xA6, 0x3B, 0xA6, 0x3B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, - 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x3B, 0xAE, 0x3B, 0xA6, 0x1B, 0xA6, 0x37, 0x8D, 0xD1, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x29, 0x98, 0x95, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x1A, 0xA6, 0xEA, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB9, 0x95, 0x5B, 0xA6, 0x5B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0xB9, 0x9D, 0x60, 0xE1, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xC2, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x38, 0x81, 0xC9, 0xE0, 0xF9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xA0, 0xE1, 0xE2, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xB1, 0x60, 0xF1, 0x40, 0xF1, 0x40, 0xF1, 0x20, 0xF1, 0x20, 0xF9, 0x40, 0xF9, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x50, 0x61, 0xB9, 0x81, 0xD1, 0xA0, 0xF1, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF1, 0x61, 0xD9, 0x41, 0xB1, - 0xA2, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x32, 0x58, 0x85, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xBA, 0x95, 0xB9, 0x95, 0xD5, 0x7C, 0xE9, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x74, 0x3B, 0xA6, 0x1B, 0x9E, 0xFB, 0x9D, 0xFB, 0x9D, 0x1B, 0x9E, 0x1B, 0xA6, 0xD5, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x4B, 0xD5, 0x7C, 0x98, 0x95, 0x1B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x1B, 0xA6, 0xB9, 0x95, 0xF6, 0x84, 0xB0, 0x5B, 0x06, 0x09, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x3C, 0xD9, 0x95, 0xDA, 0x9D, 0xFA, 0x9D, 0xDA, 0x9D, 0xDA, 0x9D, 0xFA, 0x9D, 0x37, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x42, 0x12, 0x6C, 0x57, 0x8D, 0xFA, 0xA5, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x1B, 0xA6, 0xFA, 0x9D, 0x57, 0x8D, 0x53, 0x74, 0xCD, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x29, 0x78, 0x95, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0xF9, 0x9D, 0xA8, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x98, 0x95, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0xA6, 0x1B, 0xA6, 0xB8, 0x95, - 0xE1, 0xB0, 0x21, 0xC1, 0x41, 0xB9, 0x41, 0xC1, 0x41, 0xC9, 0x41, 0xD9, 0x20, 0xD9, 0xC7, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x99, 0xC0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF9, 0x40, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x80, 0x01, 0xB9, 0x21, 0xC1, 0x21, 0xC1, 0x01, 0xC1, 0x01, 0xC1, 0x01, 0xD1, 0xE2, 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, 0x62, 0x30, 0xE1, 0x88, 0x41, 0xC1, 0x60, 0xC9, 0x80, 0xD9, 0x80, 0xE1, 0x80, 0xE1, 0x80, 0xD9, 0x61, 0xC9, 0x41, 0xC1, 0xE1, 0x90, 0xC6, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0xD1, 0x5B, 0x75, 0x6C, 0x33, 0x6C, 0x13, 0x64, 0x12, 0x64, 0x13, 0x64, 0x33, 0x6C, 0xF2, 0x63, 0xD1, 0x63, 0x6F, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x5B, 0xD5, 0x7C, 0x94, 0x74, 0x94, 0x74, - 0x94, 0x74, 0x94, 0x7C, 0x94, 0x7C, 0x6F, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x21, 0x12, 0x6C, 0x16, 0x85, 0x16, 0x8D, 0x77, 0x95, 0x98, 0x95, 0x98, 0x95, 0x78, 0x95, 0x16, 0x8D, 0x37, 0x8D, 0x53, 0x74, 0xC9, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x6C, 0x53, 0x6C, 0x33, 0x6C, 0x32, 0x6C, 0x12, 0x6C, 0x12, 0x6C, 0x90, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x5B, 0xB5, 0x7C, 0xD9, 0x9D, 0x57, 0x95, 0x98, 0x9D, 0x98, 0x9D, 0x57, 0x95, 0x98, 0x95, 0xB4, 0x7C, 0x0E, 0x4B, 0x06, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x67, 0x21, 0x11, 0x6C, 0xB5, 0x7C, 0xB5, 0x7C, 0xF6, 0x84, 0x16, 0x85, 0x16, 0x8D, 0x94, 0x7C, 0x26, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0xF2, 0x63, 0x74, 0x74, 0x94, 0x7C, 0xB5, 0x7C, 0xB5, 0x84, 0xD5, 0x84, 0x94, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x81, 0xA0, 0xE1, 0xC0, 0xF9, 0xA0, 0xF9, - 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF1, 0xC1, 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, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xA8, 0xE0, 0xC0, 0xE0, 0xB8, 0xE1, 0xB0, 0x21, 0xB1, 0x61, 0xC9, 0xA0, 0xE9, 0xA0, 0xF9, 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x01, 0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC1, 0x40, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xD9, 0xA1, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xF9, 0xE0, 0xE0, 0xC1, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0xE0, 0xD8, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x00, 0xF9, 0x00, 0xD1, 0xA1, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x50, 0xC0, 0xD8, 0x00, 0xF9, 0x20, 0xF9, 0x00, 0xF9, 0x00, 0xF9, 0x00, 0xF9, 0x20, 0xF9, 0x20, 0xF1, - 0x00, 0xF1, 0xE0, 0xD8, 0xE1, 0xB8, 0xA2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x60, 0xA1, 0xB0, 0xC0, 0xD0, 0xC1, 0xD0, 0xC1, 0xD0, 0xC1, 0xD0, 0xC1, 0xC8, 0xE3, 0xD0, 0xE1, 0xB8, 0xA2, 0x90, 0x82, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE1,0x18,0xE2,0x10,0x02,0x19,0x02,0x11,0xC1,0x00,0xA1,0x00,0xC1,0x08,0x02,0x19,0x22,0x21,0x22,0x19,0x22,0x21,0x22,0x21,0x42,0x21,0x42,0x21,0x02,0x21,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,0xE6,0x08,0xE5,0x10,0xA4,0x00,0x23,0x00,0x23,0x00,0x84,0x00,0xC5,0x10,0x46,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0x10,0x26,0x19,0x46,0x21,0x46,0x21,0x67,0x21,0xA7,0x29,0xA8,0x29,0xE5,0x10,0x92,0x94,0x9A,0xD6,0xFB,0xDE,0xFB,0xDE, + 0xFB,0xDE,0xFB,0xDE,0xDB,0xDE,0x14,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA7,0x31,0x79,0xCE,0x1C,0xE7,0x3C,0xE7,0x5D,0xE7,0x5D,0xEF,0x3D,0xE7,0x39,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xCD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x41,0xDD,0x41,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x62,0xDD,0x61,0xDD,0x02,0xCD,0xA3,0xBC,0xA2,0x93,0xA1,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xBE,0xDB,0xDE,0xDB,0xDE,0xBB,0xD6,0xBB,0xD6,0xDB,0xDE,0xDB,0xDE,0x39,0xC6, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x6B,0x7A,0xCE,0xDB,0xDE,0xDB,0xDE,0xDB,0xDE,0xDB,0xDE,0xFB,0xDE,0xBA,0xD6,0xCC,0x52,0x38,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x73,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xED,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE, + 0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x21,0xFE,0x41,0xFE,0x21,0xF6,0xA1,0xE5,0x61,0xB4,0x21,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xEF,0xF0,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xAD,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xDE,0x93,0x8C,0x1C,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x7C,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5D,0xEF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x21,0xFE,0x21,0xFE,0x21,0xFE,0x41,0xFE,0x81,0xE5,0x21,0xAC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x8C,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBA,0xD6,0x00,0x00,0xFB,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x6B,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x20,0xFE,0x20,0xFE,0xE1,0xF5,0x21,0xBC, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x6B,0x1C,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAF,0x73,0x3D,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xD3,0x9C,0x00,0x00,0xB7,0xAD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x4A,0x5D,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0x7A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x81,0xED,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0x61,0xED,0x61,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0x0C,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0xEC,0x5A,0x00,0x00,0x00,0x00,0xB3,0x94, + 0x39,0xC6,0xD3,0x94,0x76,0xAD,0x7A,0xCE,0xF4,0x9C,0x6A,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x73,0x8C,0x7A,0xCE,0xDB,0xD6,0x7A,0xC6,0x5A,0xC6,0x76,0xAD,0x29,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0x21,0xDD,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x01,0xE5,0x21,0xE5,0xA0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0x61,0xCC,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7B,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x00,0xF8,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x59,0xCE,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xED,0xA0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xA1,0xFD,0xC2,0x82,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0x41,0x81,0xA3,0xE1,0xD4,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x21,0xED,0x62,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x31,0x41,0x6A,0xA2,0xB3,0x82,0xAB,0x61,0x72,0x01,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x41,0xC3,0x7A,0x22,0x93,0x82,0xA3,0x81,0xA3,0x61,0x9B,0x41,0x72,0x81,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x3A,0xFC,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0xC6,0xE4,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x6B,0xDB,0xDE,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x14,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x42,0xCF,0x73,0xF3,0x9C,0xF4,0x9C,0x14,0xA5,0xD3,0x9C,0xB3,0x94,0x6A,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x08,0x88,0x31,0x6E,0x6B,0xB3,0x94,0xF4,0x9C,0xF4,0x9C,0xB3,0x94,0x31,0x84,0x4A,0x4A,0xAC,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x00,0x8B,0x01,0x6B,0x00,0x8B,0x01,0x2B,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x52,0xB3,0x94,0x14,0x9D,0x14,0xA5,0xB3,0x94,0x11,0x7C,0xC8,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xED,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0xC1,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x62,0xE1,0xD4,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x82,0xA3,0x22,0xAC,0xA0,0xD4,0xA0,0xD4,0xA0,0xD4,0xA1,0xCC,0xA1,0xCC,0xA1,0xCC,0x61,0xC4,0x03,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xC4,0x81,0xD4,0x81,0xCC,0x60,0xCC, + 0x60,0xCC,0x80,0xCC,0xA0,0xCC,0x22,0xB4,0x00,0x00,0x03,0xAC,0xA1,0xCC,0xA0,0xCC,0xA1,0xCC,0xA1,0xD4,0x80,0xD4,0xE1,0xB3,0x00,0x00,0x00,0x00,0xC2,0x72,0x01,0xB4,0x01,0xE5,0x61,0xF5,0xA1,0xFD,0x81,0xFD,0x60,0xF5,0xA1,0xD4,0x62,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6A,0xC1,0xA3,0xE1,0xD4,0x41,0xED,0xA1,0xF5,0xC1,0xFD,0xC1,0xFD,0xC1,0xFD,0xC1,0xFD,0xA1,0xF5,0x61,0xED,0xC1,0xD4,0xA1,0xA3,0x21,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xDE,0xEF,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x31,0x84,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x2D,0x63,0x00,0x00,0x00,0x00,0x76,0xAD,0x9A,0xCE,0x9A,0xD6,0x9A,0xD6,0xBA,0xD6,0xBA,0xD6,0x9A,0xD6,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0x6B,0x96,0xB5,0xBA,0xD6,0x7D,0xEF,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0xDB,0xDE,0x59,0xCE,0xB3,0x94,0x0D,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x7C,0x39,0xC6,0x79,0xCE,0x79,0xCE,0x79,0xCE,0x79,0xCE,0x79,0xCE,0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7B,0x55,0xA5,0x9A,0xD6, + 0x3D,0xE7,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBF,0xF7,0x7D,0xEF,0xBA,0xD6,0x18,0xC6,0x52,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0x4A,0xB7,0xB5,0x9A,0xCE,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x7A,0xCE,0x14,0xA5,0x00,0x00,0xF0,0x7B,0x76,0xAD,0xDB,0xDE,0x7E,0xEF,0xDF,0xF7,0xDF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBE,0xF7,0x5D,0xE7,0xBB,0xD6,0x35,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xED,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0xA1,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x7A,0x61,0xF5,0x80,0xFD,0x80,0xFD,0x80,0xFD, + 0x80,0xFD,0x80,0xFD,0x80,0xFD,0x42,0xCC,0xE1,0x8A,0x80,0xFD,0x80,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x60,0xF5,0x42,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xDC,0x80,0xFD,0x80,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x80,0xFD,0x81,0xA3,0x00,0x00,0x62,0xC4,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x00,0xED,0x81,0x08,0xC2,0xAB,0x01,0xE5,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0xC1,0xE4,0x81,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x92,0xE1,0xB3,0x01,0xE5,0x80,0xFD,0x80,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA1,0xFD,0xA1,0xFD,0xA1,0xFD,0xA1,0xFD, + 0xC1,0xFD,0xC1,0xFD,0xA1,0xFD,0x01,0xDD,0x81,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x84,0x7E,0xEF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x71,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xC6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x79,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xBD,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x35,0xA5,0xFC,0xDE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0x9E,0xF7,0xDB,0xDE,0x51,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0xEA,0x31,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDB,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xAD,0x3C,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xEF,0xF8,0xBD,0x30,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x4A,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x92,0x8C,0xBB,0xD6,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xBE,0xF7,0xF8,0xBD,0x00,0x00,0x00,0x00,0x21,0xED,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x60,0xFD,0xA2,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x62,0xA1,0xDC,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x41,0xCC,0xE1,0x9A,0xC1,0xDC,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x21,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x93,0x40,0xF5,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x60,0xFD,0xE1,0xE4,0x41,0x39,0x00,0x00,0x22,0xC4,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x40,0xFD,0xE1,0xEC, + 0xE1,0x8A,0x20,0xF5,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x61,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x49,0x01,0xC4,0x20,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x81,0xFD,0xA1,0xFD,0x61,0xF5,0xE1,0xBB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBA,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xF7,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x29,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x55,0xAD,0x00,0x00,0x00,0x00,0x00,0x00, + 0xD7,0xB5,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x00,0x76,0xAD,0x9E,0xEF,0xDF,0xFF,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,0x5D,0xEF,0x71,0x8C,0x00,0x00,0x00,0x00,0x46,0x21,0x7E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xF8,0xBD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF, + 0xFC,0xDE,0x55,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x4A,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0xD6,0xFC,0xDE,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE,0xF7,0xB6,0xB5,0x00,0x00,0x01,0xED,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0xA2,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x41,0x61,0xD4,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x41,0xD4,0x00,0x00,0xA1,0xB3,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD, + 0x81,0xDC,0x61,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xC4,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x41,0xCC,0x00,0x00,0x00,0x00,0xE1,0xC3,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x01,0xFD,0xA1,0xE4,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0xC1,0xC3,0x00,0x00,0x00,0x00,0x61,0x49,0x01,0xC4,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x61,0xFD,0x61,0xFD,0x41,0xFD,0xC1,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB6,0xB5, + 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDB,0xD6,0x31,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x5B,0x9E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x3D,0xE7,0x2D,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xB5,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xA5,0x7D,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0xDE,0xAB,0x52,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7, + 0xDF,0xFF,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xBD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x9A,0xD6,0x2A,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x52,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0x2D,0x63,0xE0,0xEC,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x20,0xFD,0x81,0x82, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x72,0x61,0xDC,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x20,0xFD,0x01,0xCC,0x00,0x00,0x01,0x62,0xA0,0xEC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0xE0,0xF4,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xDC,0x20,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x22,0x9B,0x00,0x00,0x00,0x00,0xC1,0xBB,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x81,0xB3,0x00,0x00,0x00,0x00, + 0x82,0xAB,0x00,0xF5,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0xE0,0xF4,0x81,0x8A,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x7C,0x7D,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9E,0xEF,0x8E,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7A,0xCE,0xBF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x7A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF7,0xBD,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xD6, + 0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0xBA,0xD6,0xFB,0xDE,0x1C,0xDF,0x9A,0xD6,0xDB,0xDE,0x9E,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0xD3,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0x7E,0xEF,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x7D,0xEF,0x7D,0xEF,0xDF,0xF7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE,0xF7,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0xAB,0x52,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF, + 0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x96,0xAD,0xA0,0xEC,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x00,0xFD,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x59,0xA0,0xEC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0xA1,0xC3,0x00,0x00,0x00,0x00,0x41,0xD4,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0x81,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC2,0x82,0xE0,0xEC,0x00,0xFD,0x00,0xFD, + 0x00,0xFD,0x00,0xFD,0x00,0xFD,0x81,0xE4,0x62,0x82,0x00,0x00,0x00,0x00,0xA1,0xBB,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0xA0,0xFC,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC1,0xF4,0xC1,0xEC,0xA1,0xEC,0xA0,0xF4,0xA0,0xF4,0xA1,0x8A,0x00,0x00,0x00,0x00,0x81,0xE4,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0xE0,0xFC,0x21,0xD4,0x62,0xAB,0x02,0x9B,0xE2,0x92,0xA1,0xBB,0x81,0xDC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x01,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xD6,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0xDF,0xF7,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xDB,0xD6,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xBD,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x08,0x00,0x3C,0xE7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0x14,0xA5,0x2D,0x63,0x00,0x00,0x00,0x00,0x88,0x29,0x8C,0x52,0xAF,0x73,0x7A,0xCE,0x3C,0xE7,0xDF,0xF7,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x21,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xD6,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7, + 0xDF,0xF7,0xDF,0xF7,0x9E,0xF7,0x39,0xC6,0xB3,0x94,0x8A,0x52,0x6A,0x4A,0x72,0x8C,0xF8,0xBD,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFB,0xDE,0xEC,0x5A,0x00,0x00,0x00,0x00,0xAB,0x52,0xDB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xBE,0xF7,0xBB,0xD6,0xD7,0xB5,0xB7,0xB5,0x18,0xBE,0x38,0xC6,0x1C,0xDF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x59,0xC6,0xA1,0xEC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xC3,0xC0,0xFC,0xC0,0xFC, + 0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x01,0xA3,0x00,0x00,0x00,0x00,0x62,0xA3,0xC0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xE0,0xD3,0x81,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xAB,0x00,0xFD,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x21,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xBB,0xA0,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xE1,0xD3,0x63,0xB3,0x83,0x72,0x62,0x39,0x61,0x41,0x81,0x82,0x20,0xA3,0xE1,0x51,0x00,0x00,0xC1,0x9A,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x61,0xB3,0x22,0x31,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x31,0xA1,0xC3,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0x80,0xF4,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xAD,0xBE,0xEF,0xBE,0xF7,0xBE,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBA,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0x52,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0x7D,0xEF,0x6E,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xBD,0xDF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0xC5,0x08,0x9E,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFB,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x8E,0x6B,0xD7,0xB5,0x0C,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0xBA,0xD6,0x0A,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBE,0xF7,0x96,0xB5,0x49,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xA5,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x92,0x8C,0x00,0x00,0x00,0x00,0xAB,0x52,0xBB,0xD6,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9E,0xEF,0x76,0xAD,0x4E,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x6B,0xDB,0xD6,0xDF,0xF7, + 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9A,0xCE,0x81,0xEC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x49,0x60,0xBB,0x60,0xF4,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xFC,0x60,0xFC,0x20,0xEC,0x01,0x7A,0x00,0x00,0x00,0x00,0xA1,0x51,0x20,0xE4,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xF4,0x20,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xE1,0xCB,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0xE1,0xA2,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xBB,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC, + 0x40,0xFC,0x60,0xFC,0x60,0xFC,0xA0,0xCB,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xC3,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x80,0xFC,0x00,0xE4,0x21,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0x69,0x21,0xE4,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x41,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x84,0x7E,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x5D,0xE7,0xCC,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0xB5,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xD7,0xB5,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x07,0x01,0xBE,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDB,0xD6,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0xBF,0xF7,0xBA,0xD6,0x0A,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0xBE,0xF7,0xBE,0xF7,0xBE,0xEF,0xBE,0xEF,0xBE,0xF7,0xBF,0xF7,0xFC,0xDE,0x8F,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7A,0xCE,0xDF,0xF7, + 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x79,0xCE,0x00,0x00,0x00,0x00,0x8B,0x52,0xBB,0xD6,0xBF,0xF7,0xDF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0x79,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xAD,0xBE,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x3D,0xE7,0x41,0xEC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x62,0xBB,0xC1,0xC3,0xA1,0xC3,0xA0,0xC3,0x81,0xC3,0x80,0xC3,0x80,0xC3,0x61,0xCB,0xE0,0xE3,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x40,0xCB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBB,0x60,0xFC,0x60,0xFC, + 0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x7A,0x20,0xE4,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x80,0xFC,0x00,0xE4,0xC1,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBB,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0xC0,0xE3,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xDB,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xC3,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x61,0xFC,0x81,0xCB,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xCE,0x9E,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0xBF,0xF7,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBE,0xEF,0x9A,0xCE,0x35,0xA5,0x0C,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x21,0x5D,0xE7,0xBE,0xEF, + 0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBA,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xC6,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xB5,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x8B,0x4A,0xBB,0xCE,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xF7,0x7E,0xEF,0xF4,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x4A,0x3C,0xDF,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xEF,0x3D,0xE7,0x01,0xEC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC, + 0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xC0,0xF3,0x01,0x8A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x82,0x20,0xF4,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x60,0xFC,0xA0,0xD3,0x81,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x92,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xFC,0x61,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xBB,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x40,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xC1,0xE3,0x20,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x01,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xB3,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0xA1,0xDB,0x82,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x32,0xFC,0xD6,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x5D,0xDF,0xF0,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xAD,0xBE,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xF8,0xB5,0x00,0x00,0x00,0x00, + 0x00,0x00,0x9A,0xCE,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0x9E,0xEF,0x5D,0xE7,0xBB,0xD6,0x18,0xBE,0xB3,0x94,0x33,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x21,0x5D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBA,0xCE,0x00,0x00,0x00,0x00,0x87,0x21,0xDB,0xD6,0x7E,0xEF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xEF,0x14,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x9D,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x1C,0xDF,0x00,0x00,0x00,0x00,0x6A,0x42,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF, + 0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0x3D,0xE7,0xAB,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xD6,0xBF,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0x1C,0xDF,0xC1,0xEB,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC1,0xB2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x10,0x81,0xD3,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xF4,0xC1,0x79,0x00,0x00,0x00,0x00,0xE2,0x28,0x81,0xCB,0x60,0xFC,0x60,0xFC, + 0x60,0xFC,0x40,0xFC,0x60,0xFC,0x40,0xF4,0x61,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xBA,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0x60,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xEB,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x81,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xA2,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x81,0xDB,0xC2,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x73,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x1C,0xD7,0x0A,0x2A, + 0x00,0x00,0x00,0x00,0x93,0x8C,0x5E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9B,0xCE,0xAB,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xA5,0x9E,0xEF,0x9E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x84,0x7D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBF,0xEF,0xBF,0xEF,0x9E,0xEF,0xDB,0xD6,0x59,0xC6,0x72,0x8C,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDD,0x64,0x5E,0xE7,0x9E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xBB,0xCE,0x00,0x00,0x00,0x00,0x4A,0x21,0x9A,0xCE,0x5D,0xE7,0x5E,0xE7,0x7E,0xE7, + 0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x76,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x42,0x5D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x1C,0xDF,0xC5,0x08,0x00,0x00,0x4A,0x42,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x3D,0xDF,0x4A,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xD6,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x1C,0xDF,0xA1,0xE3,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB, + 0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xF3,0xA1,0xBA,0xE1,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xBA,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x01,0xBB,0x00,0x00,0x00,0x00,0x42,0x51,0xC1,0xDB,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0xA1,0xDB,0x21,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x41,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x39,0xA1,0xF3,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x21,0x92,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x92,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xA1,0xE3,0xA2,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x5B,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xF4,0x94,0x00,0x00,0x00,0x00,0xF8,0xB5,0x7E,0xE7,0x7E,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xA5,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x42,0xD7,0xB5,0x5D,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xE7, + 0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x5D,0xE7,0x7A,0xCE,0x31,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD6,0x4B,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x6C,0x42,0x7A,0xC6,0x5D,0xDF,0x5D,0xDF,0x5D,0xDF,0x5E,0xDF,0x5E,0xDF,0x3D,0xDF,0x39,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x21,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x3D,0xDF,0xA8,0x29,0x00,0x00,0x4A,0x42,0x9A,0xCE,0x9E,0xE7,0x9E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x1D,0xDF,0x6B,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xDB,0xD6,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0xFC,0xD6,0x81,0xEB,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x01,0xE3,0x61,0xB2,0x01,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x69,0xC0,0xEB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x41,0xD3,0x00,0x00,0x00,0x00,0x02,0x82,0x00,0xF4,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x01,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0x80,0xFB,0x80,0xFB, + 0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x00,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x80,0xEB,0xA0,0xFB,0xA0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xE1,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x92,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x81,0xE3,0xA2,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xB6,0x3E,0xDF,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x5E,0xDF,0xB7,0xAD,0x00,0x00,0x29,0x3A,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x3D,0xDF,0x72,0x84,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0xA5,0x7E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7E,0xDF,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x42,0x15,0x9D,0xDB,0xCE,0x5E,0xE7,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xFC,0xD6,0xF4,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x19,0xFC,0xD6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7A,0xC6,0x00,0x00,0x00,0x00,0x4D,0x42,0x7A,0xC6,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xD7,0x18,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x46,0x21,0x1D,0xD7,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x1D,0xD7,0x09,0x32,0x00,0x00,0x8B,0x4A,0x7A,0xC6,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x1D,0xD7,0x6B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xCE,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xFC,0xD6,0x61,0xEB,0xA0,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0xE0,0xF2,0xA0,0xDA,0xA1,0xD2,0x22,0xAA,0xA2,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x21,0xD3,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0x80,0xEB,0x01,0x51,0x00,0x00,0xE2,0xBA,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xF3,0x21,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0xE0,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xEB,0x80,0xFB,0x80,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xC1,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x92,0x80,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB, + 0x21,0xDB,0x42,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x74,0x1D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x39,0xB6,0x46,0x19,0xD0,0x6B,0xFD,0xCE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0x5E,0xD7,0x9B,0xC6,0xEB,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xA5,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xD8,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x63,0x76,0xA5,0x7A,0xC6,0x1D,0xD7,0x3D,0xD7,0x3D,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xDC,0xCE,0x6E,0x63,0x00,0x00,0x00,0x00,0x26,0x19, + 0xDC,0xCE,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x5D,0xDF,0x5E,0xDF,0x5A,0xBE,0x00,0x00,0x00,0x00,0xCB,0x31,0x39,0xBE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x1D,0xD7,0x19,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x29,0x1D,0xD7,0x5E,0xDF,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x5E,0xDF,0xFC,0xCE,0x87,0x21,0x00,0x00,0x8B,0x4A,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x1C,0xD7,0x6B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xDB,0xCE,0x41,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB, + 0x60,0xFB,0x60,0xFB,0x40,0xFB,0xA2,0x89,0x82,0x79,0xA2,0x89,0xC1,0x99,0xC1,0x99,0xA1,0x91,0xA1,0x91,0xA2,0x91,0x42,0x69,0x03,0x59,0xE2,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAA,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x41,0xB2,0x00,0x00,0x21,0xD3,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0xA0,0xFB,0x40,0xE3,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xBA,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0xC0,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0xC1,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xA2,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0xE1,0xDA,0xA2,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA9,0x29,0x7B,0xBE,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xBC,0xC6,0xD0,0x6B,0x56,0x9D,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xD7,0x3D,0xD7,0xB7,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x9D,0x5E,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0xD8,0xAD, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0x4A,0xAF,0x63,0xB7,0xA5,0x7A,0xBE,0xBB,0xCE,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xDF,0x56,0xA5,0x00,0x00,0x00,0x00,0x26,0x19,0xBC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x3D,0xD7,0x39,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xCF,0x1D,0xCF,0x1D,0xD7,0x1D,0xD7,0x15,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x8C,0x1D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0xBB,0xC6,0x00,0x00,0x00,0x00,0x6B,0x4A,0x5A,0xBE, + 0x5E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x1C,0xD7,0x8C,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9B,0xC6,0x3E,0xD7,0x3E,0xD7,0x3D,0xD7,0x3D,0xDF,0x5D,0xDF,0xBB,0xCE,0x21,0xEB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x82,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x71,0x20,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0xA0,0xCA,0x63,0x51,0x40,0xF3,0x60,0xFB, + 0x40,0xFB,0x40,0xFB,0x40,0xFB,0x60,0xFB,0xA1,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xBA,0x20,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0x80,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xD2,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x81,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAA,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0xA1,0xDA,0x82,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xA5,0xFD,0xCE,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6, + 0xFD,0xC6,0xFD,0xC6,0x15,0x95,0xF9,0xAD,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xDC,0xC6,0x11,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x9D,0x3E,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x3D,0xD7,0x3E,0xD7,0xB8,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x7C,0xB4,0x8C,0x19,0xB6,0xFC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x39,0xB6,0x09,0x3A,0x00,0x00,0x05,0x19,0x9C,0xC6,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0x19,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xB6,0xFD,0xCE, + 0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0xB7,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF4,0x94,0x1D,0xD7,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xF9,0xAD,0x00,0x00,0x00,0x00,0x2A,0x3A,0x3A,0xBE,0x3E,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0xFC,0xCE,0xED,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0xBE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0xBB,0xC6,0x01,0xE3,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xFA,0x62,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xD2,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0xC0,0xE2,0x41,0x9A,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xF3,0x81,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBA,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xA0,0xFA,0x40,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xCA,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x80,0xDA,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x28,0x81,0xCA,0x00,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x42,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x74,0xBC,0xBE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xB8,0x9D,0x1A,0xAE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDC,0xC6,0x19,0xAE,0xC8,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x95,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x97,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x8C,0xDC,0xC6,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0x3A,0xB6,0xF1,0x73,0x00,0x00,0x26,0x19,0x7B,0xBE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0xF9,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x57,0x9D,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xF9,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xA5,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xB8,0xA5,0x00,0x00,0x00,0x00,0x09,0x3A,0x19,0xB6,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xFC,0xCE,0xED,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x5B,0xBE,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xBB,0xC6,0xC1,0xEA,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xA1,0xC0,0xF2,0xE0,0xFA,0x00,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xF2,0x61,0xBA,0x00,0xFB,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0x60,0xDA,0x81,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xBA, + 0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x00,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB9,0xA0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x80,0xF2,0x61,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x81,0xC0,0xF2,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA2,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x19,0x1A,0xAE,0xBD,0xBE,0xBD,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x7B,0xB6,0x9C,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x15,0x95,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x8C,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0x97,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x84,0xF5,0x84,0xC8,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x01,0x5B,0xB6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0x3A,0xB6,0x11,0x74,0x00,0x00,0x26,0x19,0x7B,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xB8,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0xF1,0x6B,0xBC,0xBE,0xBD,0xC6,0xDC,0xC6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x9C,0xBE,0x12,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x6F,0x5B,0x5A,0xB6,0xDC,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0x32,0x74,0x00,0x00,0x00,0x00,0xE9,0x31,0x19,0xAE,0xFD,0xCE,0xFD,0xC6,0xFD,0xC6,0xFD,0xCE,0x1D,0xCF,0xDC,0xC6,0x8C,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3A,0xB6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0x9B,0xBE,0x81,0xEA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0xA0,0xFA,0x80,0xFA,0x21,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x49,0x41,0xDA,0xC0,0xFA,0xC0,0xFA,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xC0,0xF2,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x00,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xB9,0x60,0xFA,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0xC0,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x58,0x40,0xEA,0x80,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x20,0xDA,0x61,0x99,0xE1,0x58,0x00,0x00,0x00,0x00,0xC2,0x48,0x81,0x89,0x60,0xDA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA, + 0x60,0xFA,0x00,0xDA,0x01,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x9D,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x7B,0xB6,0xF1,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x84,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xC6,0xDD,0xBE,0x77,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0xD1,0x63,0x1A,0xAE,0x9C,0xB6,0x98,0x9D,0x93,0x7C,0x0E,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x00,0x73,0x7C,0x9C,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xDD,0xBE,0x97,0x9D,0x09,0x32, + 0x00,0x00,0x05,0x19,0x3B,0xAE,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0xB8,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x3A,0xF9,0xA5,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x1A,0xAE,0x73,0x7C,0x6B,0x3A,0x00,0x00,0x00,0x00,0xE9,0x31,0xF1,0x6B,0xD8,0xA5,0x9C,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBD,0xBE,0x3A,0xAE,0x09,0x32,0x00,0x00,0x00,0x00,0x09,0x32,0xF9,0xAD,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0xFD,0xC6,0xBC,0xBE,0x4B,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x1A,0xAE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xC6,0xDD,0xBE,0x5B,0xB6,0x41,0xEA,0x60,0xFA, + 0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB1,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x41,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB9,0x20,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xA0,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xB9,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x40,0xF2,0x20,0xDA,0x41,0xDA,0x41,0xD2,0x41,0xE2,0x80,0xF2,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x20,0xFA,0x80,0xB9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0x84,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0xD9,0xA5,0xC8,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x84,0xBC,0xBE,0x9C,0xB6,0x9C,0xB6,0xBC,0xBE,0xBC,0xBE, + 0xBD,0xBE,0x56,0x95,0x00,0x00,0x00,0x00,0xD3,0x4B,0x98,0x9D,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7B,0xB6,0xD9,0xA5,0x77,0x95,0x57,0x95,0x52,0x74,0x52,0x74,0xF5,0x8C,0xB8,0xA5,0x5B,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x36,0x95,0x00,0x00,0x00,0x00,0x05,0x11,0x3A,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x98,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x84,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xB6,0xF9,0xA5,0xB8,0xA5,0xB8,0xA5,0xD9,0xA5,0x7B,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xBE,0x9C,0xB6,0x16,0x8D,0x00,0x00,0x00,0x00,0x00,0x00, + 0xE9,0x31,0xD9,0xA5,0xBD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0x9B,0xB6,0x2A,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xF9,0xA5,0xBC,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0x1A,0xAE,0x21,0xE2,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x79,0x40,0xEA,0x60,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA, + 0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x20,0xE2,0xC1,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xB9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0x80,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x69,0x01,0xE2,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0xC0,0xD9,0xA1,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x11,0xFA,0x9D, + 0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x37,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0x7C,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x36,0x8D,0x00,0x00,0x00,0x00,0x15,0x8D,0x7B,0xB6,0x7B,0xB6,0x7B,0xB6,0x7B,0xAE,0x5B,0xAE,0x7B,0xAE,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xBE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x1A,0xA6,0x90,0x63,0x00,0x00,0x00,0x00,0x26,0x11,0x1A,0xA6,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x78,0x95,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x68,0x09,0x98,0x9D,0x7C,0xAE,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0xD9,0x9D,0x8B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x29,0xB9,0x9D,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0xBC,0xB6,0xBC,0xBE,0x5B,0xAE,0x2A,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xF9,0xA5,0x9C,0xB6,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0xD9,0x9D,0xE1,0xE1,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x00,0xFA,0xE1,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,0x22,0x00,0xC1,0xD1,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0xC0,0xD1,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xB1,0xA0,0xF9,0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0xA0,0xF9,0x60,0xD1,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,0x91,0xE1,0xE1,0x00,0xFA,0x20,0xFA,0x20,0xFA, + 0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xA0,0xE1,0xE1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x8D,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x32,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x7C,0x7C,0xAE,0x5B,0xAE,0x5C,0xAE,0x5C,0xAE,0x7C,0xAE,0x7C,0xAE,0xF5,0x84,0x00,0x00,0x00,0x00,0x57,0x95,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE, + 0x5B,0xAE,0x7B,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x1A,0xA6,0x94,0x7C,0x84,0x00,0x00,0x00,0x00,0x00,0x4D,0x22,0xFA,0xA5,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x77,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x4B,0x98,0x95,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x98,0x95,0xB1,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x29,0x98,0x9D,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x3B,0xAE,0x2A,0x2A,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xD9,0x9D,0x7C,0xAE,0x7C,0xAE,0x5C,0xAE,0x5B,0xAE,0x5B,0xAE,0xB9,0x9D,0xA0,0xE1,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xE2,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xA1,0x00,0xFA,0x00,0xFA,0x20,0xFA,0x20,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x21,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x41,0xB9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xD1,0x00,0x00,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,0x81,0xC1,0xD9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA1,0xD9,0xE1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x6C,0xFA,0x9D,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0xFA,0x9D,0xFA,0x9D,0xB9,0x95,0x4B,0x32,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x7C,0x5B,0xAE,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x5B,0xA6,0x5B,0xAE,0xD5,0x84,0x00,0x00,0x00,0x00,0x6B,0x32,0xB5,0x7C,0xB9,0x9D,0x3B,0xA6,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x3B,0xAE,0x3B,0xA6,0x3B,0xA6,0xD9,0x9D,0x74,0x74,0x4B,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0x44,0xFA,0x9D,0x1B,0xA6,0x1B,0xA6,0x1B,0xA6,0x1B,0x9E,0x1B,0xA6,0x57,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xED,0x4A,0x37,0x8D,0x1B,0xA6,0x3B,0xA6,0x3B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE, + 0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x3B,0xAE,0x3B,0xA6,0x1B,0xA6,0x37,0x8D,0xD1,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE9,0x29,0x98,0x95,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x1A,0xA6,0xEA,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xB9,0x95,0x5B,0xA6,0x5B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0xB9,0x9D,0x60,0xE1,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0xC2,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x38,0x81,0xC9,0xE0,0xF9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xC0,0xF9,0xA0,0xE1,0xE2,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xB1,0x60,0xF1,0x40,0xF1,0x40,0xF1,0x20,0xF1,0x20,0xF9,0x40,0xF9,0x00,0xE1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x50,0x61,0xB9,0x81,0xD1,0xA0,0xF1,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA0,0xF1,0x61,0xD9,0x41,0xB1, + 0xA2,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x32,0x58,0x85,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xBA,0x95,0xB9,0x95,0xD5,0x7C,0xE9,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x74,0x3B,0xA6,0x1B,0x9E,0xFB,0x9D,0xFB,0x9D,0x1B,0x9E,0x1B,0xA6,0xD5,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x4B,0xD5,0x7C,0x98,0x95,0x1B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x1B,0xA6,0xB9,0x95,0xF6,0x84,0xB0,0x5B,0x06,0x09,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0x3C,0xD9,0x95,0xDA,0x9D,0xFA,0x9D,0xDA,0x9D,0xDA,0x9D,0xFA,0x9D,0x37,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0x42,0x12,0x6C,0x57,0x8D,0xFA,0xA5,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xAE,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x1B,0xA6,0xFA,0x9D,0x57,0x8D,0x53,0x74,0xCD,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE9,0x29,0x78,0x95,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0xF9,0x9D,0xA8,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x98,0x95,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0xA6,0x1B,0xA6,0xB8,0x95, + 0xE1,0xB0,0x21,0xC1,0x41,0xB9,0x41,0xC1,0x41,0xC9,0x41,0xD9,0x20,0xD9,0xC7,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x99,0xC0,0xF9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA0,0xF9,0x40,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x80,0x01,0xB9,0x21,0xC1,0x21,0xC1,0x01,0xC1,0x01,0xC1,0x01,0xD1,0xE2,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,0x62,0x30,0xE1,0x88,0x41,0xC1,0x60,0xC9,0x80,0xD9,0x80,0xE1,0x80,0xE1,0x80,0xD9,0x61,0xC9,0x41,0xC1,0xE1,0x90,0xC6,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x11,0xD1,0x5B,0x75,0x6C,0x33,0x6C,0x13,0x64,0x12,0x64,0x13,0x64,0x33,0x6C,0xF2,0x63,0xD1,0x63,0x6F,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x5B,0xD5,0x7C,0x94,0x74,0x94,0x74, + 0x94,0x74,0x94,0x7C,0x94,0x7C,0x6F,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x21,0x12,0x6C,0x16,0x85,0x16,0x8D,0x77,0x95,0x98,0x95,0x98,0x95,0x78,0x95,0x16,0x8D,0x37,0x8D,0x53,0x74,0xC9,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x6C,0x53,0x6C,0x33,0x6C,0x32,0x6C,0x12,0x6C,0x12,0x6C,0x90,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x5B,0xB5,0x7C,0xD9,0x9D,0x57,0x95,0x98,0x9D,0x98,0x9D,0x57,0x95,0x98,0x95,0xB4,0x7C,0x0E,0x4B,0x06,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x67,0x21,0x11,0x6C,0xB5,0x7C,0xB5,0x7C,0xF6,0x84,0x16,0x85,0x16,0x8D,0x94,0x7C,0x26,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0xF2,0x63,0x74,0x74,0x94,0x7C,0xB5,0x7C,0xB5,0x84,0xD5,0x84,0x94,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x81,0xA0,0xE1,0xC0,0xF9,0xA0,0xF9, + 0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF1,0xC1,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,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xA8,0xE0,0xC0,0xE0,0xB8,0xE1,0xB0,0x21,0xB1,0x61,0xC9,0xA0,0xE9,0xA0,0xF9,0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x01,0xC1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC1,0x40,0xF9,0x40,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xD9,0xA1,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD1,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xF9,0xE0,0xE0,0xC1,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0xE0,0xD8,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xF9,0x20,0xF9,0x00,0xF9,0x00,0xD1,0xA1,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x50,0xC0,0xD8,0x00,0xF9,0x20,0xF9,0x00,0xF9,0x00,0xF9,0x00,0xF9,0x20,0xF9,0x20,0xF1, + 0x00,0xF1,0xE0,0xD8,0xE1,0xB8,0xA2,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x60,0xA1,0xB0,0xC0,0xD0,0xC1,0xD0,0xC1,0xD0,0xC1,0xD0,0xC1,0xC8,0xE3,0xD0,0xE1,0xB8,0xA2,0x90,0x82,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //alpha channel data: - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x05, 0x47, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xC2, 0x96, 0x56, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x40, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xAD, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x02, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB1, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x5A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x5D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x21, 0x00, 0x00, 0x3C, - 0x4C, 0x93, 0x73, 0x4B, 0x45, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x45, 0x4D, 0x55, 0x4E, 0x45, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xE7, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFE, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1F, 0x5F, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x3F, 0x3F, 0x3F, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x43, 0x76, 0x8E, 0x8E, 0x69, 0x3F, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x2D, 0x52, 0x8F, 0x97, 0x8F, 0x86, 0x46, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2C, 0x49, 0x7F, 0x8E, 0x8E, 0x8C, 0x40, 0x35, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0C, 0x0C, 0x0C, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x52, 0x8F, 0x8E, 0x84, 0x43, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x85, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xDA, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xEF, 0xEF, 0xEF, - 0xEF, 0xEF, 0xEF, 0x6C, 0x00, 0x78, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xD8, 0x00, 0x00, 0x1E, 0xB7, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x87, 0xDE, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xD4, 0x79, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x5B, 0xF0, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x7F, 0xE4, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xED, 0x9C, 0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x7A, 0xDF, - 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF0, 0x8F, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0xEF, 0xF1, 0xF2, 0xF2, 0xF2, 0x9C, 0x00, 0x05, 0x7C, 0xDA, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xBB, 0x34, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xFC, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x95, 0x50, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x05, 0x58, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x2A, 0x00, 0x00, 0x00, 0x02, 0x82, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xE8, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x01, 0x57, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFD, 0xAD, 0x2E, 0x00, 0x00, 0x00, 0x27, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xE6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0x19, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF7, 0x80, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x01, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x0E, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x8A, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x15, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xA0, 0x07, 0x00, 0x00, 0x00, 0x05, 0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, - 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x01, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x2B, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x9B, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x98, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x00, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xED, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0x00, 0x00, 0x02, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x8A, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x22, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x29, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x11, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x03, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x00, 0x2D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x00, 0x00, - 0x4E, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x55, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0xAA, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBC, 0xB6, 0xEB, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x35, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xF6, 0x08, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xA2, 0x56, 0x54, 0x98, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8B, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x72, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x0C, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x5C, 0x08, 0x01, 0x00, 0x07, 0x0D, 0x4C, 0x8B, 0xF6, 0xFF, 0x92, 0x01, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x01, 0xA9, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xCE, 0x69, 0x55, 0x55, 0x58, 0xC2, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0x06, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xA5, 0x64, 0x55, 0xA1, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x80, 0x43, 0x43, 0x43, 0x45, 0x8C, 0x14, 0x00, 0x3B, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x14, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x24, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x21, 0x89, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x08, 0x00, 0x00, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4B, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0xDD, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x85, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x35, 0x00, 0x00, 0x17, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x46, 0x00, 0x00, 0x00, 0x00, 0x03, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xAF, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x00, 0x00, 0x36, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x29, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x1E, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x07, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE2, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xD3, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC2, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xC8, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x03, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x0C, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x00, - 0x00, 0x00, 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x00, 0x00, 0x00, 0x00, 0xB1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x4D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x02, 0x00, 0x00, 0x00, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x06, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x00, 0x00, 0x00, 0x14, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, - 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0xD5, 0x9A, 0x46, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x02, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x37, 0x00, 0x00, 0x01, 0xB8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x13, - 0x00, 0x00, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFB, 0x9F, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x09, 0xE4, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x16, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x86, 0x00, 0x00, 0x12, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x18, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x05, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0x00, 0x00, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x01, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x43, 0x00, 0x00, 0x00, 0x00, 0x09, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x08, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x6A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD8, 0x00, 0x00, 0x53, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0x00, 0x09, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x01, 0x84, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x50, 0x00, 0x00, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x0C, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFA, 0xB1, 0x5C, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x2D, 0x00, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x49, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x0A, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x92, 0xE1, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x1D, 0x00, 0x00, 0x3E, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x0A, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x28, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xA1, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x40, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3D, 0x78, 0xB3, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x03, 0xF7, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0x2F, 0xFB, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x83, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x47, 0xB2, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x01, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xAF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE2, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDA, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x02, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x91, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x02, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6D, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x4A, 0x06, 0x00, 0x00, 0x04, 0x67, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFE, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x29, 0xF7, 0xFF, 0xE6, 0x4A, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x02, - 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x0B, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x54, 0x05, 0x00, 0x00, 0x06, 0x46, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x1D, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE5, 0xB6, 0xB6, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xAB, 0x00, 0x00, 0x05, 0xD5, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0xB0, 0x69, 0x69, 0x67, 0x67, 0xA8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0, 0xB6, 0xB6, 0xE3, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0x00, 0x00, 0x00, - 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xF4, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x32, 0x00, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, - 0x00, 0x06, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD3, 0x18, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xCB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xF3, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x01, 0x00, 0x00, 0x22, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE5, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x32, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x04, 0x77, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x83, 0x01, 0x00, 0x00, 0x00, 0x08, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xC9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x83, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x96, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x25, 0xA8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xB2, 0x2F, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x04, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x70, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x67, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x46, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 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, 0x00, 0x00, 0xA3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x26, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x61, 0x9D, 0xE0, 0xDF, 0xDF, 0xDF, 0xDF, 0xDE, 0x91, 0x54, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3C, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0x3F, 0x3F, - 0x3F, 0x3F, 0x3F, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x53, 0x8F, 0xC7, 0xDF, 0xDF, 0xE5, 0xE3, 0xD7, 0x8E, 0x62, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x89, 0x93, 0xDF, 0xDF, 0xDF, 0xDC, 0x8F, 0x82, 0x3F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x3D, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xFC, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xBD, 0x94, 0x94, 0x94, 0xB9, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xF9, 0x9B, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xA9, 0xB0, 0xDD, 0xFF, 0xFF, 0xFF, 0xBD, 0xAF, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x11,0x11,0x11,0x11,0x11,0x11,0x05,0x47,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xDC,0xFF,0xFF,0xFF,0xFF,0xFF,0xB4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0xC2,0x96,0x56,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x40,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xAD,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x02,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB1,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x5A, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x00,0x5D,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x16,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xAE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x21,0x00,0x00,0x3C, + 0x4C,0x93,0x73,0x4B,0x45,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x45,0x4D,0x55,0x4E,0x45,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xE7,0xD3,0xD3,0xD3,0xD3,0xD3,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFE,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1F,0x5F,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0x3F,0x3F,0x3F,0x3F,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x33,0x43,0x76,0x8E,0x8E,0x69,0x3F,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x2D,0x52,0x8F,0x97,0x8F,0x86,0x46,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x2C,0x49,0x7F,0x8E,0x8E,0x8C,0x40,0x35,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x0C,0x0C,0x03, + 0x00,0x00,0x00,0x00,0x3C,0x52,0x8F,0x8E,0x84,0x43,0x1A,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x85,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xDA,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xEF,0xEF,0xEF, + 0xEF,0xEF,0xEF,0x6C,0x00,0x78,0xEF,0xEF,0xEF,0xEF,0xEF,0xD8,0x00,0x00,0x1E,0xB7,0xF6,0xFF,0xFF,0xFF,0xFF,0xF5,0x2A,0x00,0x00,0x00,0x00,0x00,0x1C,0x87,0xDE,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xD4,0x79,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x52,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x5B,0xF0,0xEF,0xEF,0xEF,0xEF,0xEF,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x7F,0xE4,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xED,0x9C,0x2F,0x01,0x00,0x00,0x00,0x00,0x01,0xE0,0xEF,0xEF,0xEF,0xEF,0xEF,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x7A,0xDF, + 0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF0,0x8F,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xD0,0xEF,0xF1,0xF2,0xF2,0xF2,0x9C,0x00,0x05,0x7C,0xDA,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xBB,0x34,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xFC,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x95,0x50,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x05,0x58,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x2A,0x00,0x00,0x00,0x02,0x82,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xE8,0x4D,0x00,0x00,0x00,0x00,0x00,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x01,0x57,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFD,0xAD,0x2E,0x00,0x00,0x00,0x27,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x87,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0x19,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xF7,0x80,0x02,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x01,0xD4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x0E,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x8A,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x15,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xA0,0x07,0x00,0x00,0x00,0x05,0xDA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x71,0x00,0x00,0x00, + 0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x01,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x2B,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x06,0x9B,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x98,0x03,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x00,0x82,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xED,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0x00,0x00,0x02,0xB9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00,0x00,0x00,0x8A, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x22,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x29,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x11,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x99,0x03,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x00,0x2D,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00, + 0x4E,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x55,0x00,0x00,0x00,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x5D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0xAA, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBC,0xB6,0xEB,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x35,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xF6,0x08,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0x00,0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xA2,0x56,0x54,0x98,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x00,0x00,0x00,0x00,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8B,0x00,0x00,0x00,0x00, + 0x00,0x00,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x72,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x0C,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x5C,0x08,0x01,0x00,0x07,0x0D,0x4C,0x8B,0xF6,0xFF,0x92,0x01,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x00,0x00,0x00,0x01,0xA9,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xCE,0x69,0x55,0x55,0x58,0xC2,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDE,0x06,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xA5,0x64,0x55,0xA1,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0x00,0x00,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0x06,0x00,0x00,0x00,0x00,0x00,0x7D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x80,0x43,0x43,0x43,0x45,0x8C,0x14,0x00,0x3B,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB2,0x08,0x00,0x00,0x00, + 0x00,0x14,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x00,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x00,0x00,0x00,0x00,0x00,0x15,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x24,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x38,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x21,0x89,0x0A,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x08,0x00,0x00,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x02,0x00,0x00,0x00,0x00,0x00,0x6B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4B,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9E,0x03,0x00,0x00,0x00,0x00,0x20,0xDD,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x85,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x35,0x00,0x00,0x17,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x46,0x00,0x00,0x00,0x00,0x03,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x51,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xAF,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x00,0x00,0x00,0x36,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x29,0x00,0x00,0x00,0x00,0x5B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00, + 0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x1E,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x07,0x00,0x00,0x6E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xD3,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x90,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x4D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC2,0x90,0x90,0x90,0x90,0x90,0x90,0xC8,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0x03,0x00,0x00,0x00,0xBB,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x00,0x00,0x13,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x0C,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7,0x00, + 0x00,0x00,0x00,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x61,0x00,0x00,0x00,0x00,0xB1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x4D,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x71,0x00,0x00,0x00,0x00,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x02,0x00,0x00,0x00,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x06,0x00,0x00,0x00,0xA2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7,0x00,0x00,0x00,0x14,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x21,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00, + 0x00,0xB7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0xD5,0x9A,0x46,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x02,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x00,0x00,0x03,0xF7,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC4,0x00,0x00,0x00,0x00,0x00,0x0D,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x37,0x00,0x00,0x01,0xB8,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x5C,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x13, + 0x00,0x00,0x5A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0x04,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x5D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFB,0x9F,0x46,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x09,0xE4,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x16,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xBE,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x97,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x86,0x00,0x00,0x12,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x18,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x05,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x47,0x00,0x00,0x97,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x01,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x43,0x00,0x00,0x00,0x00,0x09,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x08,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x6A,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xD8,0x00,0x00,0x53,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA8,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9D,0x00,0x09,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x37,0x00,0x00, + 0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x01,0x84,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x50,0x00,0x00,0x00,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x0C,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFA,0xB1,0x5C,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x2D,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x52,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFC,0x09,0x00,0x00,0x00,0x00,0x49,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x0A,0x41,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x92,0xE1,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x1D,0x00,0x00,0x3E, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x0A,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x28,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xA1,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x54,0x40,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x67,0x00,0xED,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x0F,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x00,0x0B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2E,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x3D,0x78,0xB3,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xB5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x00,0x00,0x03,0xF7, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x2F,0xFB,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x02,0x00,0x00,0x00,0x00,0x00,0xA1,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0x83,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x47,0xB2,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0x01,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xAF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x7A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB9,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDA,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x63,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x02,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x96, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x4F,0x91,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x02,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x56,0x00,0x00,0x00,0x00,0x00, + 0x00,0x38,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6D,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x08,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x4A,0x06,0x00,0x00,0x04,0x67,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFE,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x29,0xF7,0xFF,0xE6,0x4A,0x07,0x00,0x00,0x00,0x00,0x00,0x01,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1,0x02, + 0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x0B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x54,0x05,0x00,0x00,0x06,0x46,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x1D,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE5,0xB6,0xB6,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xAB,0x00,0x00,0x05,0xD5,0xFF,0xFF,0xFF,0xFE,0xEF,0xB0,0x69,0x69,0x67,0x67,0xA8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE0,0xB6,0xB6,0xE3,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8D,0x00,0x00,0x00, + 0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFD,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xF4, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x9E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x32,0x00,0x00,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00, + 0x00,0x06,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD3,0x18,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xF3,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x9B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0x01,0x00,0x00,0x22,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x22,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x2D,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE5,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x32,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x04,0x77,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x83,0x01,0x00,0x00,0x00,0x08,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xC9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD2,0x1E,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xD2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x83,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x96, + 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x25,0xA8,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xB2,0x2F,0x01,0x00, + 0x00,0x00,0x00,0x04,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x70,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x67,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x46,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,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,0x00,0x00,0xA3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x3F,0x3F,0x3F,0x3F,0x3F,0x40,0x26,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x61,0x9D,0xE0,0xDF,0xDF,0xDF,0xDF,0xDE,0x91,0x54,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3C,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x3F,0x3F,0x3F, + 0x3F,0x3F,0x3F,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x53,0x8F,0xC7,0xDF,0xDF,0xE5,0xE3,0xD7,0x8E,0x62,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x3F,0x3F,0x3F,0x3F,0x3F,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x89,0x93,0xDF,0xDF,0xDF,0xDC,0x8F,0x82,0x3F,0x05,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x3D,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xFC,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0xBD,0x94,0x94,0x94,0xB9,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xF9,0x9B,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xA9,0xB0,0xDD,0xFF,0xFF,0xFF,0xBD,0xAF,0x5F,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; const lv_image_dsc_t ui_img_text_218x40_png = { .header.w = 218, diff --git a/main/Application/Tasks/GUI/Export/project.info b/main/Application/Tasks/GUI/Export/project.info index 62525e8..7e33403 100644 --- a/main/Application/Tasks/GUI/Export/project.info +++ b/main/Application/Tasks/GUI/Export/project.info @@ -1,9 +1,9 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-01-16T11:44:08.7236698+01:00", + "datetime": "2026-01-16T13:29:19.5084763+01:00", "editor_version": "1.5.4", - "project_version": 93, + "project_version": 94, "user": "Kampert Daniel", - "export_datetime": "2026-01-16T13:13:27.6266397+01:00", + "export_datetime": "2026-01-29T11:38:03.9082624+01:00", "export_user": "Kampert Daniel" } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.c b/main/Application/Tasks/GUI/Export/screens/ui_Info.c index ff59aec..1169b49 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.c @@ -1,65 +1,67 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision #include "../ui.h" -lv_obj_t *ui_Info = NULL; -lv_obj_t *ui_Panel_Info_Header = NULL; -lv_obj_t *ui_Label_Info_Header = NULL; -lv_obj_t *ui_Panel_Info_Content = NULL; -lv_obj_t *ui_Panel_Device = NULL; -lv_obj_t *ui_Label_Info_Device = NULL; -lv_obj_t *ui_Container_Info_Device = NULL; -lv_obj_t *ui_Info_Container4 = NULL; -lv_obj_t *ui_Label_Info_MAC_Name = NULL; -lv_obj_t *ui_Label_Info_IP_Name = NULL; -lv_obj_t *ui_Info_Container5 = NULL; -lv_obj_t *ui_Label_Info_MAC = NULL; -lv_obj_t *ui_Label_Info_IP = NULL; -lv_obj_t *ui_Panel_Battery = NULL; -lv_obj_t *ui_Label_Info_Battery = NULL; -lv_obj_t *ui_Container_Battery = NULL; -lv_obj_t *ui_Info_Container2 = NULL; -lv_obj_t *ui_Label_Info_Battery_Status_Name = NULL; -lv_obj_t *ui_Label_Info_Battery_Voltage_Name = NULL; -lv_obj_t *ui_Label_Info_Battery_Remaining_Name = NULL; -lv_obj_t *ui_Info_Container3 = NULL; -lv_obj_t *ui_Label_Info_Battery_Status = NULL; -lv_obj_t *ui_Label_Info_Battery_Voltage = NULL; -lv_obj_t *ui_Label_Info_Battery_Remaining = NULL; -lv_obj_t *ui_Info_Bar2 = NULL; -lv_obj_t *ui_Panel_Lepton = NULL; -lv_obj_t *ui_Label_Info_Lepton = NULL; -lv_obj_t *ui_Container_Lepton = NULL; -lv_obj_t *ui_Info_Container1 = NULL; -lv_obj_t *ui_Label_Info_Lepton_Serial_Name = NULL; -lv_obj_t *ui_Label_Info_Lepton_Part_Name = NULL; -lv_obj_t *ui_Label_Info_Lepton_Revision_Name = NULL; -lv_obj_t *ui_Label_Info_Lepton_Uptime_Name = NULL; -lv_obj_t *ui_Label_Info_Lepton_FPA_Name = NULL; -lv_obj_t *ui_Label_Info_Lepton_AUX_Name = NULL; -lv_obj_t *ui_Info_Container7 = NULL; -lv_obj_t *ui_Label_Info_Lepton_Serial = NULL; -lv_obj_t *ui_Label_Info_Lepton_Part = NULL; -lv_obj_t *ui_Label_Info_Lepton_Revision = NULL; -lv_obj_t *ui_Label_Info_Lepton_Uptime = NULL; -lv_obj_t *ui_Label_Info_Lepton_FPA = NULL; -lv_obj_t *ui_Label_Info_Lepton_AUX = NULL; -lv_obj_t *ui_Container_Info_Buttons = NULL; -lv_obj_t *ui_Button_Info_Back = NULL; -lv_obj_t *ui_Label_Info_Back = NULL; +lv_obj_t * ui_Info = NULL; +lv_obj_t * ui_Panel_Info_Header = NULL; +lv_obj_t * ui_Label_Info_Header = NULL; +lv_obj_t * ui_Panel_Info_Content = NULL; +lv_obj_t * ui_Panel_Device = NULL; +lv_obj_t * ui_Label_Info_Device = NULL; +lv_obj_t * ui_Container_Info_Device = NULL; +lv_obj_t * ui_Info_Container4 = NULL; +lv_obj_t * ui_Label_Info_MAC_Name = NULL; +lv_obj_t * ui_Label_Info_IP_Name = NULL; +lv_obj_t * ui_Label_Info_Serial_Name = NULL; +lv_obj_t * ui_Info_Container5 = NULL; +lv_obj_t * ui_Label_Info_MAC = NULL; +lv_obj_t * ui_Label_Info_IP = NULL; +lv_obj_t * ui_Label_Info_Serial = NULL; +lv_obj_t * ui_Panel_Battery = NULL; +lv_obj_t * ui_Label_Info_Battery = NULL; +lv_obj_t * ui_Container_Battery = NULL; +lv_obj_t * ui_Info_Container2 = NULL; +lv_obj_t * ui_Label_Info_Battery_Status_Name = NULL; +lv_obj_t * ui_Label_Info_Battery_Voltage_Name = NULL; +lv_obj_t * ui_Label_Info_Battery_Remaining_Name = NULL; +lv_obj_t * ui_Info_Container3 = NULL; +lv_obj_t * ui_Label_Info_Battery_Status = NULL; +lv_obj_t * ui_Label_Info_Battery_Voltage = NULL; +lv_obj_t * ui_Label_Info_Battery_Remaining = NULL; +lv_obj_t * ui_Info_Bar2 = NULL; +lv_obj_t * ui_Panel_Lepton = NULL; +lv_obj_t * ui_Label_Info_Lepton = NULL; +lv_obj_t * ui_Container_Lepton = NULL; +lv_obj_t * ui_Info_Container1 = NULL; +lv_obj_t * ui_Label_Info_Lepton_Serial_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_Part_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_Revision_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_Uptime_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_FPA_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_AUX_Name = NULL; +lv_obj_t * ui_Info_Container7 = NULL; +lv_obj_t * ui_Label_Info_Lepton_Serial = NULL; +lv_obj_t * ui_Label_Info_Lepton_Part = NULL; +lv_obj_t * ui_Label_Info_Lepton_Revision = NULL; +lv_obj_t * ui_Label_Info_Lepton_Uptime = NULL; +lv_obj_t * ui_Label_Info_Lepton_FPA = NULL; +lv_obj_t * ui_Label_Info_Lepton_AUX = NULL; +lv_obj_t * ui_Container_Info_Buttons = NULL; +lv_obj_t * ui_Button_Info_Back = NULL; +lv_obj_t * ui_Label_Info_Back = NULL; // event funtions void ui_event_Info(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if (event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { + if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { lv_indev_wait_release(lv_indev_active()); _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } - if (event_code == LV_EVENT_SCREEN_LOADED) { + if(event_code == LV_EVENT_SCREEN_LOADED) { ScreenInfoLoaded(e); } } @@ -68,7 +70,7 @@ void ui_event_Button_Info_Back(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if (event_code == LV_EVENT_CLICKED) { + if(event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } } @@ -221,6 +223,22 @@ void ui_Info_screen_init(void) lv_obj_set_style_pad_top(ui_Label_Info_IP_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_bottom(ui_Label_Info_IP_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + ui_Label_Info_Serial_Name = lv_label_create(ui_Info_Container4); + lv_obj_set_width(ui_Label_Info_Serial_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Serial_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Serial_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Serial_Name, "Serial:\n"); + lv_obj_remove_flag(ui_Label_Info_Serial_Name, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Serial_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Serial_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Serial_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Serial_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + ui_Info_Container5 = lv_obj_create(ui_Container_Info_Device); lv_obj_remove_style_all(ui_Info_Container5); lv_obj_set_width(ui_Info_Container5, lv_pct(50)); @@ -253,7 +271,7 @@ void ui_Info_screen_init(void) lv_obj_set_width(ui_Label_Info_IP, lv_pct(100)); lv_obj_set_height(ui_Label_Info_IP, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Label_Info_IP, LV_ALIGN_CENTER); - lv_label_set_text(ui_Label_Info_IP, "127.0.0.1\n"); + lv_label_set_text(ui_Label_Info_IP, "127.0.0.1"); lv_obj_remove_flag(ui_Label_Info_IP, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags @@ -266,6 +284,23 @@ void ui_Info_screen_init(void) lv_obj_set_style_pad_top(ui_Label_Info_IP, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_bottom(ui_Label_Info_IP, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + ui_Label_Info_Serial = lv_label_create(ui_Info_Container5); + lv_obj_set_width(ui_Label_Info_Serial, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Serial, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Serial, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Serial, "00000001"); + lv_obj_remove_flag(ui_Label_Info_Serial, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Serial, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Serial, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Serial, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Serial, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Serial, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + ui_Panel_Battery = lv_obj_create(ui_Panel_Info_Content); lv_obj_set_width(ui_Panel_Battery, 300); lv_obj_set_height(ui_Panel_Battery, 100); @@ -453,8 +488,8 @@ void ui_Info_screen_init(void) lv_obj_set_style_bg_grad_dir(ui_Info_Bar2, LV_GRAD_DIR_HOR, LV_PART_INDICATOR | LV_STATE_DEFAULT); //Compensating for LVGL9.1 draw crash with bar/slider max value when top-padding is nonzero and right-padding is 0 - if (lv_obj_get_style_pad_top(ui_Info_Bar2, LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_Info_Bar2, - lv_obj_get_style_pad_right(ui_Info_Bar2, LV_PART_MAIN) + 1, LV_PART_MAIN); + if(lv_obj_get_style_pad_top(ui_Info_Bar2, LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_Info_Bar2, + lv_obj_get_style_pad_right(ui_Info_Bar2, LV_PART_MAIN) + 1, LV_PART_MAIN); ui_Panel_Lepton = lv_obj_create(ui_Panel_Info_Content); lv_obj_set_width(ui_Panel_Lepton, 300); lv_obj_set_height(ui_Panel_Lepton, 140); @@ -754,9 +789,7 @@ void ui_Info_screen_init(void) void ui_Info_screen_destroy(void) { - if (ui_Info) { - lv_obj_del(ui_Info); - } + if(ui_Info) lv_obj_del(ui_Info); // NULL screen variables ui_Info = NULL; @@ -769,9 +802,11 @@ void ui_Info_screen_destroy(void) ui_Info_Container4 = NULL; ui_Label_Info_MAC_Name = NULL; ui_Label_Info_IP_Name = NULL; + ui_Label_Info_Serial_Name = NULL; ui_Info_Container5 = NULL; ui_Label_Info_MAC = NULL; ui_Label_Info_IP = NULL; + ui_Label_Info_Serial = NULL; ui_Panel_Battery = NULL; ui_Label_Info_Battery = NULL; ui_Container_Battery = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.h b/main/Application/Tasks/GUI/Export/screens/ui_Info.h index 0ddd077..3e61723 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.h @@ -1,5 +1,5 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision @@ -14,52 +14,54 @@ extern "C" { extern void ui_Info_screen_init(void); extern void ui_Info_screen_destroy(void); extern void ui_event_Info(lv_event_t * e); -extern lv_obj_t *ui_Info; -extern lv_obj_t *ui_Panel_Info_Header; -extern lv_obj_t *ui_Label_Info_Header; -extern lv_obj_t *ui_Panel_Info_Content; -extern lv_obj_t *ui_Panel_Device; -extern lv_obj_t *ui_Label_Info_Device; -extern lv_obj_t *ui_Container_Info_Device; -extern lv_obj_t *ui_Info_Container4; -extern lv_obj_t *ui_Label_Info_MAC_Name; -extern lv_obj_t *ui_Label_Info_IP_Name; -extern lv_obj_t *ui_Info_Container5; -extern lv_obj_t *ui_Label_Info_MAC; -extern lv_obj_t *ui_Label_Info_IP; -extern lv_obj_t *ui_Panel_Battery; -extern lv_obj_t *ui_Label_Info_Battery; -extern lv_obj_t *ui_Container_Battery; -extern lv_obj_t *ui_Info_Container2; -extern lv_obj_t *ui_Label_Info_Battery_Status_Name; -extern lv_obj_t *ui_Label_Info_Battery_Voltage_Name; -extern lv_obj_t *ui_Label_Info_Battery_Remaining_Name; -extern lv_obj_t *ui_Info_Container3; -extern lv_obj_t *ui_Label_Info_Battery_Status; -extern lv_obj_t *ui_Label_Info_Battery_Voltage; -extern lv_obj_t *ui_Label_Info_Battery_Remaining; -extern lv_obj_t *ui_Info_Bar2; -extern lv_obj_t *ui_Panel_Lepton; -extern lv_obj_t *ui_Label_Info_Lepton; -extern lv_obj_t *ui_Container_Lepton; -extern lv_obj_t *ui_Info_Container1; -extern lv_obj_t *ui_Label_Info_Lepton_Serial_Name; -extern lv_obj_t *ui_Label_Info_Lepton_Part_Name; -extern lv_obj_t *ui_Label_Info_Lepton_Revision_Name; -extern lv_obj_t *ui_Label_Info_Lepton_Uptime_Name; -extern lv_obj_t *ui_Label_Info_Lepton_FPA_Name; -extern lv_obj_t *ui_Label_Info_Lepton_AUX_Name; -extern lv_obj_t *ui_Info_Container7; -extern lv_obj_t *ui_Label_Info_Lepton_Serial; -extern lv_obj_t *ui_Label_Info_Lepton_Part; -extern lv_obj_t *ui_Label_Info_Lepton_Revision; -extern lv_obj_t *ui_Label_Info_Lepton_Uptime; -extern lv_obj_t *ui_Label_Info_Lepton_FPA; -extern lv_obj_t *ui_Label_Info_Lepton_AUX; -extern lv_obj_t *ui_Container_Info_Buttons; +extern lv_obj_t * ui_Info; +extern lv_obj_t * ui_Panel_Info_Header; +extern lv_obj_t * ui_Label_Info_Header; +extern lv_obj_t * ui_Panel_Info_Content; +extern lv_obj_t * ui_Panel_Device; +extern lv_obj_t * ui_Label_Info_Device; +extern lv_obj_t * ui_Container_Info_Device; +extern lv_obj_t * ui_Info_Container4; +extern lv_obj_t * ui_Label_Info_MAC_Name; +extern lv_obj_t * ui_Label_Info_IP_Name; +extern lv_obj_t * ui_Label_Info_Serial_Name; +extern lv_obj_t * ui_Info_Container5; +extern lv_obj_t * ui_Label_Info_MAC; +extern lv_obj_t * ui_Label_Info_IP; +extern lv_obj_t * ui_Label_Info_Serial; +extern lv_obj_t * ui_Panel_Battery; +extern lv_obj_t * ui_Label_Info_Battery; +extern lv_obj_t * ui_Container_Battery; +extern lv_obj_t * ui_Info_Container2; +extern lv_obj_t * ui_Label_Info_Battery_Status_Name; +extern lv_obj_t * ui_Label_Info_Battery_Voltage_Name; +extern lv_obj_t * ui_Label_Info_Battery_Remaining_Name; +extern lv_obj_t * ui_Info_Container3; +extern lv_obj_t * ui_Label_Info_Battery_Status; +extern lv_obj_t * ui_Label_Info_Battery_Voltage; +extern lv_obj_t * ui_Label_Info_Battery_Remaining; +extern lv_obj_t * ui_Info_Bar2; +extern lv_obj_t * ui_Panel_Lepton; +extern lv_obj_t * ui_Label_Info_Lepton; +extern lv_obj_t * ui_Container_Lepton; +extern lv_obj_t * ui_Info_Container1; +extern lv_obj_t * ui_Label_Info_Lepton_Serial_Name; +extern lv_obj_t * ui_Label_Info_Lepton_Part_Name; +extern lv_obj_t * ui_Label_Info_Lepton_Revision_Name; +extern lv_obj_t * ui_Label_Info_Lepton_Uptime_Name; +extern lv_obj_t * ui_Label_Info_Lepton_FPA_Name; +extern lv_obj_t * ui_Label_Info_Lepton_AUX_Name; +extern lv_obj_t * ui_Info_Container7; +extern lv_obj_t * ui_Label_Info_Lepton_Serial; +extern lv_obj_t * ui_Label_Info_Lepton_Part; +extern lv_obj_t * ui_Label_Info_Lepton_Revision; +extern lv_obj_t * ui_Label_Info_Lepton_Uptime; +extern lv_obj_t * ui_Label_Info_Lepton_FPA; +extern lv_obj_t * ui_Label_Info_Lepton_AUX; +extern lv_obj_t * ui_Container_Info_Buttons; extern void ui_event_Button_Info_Back(lv_event_t * e); -extern lv_obj_t *ui_Button_Info_Back; -extern lv_obj_t *ui_Label_Info_Back; +extern lv_obj_t * ui_Button_Info_Back; +extern lv_obj_t * ui_Label_Info_Back; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.c b/main/Application/Tasks/GUI/Export/screens/ui_Main.c index 6768e31..9783889 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.c @@ -1,48 +1,47 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision #include "../ui.h" -lv_obj_t *ui_Main = NULL; -lv_obj_t *ui_Container_Main_StatusBar = NULL; -lv_obj_t *ui_Image_Main_WiFi = NULL; -lv_obj_t *ui_Image_Main_SDCard = NULL; -lv_obj_t *ui_Label_Main_Time = NULL; -lv_obj_t *ui_Image_Main_Battery = NULL; -lv_obj_t *ui_Label_Main_Battery_Remaining = NULL; -lv_obj_t *ui_Container_Main_Thermal = NULL; -lv_obj_t *ui_Image_Thermal = NULL; -lv_obj_t *ui_Image_Main_Thermal_Scene_ROI = NULL; -lv_obj_t *ui_Image_Main_Thermal_Spotmeter_ROI = NULL; -lv_obj_t *ui_Image_Main_Thermal_Video_Focus_ROI = NULL; -lv_obj_t *ui_Image_Main_Thermal_AGC_ROI = NULL; -lv_obj_t *ui_Label_Main_Thermal_Crosshair = NULL; -lv_obj_t *ui_Label_Main_Thermal_PixelTemperature = NULL; -lv_obj_t *ui_Container_Main_Thermal_Scene_Statistics = NULL; -lv_obj_t *ui_Label_Main_Thermal_Scene_Max = NULL; -lv_obj_t *ui_Label_Main_Thermal_Scene_Min = NULL; -lv_obj_t *ui_Label_Main_Thermal_Scene_Mean = NULL; -lv_obj_t *ui_Container_Gradient = NULL; -lv_obj_t *ui_Label_TempScaleMax = NULL; -lv_obj_t *ui_Image_Gradient = NULL; -lv_obj_t *ui_Label_TempScaleMin = NULL; -lv_obj_t *ui_Container_Main_Buttons = NULL; -lv_obj_t *ui_Button_Main_WiFi = NULL; -lv_obj_t *ui_Label_Main_Button_WiFi = NULL; -lv_obj_t *ui_Button_Main_ROI = NULL; -lv_obj_t *ui_Label_Main_Button_ROI = NULL; -lv_obj_t *ui_Button_Main_Info = NULL; -lv_obj_t *ui_Label_Main_Button_Info = NULL; -lv_obj_t *ui_Button_Main_Menu = NULL; -lv_obj_t *ui_Label_Main_Button_Menu = NULL; +lv_obj_t * ui_Main = NULL; +lv_obj_t * ui_Container_Main_StatusBar = NULL; +lv_obj_t * ui_Image_Main_WiFi = NULL; +lv_obj_t * ui_Image_Main_SDCard = NULL; +lv_obj_t * ui_Label_Main_Time = NULL; +lv_obj_t * ui_Label_Main_Battery_Remaining = NULL; +lv_obj_t * ui_Container_Main_Thermal = NULL; +lv_obj_t * ui_Image_Thermal = NULL; +lv_obj_t * ui_Image_Main_Thermal_Scene_ROI = NULL; +lv_obj_t * ui_Image_Main_Thermal_Spotmeter_ROI = NULL; +lv_obj_t * ui_Image_Main_Thermal_Video_Focus_ROI = NULL; +lv_obj_t * ui_Image_Main_Thermal_AGC_ROI = NULL; +lv_obj_t * ui_Label_Main_Thermal_Crosshair = NULL; +lv_obj_t * ui_Label_Main_Thermal_PixelTemperature = NULL; +lv_obj_t * ui_Container_Main_Thermal_Scene_Statistics = NULL; +lv_obj_t * ui_Label_Main_Thermal_Scene_Max = NULL; +lv_obj_t * ui_Label_Main_Thermal_Scene_Min = NULL; +lv_obj_t * ui_Label_Main_Thermal_Scene_Mean = NULL; +lv_obj_t * ui_Container_Gradient = NULL; +lv_obj_t * ui_Label_TempScaleMax = NULL; +lv_obj_t * ui_Image_Gradient = NULL; +lv_obj_t * ui_Label_TempScaleMin = NULL; +lv_obj_t * ui_Container_Main_Buttons = NULL; +lv_obj_t * ui_Button_Main_WiFi = NULL; +lv_obj_t * ui_Label_Main_Button_WiFi = NULL; +lv_obj_t * ui_Button_Main_ROI = NULL; +lv_obj_t * ui_Label_Main_Button_ROI = NULL; +lv_obj_t * ui_Button_Main_Info = NULL; +lv_obj_t * ui_Label_Main_Button_Info = NULL; +lv_obj_t * ui_Button_Main_Menu = NULL; +lv_obj_t * ui_Label_Main_Button_Menu = NULL; // event funtions void ui_event_Main(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if (event_code == LV_EVENT_SCREEN_LOADED) { + if(event_code == LV_EVENT_SCREEN_LOADED) { ScreenMainLoaded(e); } } @@ -51,7 +50,7 @@ void ui_event_Button_Main_WiFi(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if (event_code == LV_EVENT_CLICKED) { + if(event_code == LV_EVENT_CLICKED) { ButtonMainWiFiClicked(e); } } @@ -60,7 +59,7 @@ void ui_event_Button_Main_Info(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if (event_code == LV_EVENT_CLICKED) { + if(event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Info, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Info_screen_init); } } @@ -69,7 +68,7 @@ void ui_event_Button_Main_Menu(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if (event_code == LV_EVENT_CLICKED) { + if(event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Menu, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Menu_screen_init); } } @@ -136,23 +135,10 @@ void ui_Main_screen_init(void) lv_obj_set_style_text_opa(ui_Label_Main_Time, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_Label_Main_Time, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Image_Main_Battery = lv_label_create(ui_Container_Main_StatusBar); - lv_obj_set_width(ui_Image_Main_Battery, LV_SIZE_CONTENT); /// 1 - lv_obj_set_height(ui_Image_Main_Battery, LV_SIZE_CONTENT); /// 1 - lv_obj_set_x(ui_Image_Main_Battery, 260); - lv_obj_set_y(ui_Image_Main_Battery, 0); - lv_label_set_text(ui_Image_Main_Battery, "B"); - lv_obj_remove_flag(ui_Image_Main_Battery, - LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | - LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Image_Main_Battery, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_opa(ui_Image_Main_Battery, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Image_Main_Battery, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Label_Main_Battery_Remaining = lv_label_create(ui_Container_Main_StatusBar); lv_obj_set_width(ui_Label_Main_Battery_Remaining, LV_SIZE_CONTENT); /// 1 lv_obj_set_height(ui_Label_Main_Battery_Remaining, LV_SIZE_CONTENT); /// 1 - lv_obj_set_x(ui_Label_Main_Battery_Remaining, 290); + lv_obj_set_x(ui_Label_Main_Battery_Remaining, 280); lv_obj_set_y(ui_Label_Main_Battery_Remaining, 0); lv_label_set_text(ui_Label_Main_Battery_Remaining, "75%"); lv_obj_set_style_text_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -466,9 +452,7 @@ void ui_Main_screen_init(void) void ui_Main_screen_destroy(void) { - if (ui_Main) { - lv_obj_del(ui_Main); - } + if(ui_Main) lv_obj_del(ui_Main); // NULL screen variables ui_Main = NULL; @@ -476,7 +460,6 @@ void ui_Main_screen_destroy(void) ui_Image_Main_WiFi = NULL; ui_Image_Main_SDCard = NULL; ui_Label_Main_Time = NULL; - ui_Image_Main_Battery = NULL; ui_Label_Main_Battery_Remaining = NULL; ui_Container_Main_Thermal = NULL; ui_Image_Thermal = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.h b/main/Application/Tasks/GUI/Export/screens/ui_Main.h index 16a90ad..dd59eae 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.h @@ -1,5 +1,5 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision @@ -14,41 +14,40 @@ extern "C" { extern void ui_Main_screen_init(void); extern void ui_Main_screen_destroy(void); extern void ui_event_Main(lv_event_t * e); -extern lv_obj_t *ui_Main; -extern lv_obj_t *ui_Container_Main_StatusBar; -extern lv_obj_t *ui_Image_Main_WiFi; -extern lv_obj_t *ui_Image_Main_SDCard; -extern lv_obj_t *ui_Label_Main_Time; -extern lv_obj_t *ui_Image_Main_Battery; -extern lv_obj_t *ui_Label_Main_Battery_Remaining; -extern lv_obj_t *ui_Container_Main_Thermal; -extern lv_obj_t *ui_Image_Thermal; -extern lv_obj_t *ui_Image_Main_Thermal_Scene_ROI; -extern lv_obj_t *ui_Image_Main_Thermal_Spotmeter_ROI; -extern lv_obj_t *ui_Image_Main_Thermal_Video_Focus_ROI; -extern lv_obj_t *ui_Image_Main_Thermal_AGC_ROI; -extern lv_obj_t *ui_Label_Main_Thermal_Crosshair; -extern lv_obj_t *ui_Label_Main_Thermal_PixelTemperature; -extern lv_obj_t *ui_Container_Main_Thermal_Scene_Statistics; -extern lv_obj_t *ui_Label_Main_Thermal_Scene_Max; -extern lv_obj_t *ui_Label_Main_Thermal_Scene_Min; -extern lv_obj_t *ui_Label_Main_Thermal_Scene_Mean; -extern lv_obj_t *ui_Container_Gradient; -extern lv_obj_t *ui_Label_TempScaleMax; -extern lv_obj_t *ui_Image_Gradient; -extern lv_obj_t *ui_Label_TempScaleMin; -extern lv_obj_t *ui_Container_Main_Buttons; +extern lv_obj_t * ui_Main; +extern lv_obj_t * ui_Container_Main_StatusBar; +extern lv_obj_t * ui_Image_Main_WiFi; +extern lv_obj_t * ui_Image_Main_SDCard; +extern lv_obj_t * ui_Label_Main_Time; +extern lv_obj_t * ui_Label_Main_Battery_Remaining; +extern lv_obj_t * ui_Container_Main_Thermal; +extern lv_obj_t * ui_Image_Thermal; +extern lv_obj_t * ui_Image_Main_Thermal_Scene_ROI; +extern lv_obj_t * ui_Image_Main_Thermal_Spotmeter_ROI; +extern lv_obj_t * ui_Image_Main_Thermal_Video_Focus_ROI; +extern lv_obj_t * ui_Image_Main_Thermal_AGC_ROI; +extern lv_obj_t * ui_Label_Main_Thermal_Crosshair; +extern lv_obj_t * ui_Label_Main_Thermal_PixelTemperature; +extern lv_obj_t * ui_Container_Main_Thermal_Scene_Statistics; +extern lv_obj_t * ui_Label_Main_Thermal_Scene_Max; +extern lv_obj_t * ui_Label_Main_Thermal_Scene_Min; +extern lv_obj_t * ui_Label_Main_Thermal_Scene_Mean; +extern lv_obj_t * ui_Container_Gradient; +extern lv_obj_t * ui_Label_TempScaleMax; +extern lv_obj_t * ui_Image_Gradient; +extern lv_obj_t * ui_Label_TempScaleMin; +extern lv_obj_t * ui_Container_Main_Buttons; extern void ui_event_Button_Main_WiFi(lv_event_t * e); -extern lv_obj_t *ui_Button_Main_WiFi; -extern lv_obj_t *ui_Label_Main_Button_WiFi; -extern lv_obj_t *ui_Button_Main_ROI; -extern lv_obj_t *ui_Label_Main_Button_ROI; +extern lv_obj_t * ui_Button_Main_WiFi; +extern lv_obj_t * ui_Label_Main_Button_WiFi; +extern lv_obj_t * ui_Button_Main_ROI; +extern lv_obj_t * ui_Label_Main_Button_ROI; extern void ui_event_Button_Main_Info(lv_event_t * e); -extern lv_obj_t *ui_Button_Main_Info; -extern lv_obj_t *ui_Label_Main_Button_Info; +extern lv_obj_t * ui_Button_Main_Info; +extern lv_obj_t * ui_Label_Main_Button_Info; extern void ui_event_Button_Main_Menu(lv_event_t * e); -extern lv_obj_t *ui_Button_Main_Menu; -extern lv_obj_t *ui_Label_Main_Button_Menu; +extern lv_obj_t * ui_Button_Main_Menu; +extern lv_obj_t * ui_Label_Main_Button_Menu; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c index 99fbf8b..dd0fd48 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c @@ -1,27 +1,27 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision #include "../ui.h" -lv_obj_t *ui_Menu = NULL; -lv_obj_t *ui_Panel_Menu_Header = NULL; -lv_obj_t *ui_Label_Menu_Header = NULL; -lv_obj_t *ui_Container_Menu = NULL; -lv_obj_t *ui_Container_Menu_Buttons = NULL; -lv_obj_t *ui_Button_Menu_Back = NULL; -lv_obj_t *ui_Label_Menu_Back = NULL; +lv_obj_t * ui_Menu = NULL; +lv_obj_t * ui_Panel_Menu_Header = NULL; +lv_obj_t * ui_Label_Menu_Header = NULL; +lv_obj_t * ui_Container_Menu = NULL; +lv_obj_t * ui_Container_Menu_Buttons = NULL; +lv_obj_t * ui_Button_Menu_Back = NULL; +lv_obj_t * ui_Label_Menu_Back = NULL; // event funtions void ui_event_Menu(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if (event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { + if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { lv_indev_wait_release(lv_indev_active()); _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } - if (event_code == LV_EVENT_SCREEN_LOADED) { + if(event_code == LV_EVENT_SCREEN_LOADED) { ScreenMenuLoaded(e); } } @@ -30,7 +30,7 @@ void ui_event_Button_Menu_Back(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); - if (event_code == LV_EVENT_CLICKED) { + if(event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } } @@ -120,9 +120,7 @@ void ui_Menu_screen_init(void) void ui_Menu_screen_destroy(void) { - if (ui_Menu) { - lv_obj_del(ui_Menu); - } + if(ui_Menu) lv_obj_del(ui_Menu); // NULL screen variables ui_Menu = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h index 792175c..401fac7 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h @@ -1,5 +1,5 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision @@ -14,14 +14,14 @@ extern "C" { extern void ui_Menu_screen_init(void); extern void ui_Menu_screen_destroy(void); extern void ui_event_Menu(lv_event_t * e); -extern lv_obj_t *ui_Menu; -extern lv_obj_t *ui_Panel_Menu_Header; -extern lv_obj_t *ui_Label_Menu_Header; -extern lv_obj_t *ui_Container_Menu; -extern lv_obj_t *ui_Container_Menu_Buttons; +extern lv_obj_t * ui_Menu; +extern lv_obj_t * ui_Panel_Menu_Header; +extern lv_obj_t * ui_Label_Menu_Header; +extern lv_obj_t * ui_Container_Menu; +extern lv_obj_t * ui_Container_Menu_Buttons; extern void ui_event_Button_Menu_Back(lv_event_t * e); -extern lv_obj_t *ui_Button_Menu_Back; -extern lv_obj_t *ui_Label_Menu_Back; +extern lv_obj_t * ui_Button_Menu_Back; +extern lv_obj_t * ui_Label_Menu_Back; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c index 905944e..50bc123 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c @@ -1,17 +1,17 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision #include "../ui.h" -lv_obj_t *ui_Splash = NULL; -lv_obj_t *ui_SplashScreen_Logo = NULL; -lv_obj_t *ui_SplashScreen_LogoText = NULL; -lv_obj_t *ui_SplashScreen_Subtext = NULL; -lv_obj_t *ui_SplashScreen_LoadingBar = NULL; -lv_obj_t *ui_SplashScreen_StatusText = NULL; -lv_obj_t *ui_SplashScreen_FirmwareVersion = NULL; +lv_obj_t * ui_Splash = NULL; +lv_obj_t * ui_SplashScreen_Logo = NULL; +lv_obj_t * ui_SplashScreen_LogoText = NULL; +lv_obj_t * ui_SplashScreen_Subtext = NULL; +lv_obj_t * ui_SplashScreen_LoadingBar = NULL; +lv_obj_t * ui_SplashScreen_StatusText = NULL; +lv_obj_t * ui_SplashScreen_FirmwareVersion = NULL; // event funtions // build funtions @@ -77,9 +77,9 @@ void ui_Splash_screen_init(void) lv_obj_set_style_bg_opa(ui_SplashScreen_LoadingBar, 255, LV_PART_INDICATOR | LV_STATE_DEFAULT); //Compensating for LVGL9.1 draw crash with bar/slider max value when top-padding is nonzero and right-padding is 0 - if (lv_obj_get_style_pad_top(ui_SplashScreen_LoadingBar, - LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_SplashScreen_LoadingBar, - lv_obj_get_style_pad_right(ui_SplashScreen_LoadingBar, LV_PART_MAIN) + 1, LV_PART_MAIN); + if(lv_obj_get_style_pad_top(ui_SplashScreen_LoadingBar, + LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_SplashScreen_LoadingBar, + lv_obj_get_style_pad_right(ui_SplashScreen_LoadingBar, LV_PART_MAIN) + 1, LV_PART_MAIN); ui_SplashScreen_StatusText = lv_label_create(ui_Splash); lv_obj_set_width(ui_SplashScreen_StatusText, LV_SIZE_CONTENT); /// 1 lv_obj_set_height(ui_SplashScreen_StatusText, LV_SIZE_CONTENT); /// 1 @@ -113,9 +113,7 @@ void ui_Splash_screen_init(void) void ui_Splash_screen_destroy(void) { - if (ui_Splash) { - lv_obj_del(ui_Splash); - } + if(ui_Splash) lv_obj_del(ui_Splash); // NULL screen variables ui_Splash = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h index 6df951c..ee68e83 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h @@ -1,5 +1,5 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision @@ -13,13 +13,13 @@ extern "C" { // SCREEN: ui_Splash extern void ui_Splash_screen_init(void); extern void ui_Splash_screen_destroy(void); -extern lv_obj_t *ui_Splash; -extern lv_obj_t *ui_SplashScreen_Logo; -extern lv_obj_t *ui_SplashScreen_LogoText; -extern lv_obj_t *ui_SplashScreen_Subtext; -extern lv_obj_t *ui_SplashScreen_LoadingBar; -extern lv_obj_t *ui_SplashScreen_StatusText; -extern lv_obj_t *ui_SplashScreen_FirmwareVersion; +extern lv_obj_t * ui_Splash; +extern lv_obj_t * ui_SplashScreen_Logo; +extern lv_obj_t * ui_SplashScreen_LogoText; +extern lv_obj_t * ui_SplashScreen_Subtext; +extern lv_obj_t * ui_SplashScreen_LoadingBar; +extern lv_obj_t * ui_SplashScreen_StatusText; +extern lv_obj_t * ui_SplashScreen_FirmwareVersion; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/ui.c b/main/Application/Tasks/GUI/Export/ui.c index a1552e5..1783e2a 100644 --- a/main/Application/Tasks/GUI/Export/ui.c +++ b/main/Application/Tasks/GUI/Export/ui.c @@ -1,5 +1,5 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision @@ -9,13 +9,13 @@ ///////////////////// VARIABLES //////////////////// // EVENTS -lv_obj_t *ui____initial_actions0; +lv_obj_t * ui____initial_actions0; // IMAGES AND IMAGE SETS ///////////////////// TEST LVGL SETTINGS //////////////////// #if LV_COLOR_DEPTH != 16 -#error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" + #error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" #endif ///////////////////// ANIMATIONS //////////////////// @@ -26,9 +26,9 @@ lv_obj_t *ui____initial_actions0; void ui_init(void) { - lv_disp_t *dispp = lv_display_get_default(); - lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), - false, LV_FONT_DEFAULT); + lv_disp_t * dispp = lv_display_get_default(); + lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), + false, LV_FONT_DEFAULT); lv_disp_set_theme(dispp, theme); ui_Splash_screen_init(); ui_Main_screen_init(); diff --git a/main/Application/Tasks/GUI/Export/ui.h b/main/Application/Tasks/GUI/Export/ui.h index 284b65f..b974ddc 100644 --- a/main/Application/Tasks/GUI/Export/ui.h +++ b/main/Application/Tasks/GUI/Export/ui.h @@ -1,48 +1,48 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision - -#ifndef _PYROVISION_UI_H -#define _PYROVISION_UI_H -#ifdef __cplusplus +#ifndef _PYROVISION_UI_H +#define _PYROVISION_UI_H + +#ifdef __cplusplus extern "C" { - #endif - - #include "lvgl.h" - -#include "ui_helpers.h" -#include "ui_events.h" - - -///////////////////// SCREENS //////////////////// - -#include "screens/ui_Splash.h" -#include "screens/ui_Main.h" -#include "screens/ui_Menu.h" -#include "screens/ui_Info.h" - -///////////////////// VARIABLES //////////////////// - - -// EVENTS - -extern lv_obj_t *ui____initial_actions0; - -// IMAGES AND IMAGE SETS -LV_IMG_DECLARE(ui_img_logo_80x44_png); // assets/Logo_80x44.png -LV_IMG_DECLARE(ui_img_text_218x40_png); // assets/Text_218x40.png - -// FONTS -LV_FONT_DECLARE(ui_font_fa); - -// UI INIT -void ui_init(void); -void ui_destroy(void); - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif +#endif + +#include "lvgl.h" + +#include "ui_helpers.h" +#include "ui_events.h" + + +///////////////////// SCREENS //////////////////// + +#include "screens/ui_Splash.h" +#include "screens/ui_Main.h" +#include "screens/ui_Menu.h" +#include "screens/ui_Info.h" + +///////////////////// VARIABLES //////////////////// + + +// EVENTS + +extern lv_obj_t * ui____initial_actions0; + +// IMAGES AND IMAGE SETS +LV_IMG_DECLARE(ui_img_logo_80x44_png); // assets/Logo_80x44.png +LV_IMG_DECLARE(ui_img_text_218x40_png); // assets/Text_218x40.png + +// FONTS +LV_FONT_DECLARE(ui_font_fa); + +// UI INIT +void ui_init(void); +void ui_destroy(void); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/main/Application/Tasks/GUI/Export/ui_events.cpp b/main/Application/Tasks/GUI/Export/ui_events.cpp index bb90580..8b7a5bb 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.cpp +++ b/main/Application/Tasks/GUI/Export/ui_events.cpp @@ -21,7 +21,6 @@ void ScreenMainLoaded(lv_event_t *e) lv_label_set_text(ui_Image_Main_WiFi, LV_SYMBOL_WIFI); lv_label_set_text(ui_Image_Main_SDCard, LV_SYMBOL_SD_CARD); - lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_FULL); lv_label_set_text(ui_Label_Main_Button_Menu, "\uF0C9"); lv_label_set_text(ui_Label_Main_Button_Info, "\uF129"); diff --git a/main/Application/Tasks/GUI/Export/ui_events.h b/main/Application/Tasks/GUI/Export/ui_events.h index a0f98a5..7607b69 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.h +++ b/main/Application/Tasks/GUI/Export/ui_events.h @@ -1,5 +1,5 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision diff --git a/main/Application/Tasks/GUI/Export/ui_helpers.c b/main/Application/Tasks/GUI/Export/ui_helpers.c index 84a7df4..7e5ad39 100644 --- a/main/Application/Tasks/GUI/Export/ui_helpers.c +++ b/main/Application/Tasks/GUI/Export/ui_helpers.c @@ -1,5 +1,5 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision @@ -7,83 +7,63 @@ void _ui_bar_set_property(lv_obj_t * target, int id, int val) { - if (id == _UI_BAR_PROPERTY_VALUE_WITH_ANIM) { - lv_bar_set_value(target, val, LV_ANIM_ON); - } - if (id == _UI_BAR_PROPERTY_VALUE) { - lv_bar_set_value(target, val, LV_ANIM_OFF); - } + if(id == _UI_BAR_PROPERTY_VALUE_WITH_ANIM) lv_bar_set_value(target, val, LV_ANIM_ON); + if(id == _UI_BAR_PROPERTY_VALUE) lv_bar_set_value(target, val, LV_ANIM_OFF); } void _ui_basic_set_property(lv_obj_t * target, int id, int val) { - if (id == _UI_BASIC_PROPERTY_POSITION_X) { - lv_obj_set_x(target, val); - } - if (id == _UI_BASIC_PROPERTY_POSITION_Y) { - lv_obj_set_y(target, val); - } - if (id == _UI_BASIC_PROPERTY_WIDTH) { - lv_obj_set_width(target, val); - } - if (id == _UI_BASIC_PROPERTY_HEIGHT) { - lv_obj_set_height(target, val); - } + if(id == _UI_BASIC_PROPERTY_POSITION_X) lv_obj_set_x(target, val); + if(id == _UI_BASIC_PROPERTY_POSITION_Y) lv_obj_set_y(target, val); + if(id == _UI_BASIC_PROPERTY_WIDTH) lv_obj_set_width(target, val); + if(id == _UI_BASIC_PROPERTY_HEIGHT) lv_obj_set_height(target, val); } void _ui_dropdown_set_property(lv_obj_t * target, int id, int val) { - if (id == _UI_DROPDOWN_PROPERTY_SELECTED) { - lv_dropdown_set_selected(target, val); - } + if(id == _UI_DROPDOWN_PROPERTY_SELECTED) lv_dropdown_set_selected(target, val); } void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val) { - if (id == _UI_IMAGE_PROPERTY_IMAGE) { - lv_image_set_src(target, val); - } + if(id == _UI_IMAGE_PROPERTY_IMAGE) lv_image_set_src(target, val); } void _ui_label_set_property(lv_obj_t * target, int id, const char * val) { - if (id == _UI_LABEL_PROPERTY_TEXT) { - lv_label_set_text(target, val); - } + if(id == _UI_LABEL_PROPERTY_TEXT) lv_label_set_text(target, val); } void _ui_roller_set_property(lv_obj_t * target, int id, int val) { - if (id == _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM) { - lv_roller_set_selected(target, val, LV_ANIM_ON); - } - if (id == _UI_ROLLER_PROPERTY_SELECTED) { - lv_roller_set_selected(target, val, LV_ANIM_OFF); - } + if(id == _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM) lv_roller_set_selected(target, val, LV_ANIM_ON); + if(id == _UI_ROLLER_PROPERTY_SELECTED) lv_roller_set_selected(target, val, LV_ANIM_OFF); } void _ui_slider_set_property(lv_obj_t * target, int id, int val) { - if (id == _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM) { - lv_slider_set_value(target, val, LV_ANIM_ON); - } - if (id == _UI_SLIDER_PROPERTY_VALUE) { - lv_slider_set_value(target, val, LV_ANIM_OFF); - } + if(id == _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM) lv_slider_set_value(target, val, LV_ANIM_ON); + if(id == _UI_SLIDER_PROPERTY_VALUE) lv_slider_set_value(target, val, LV_ANIM_OFF); } void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, void (*target_init)(void)) { - if (*target == NULL) { + if(*target == NULL) target_init(); - } lv_screen_load_anim(*target, fademode, spd, delay, false); } +void _ui_screen_delete(void (*target)(void)) +{ + if(target != NULL) { + target(); + } +} + void _ui_arc_increment(lv_obj_t * target, int val) { int old = lv_arc_get_value(target); @@ -111,31 +91,21 @@ void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea) void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value) { - if (value == _UI_MODIFY_FLAG_TOGGLE) { - if (lv_obj_has_flag(target, flag)) { - lv_obj_remove_flag(target, flag); - } else { - lv_obj_add_flag(target, flag); - } - } else if (value == _UI_MODIFY_FLAG_ADD) { - lv_obj_add_flag(target, flag); - } else { - lv_obj_remove_flag(target, flag); + if(value == _UI_MODIFY_FLAG_TOGGLE) { + if(lv_obj_has_flag(target, flag)) lv_obj_remove_flag(target, flag); + else lv_obj_add_flag(target, flag); } + else if(value == _UI_MODIFY_FLAG_ADD) lv_obj_add_flag(target, flag); + else lv_obj_remove_flag(target, flag); } void _ui_state_modify(lv_obj_t * target, int32_t state, int value) { - if (value == _UI_MODIFY_STATE_TOGGLE) { - if (lv_obj_has_state(target, state)) { - lv_obj_remove_state(target, state); - } else { - lv_obj_add_state(target, state); - } - } else if (value == _UI_MODIFY_STATE_ADD) { - lv_obj_add_state(target, state); - } else { - lv_obj_remove_state(target, state); + if(value == _UI_MODIFY_STATE_TOGGLE) { + if(lv_obj_has_state(target, state)) lv_obj_remove_state(target, state); + else lv_obj_add_state(target, state); } + else if(value == _UI_MODIFY_STATE_ADD) lv_obj_add_state(target, state); + else lv_obj_remove_state(target, state); } @@ -143,18 +113,10 @@ void _ui_textarea_move_cursor(lv_obj_t * target, int val) { - if (val == UI_MOVE_CURSOR_UP) { - lv_textarea_cursor_up(target); - } - if (val == UI_MOVE_CURSOR_RIGHT) { - lv_textarea_cursor_right(target); - } - if (val == UI_MOVE_CURSOR_DOWN) { - lv_textarea_cursor_down(target); - } - if (val == UI_MOVE_CURSOR_LEFT) { - lv_textarea_cursor_left(target); - } + if(val == UI_MOVE_CURSOR_UP) lv_textarea_cursor_up(target); + if(val == UI_MOVE_CURSOR_RIGHT) lv_textarea_cursor_right(target); + if(val == UI_MOVE_CURSOR_DOWN) lv_textarea_cursor_down(target); + if(val == UI_MOVE_CURSOR_LEFT) lv_textarea_cursor_left(target); lv_obj_add_state(target, LV_STATE_FOCUSED); } @@ -167,7 +129,7 @@ void scr_unloaded_delete_cb(lv_event_t * e) // Get the destroy callback from user_data screen_destroy_cb_t destroy_cb = lv_event_get_user_data(e); - if (destroy_cb) { + if(destroy_cb) { destroy_cb(); // call the specific screen destroy function @@ -190,7 +152,7 @@ void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_x(usr->target, v); } @@ -200,7 +162,7 @@ void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_y(usr->target, v); } @@ -210,7 +172,7 @@ void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_width(usr->target, v); } @@ -220,7 +182,7 @@ void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_height(usr->target, v); } @@ -230,7 +192,7 @@ void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_style_opa(usr->target, v, 0); } @@ -240,7 +202,7 @@ void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; lv_image_set_scale(usr->target, v); } @@ -250,7 +212,7 @@ void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; lv_image_set_rotation(usr->target, v); } @@ -260,15 +222,11 @@ void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; usr->val = v; - if (v < 0) { - v = 0; - } - if (v >= usr->imgset_size) { - v = usr->imgset_size - 1; - } + if(v < 0) v = 0; + if(v >= usr->imgset_size) v = usr->imgset_size - 1; lv_image_set_src(usr->target, usr->imgset[v]); } @@ -276,7 +234,7 @@ int32_t _ui_anim_callback_get_x(lv_anim_t * a) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_x_aligned(usr->target); } @@ -286,7 +244,7 @@ int32_t _ui_anim_callback_get_y(lv_anim_t * a) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_y_aligned(usr->target); } @@ -296,7 +254,7 @@ int32_t _ui_anim_callback_get_width(lv_anim_t * a) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_width(usr->target); } @@ -306,7 +264,7 @@ int32_t _ui_anim_callback_get_height(lv_anim_t * a) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_height(usr->target); } @@ -316,7 +274,7 @@ int32_t _ui_anim_callback_get_opacity(lv_anim_t * a) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_style_opa(usr->target, 0); } @@ -325,7 +283,7 @@ int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; return lv_image_get_scale(usr->target); } @@ -334,7 +292,7 @@ int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; return lv_image_get_rotation(usr->target); } @@ -343,7 +301,7 @@ int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a) { - ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; return usr->val; } @@ -367,11 +325,8 @@ void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * pref } void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off) { - if (lv_obj_has_state(src, LV_STATE_CHECKED)) { - lv_label_set_text(trg, txt_on); - } else { - lv_label_set_text(trg, txt_off); - } + if(lv_obj_has_state(src, LV_STATE_CHECKED)) lv_label_set_text(trg, txt_on); + else lv_label_set_text(trg, txt_off); } @@ -379,13 +334,9 @@ void _ui_spinbox_step(lv_obj_t * target, int val) { - if (val > 0) { - lv_spinbox_increment(target); - } + if(val > 0) lv_spinbox_increment(target); - else { - lv_spinbox_decrement(target); - } + else lv_spinbox_decrement(target); lv_obj_send_event(target, LV_EVENT_VALUE_CHANGED, 0); diff --git a/main/Application/Tasks/GUI/Export/ui_helpers.h b/main/Application/Tasks/GUI/Export/ui_helpers.h index 45374ca..cf49380 100644 --- a/main/Application/Tasks/GUI/Export/ui_helpers.h +++ b/main/Application/Tasks/GUI/Export/ui_helpers.h @@ -1,147 +1,149 @@ // This file was generated by SquareLine Studio -// SquareLine Studio version: SquareLine Studio 1.5.4 +// SquareLine Studio version: SquareLine Studio 1.6.0 // LVGL version: 9.1.0 // Project name: PyroVision - -#ifndef _PYROVISION_UI_HELPERS_H -#define _PYROVISION_UI_HELPERS_H -#ifdef __cplusplus +#ifndef _PYROVISION_UI_HELPERS_H +#define _PYROVISION_UI_HELPERS_H + +#ifdef __cplusplus extern "C" { - #endif - - #include "ui.h" - -#define _UI_TEMPORARY_STRING_BUFFER_SIZE 32 -#define _UI_BAR_PROPERTY_VALUE 0 -#define _UI_BAR_PROPERTY_VALUE_WITH_ANIM 1 -void _ui_bar_set_property(lv_obj_t * target, int id, int val); - -#define _UI_BASIC_PROPERTY_POSITION_X 0 -#define _UI_BASIC_PROPERTY_POSITION_Y 1 -#define _UI_BASIC_PROPERTY_WIDTH 2 -#define _UI_BASIC_PROPERTY_HEIGHT 3 -void _ui_basic_set_property(lv_obj_t * target, int id, int val); - -#define _UI_DROPDOWN_PROPERTY_SELECTED 0 -void _ui_dropdown_set_property(lv_obj_t * target, int id, int val); - -#define _UI_IMAGE_PROPERTY_IMAGE 0 -void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val); - -#define _UI_LABEL_PROPERTY_TEXT 0 -void _ui_label_set_property(lv_obj_t * target, int id, const char * val); - -#define _UI_ROLLER_PROPERTY_SELECTED 0 -#define _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM 1 -void _ui_roller_set_property(lv_obj_t * target, int id, int val); - -#define _UI_SLIDER_PROPERTY_VALUE 0 -#define _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM 1 -void _ui_slider_set_property(lv_obj_t * target, int id, int val); - -void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, - void (*target_init)(void)); - -void _ui_arc_increment(lv_obj_t * target, int val); - -void _ui_bar_increment(lv_obj_t * target, int val, int anm); - -void _ui_slider_increment(lv_obj_t * target, int val, int anm); - -void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea); - -#define _UI_MODIFY_FLAG_ADD 0 -#define _UI_MODIFY_FLAG_REMOVE 1 -#define _UI_MODIFY_FLAG_TOGGLE 2 -void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value); - -#define _UI_MODIFY_STATE_ADD 0 -#define _UI_MODIFY_STATE_REMOVE 1 -#define _UI_MODIFY_STATE_TOGGLE 2 -void _ui_state_modify(lv_obj_t * target, int32_t state, int value); - -#define UI_MOVE_CURSOR_UP 0 -#define UI_MOVE_CURSOR_RIGHT 1 -#define UI_MOVE_CURSOR_DOWN 2 -#define UI_MOVE_CURSOR_LEFT 3 -void _ui_textarea_move_cursor(lv_obj_t * target, int val) -; - - -void scr_unloaded_delete_cb(lv_event_t * e); - -void _ui_opacity_set(lv_obj_t * target, int val); - -/** Describes an animation*/ -typedef struct _ui_anim_user_data_t { - lv_obj_t *target; - lv_image_dsc_t **imgset; - int32_t imgset_size; - int32_t val; -} ui_anim_user_data_t; -void _ui_anim_callback_free_user_data(lv_anim_t * a); - -void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v); - -void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v); - -void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v); - -void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v); - - -void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v); - - -void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v); - - -void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v); - - -void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v); - - -int32_t _ui_anim_callback_get_x(lv_anim_t * a); - -int32_t _ui_anim_callback_get_y(lv_anim_t * a); - -int32_t _ui_anim_callback_get_width(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_height(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_opacity(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a); - - -int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a); - - -void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); - -void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); - -void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off); - -void _ui_spinbox_step(lv_obj_t * target, int val) -; - - -void _ui_switch_theme(int val) -; - - - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif +#endif + +#include "ui.h" + +#define _UI_TEMPORARY_STRING_BUFFER_SIZE 32 +#define _UI_BAR_PROPERTY_VALUE 0 +#define _UI_BAR_PROPERTY_VALUE_WITH_ANIM 1 +void _ui_bar_set_property(lv_obj_t * target, int id, int val); + +#define _UI_BASIC_PROPERTY_POSITION_X 0 +#define _UI_BASIC_PROPERTY_POSITION_Y 1 +#define _UI_BASIC_PROPERTY_WIDTH 2 +#define _UI_BASIC_PROPERTY_HEIGHT 3 +void _ui_basic_set_property(lv_obj_t * target, int id, int val); + +#define _UI_DROPDOWN_PROPERTY_SELECTED 0 +void _ui_dropdown_set_property(lv_obj_t * target, int id, int val); + +#define _UI_IMAGE_PROPERTY_IMAGE 0 +void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val); + +#define _UI_LABEL_PROPERTY_TEXT 0 +void _ui_label_set_property(lv_obj_t * target, int id, const char * val); + +#define _UI_ROLLER_PROPERTY_SELECTED 0 +#define _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM 1 +void _ui_roller_set_property(lv_obj_t * target, int id, int val); + +#define _UI_SLIDER_PROPERTY_VALUE 0 +#define _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM 1 +void _ui_slider_set_property(lv_obj_t * target, int id, int val); + +void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, + void (*target_init)(void)); + +void _ui_screen_delete(void (*target)(void)); + +void _ui_arc_increment(lv_obj_t * target, int val); + +void _ui_bar_increment(lv_obj_t * target, int val, int anm); + +void _ui_slider_increment(lv_obj_t * target, int val, int anm); + +void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea); + +#define _UI_MODIFY_FLAG_ADD 0 +#define _UI_MODIFY_FLAG_REMOVE 1 +#define _UI_MODIFY_FLAG_TOGGLE 2 +void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value); + +#define _UI_MODIFY_STATE_ADD 0 +#define _UI_MODIFY_STATE_REMOVE 1 +#define _UI_MODIFY_STATE_TOGGLE 2 +void _ui_state_modify(lv_obj_t * target, int32_t state, int value); + +#define UI_MOVE_CURSOR_UP 0 +#define UI_MOVE_CURSOR_RIGHT 1 +#define UI_MOVE_CURSOR_DOWN 2 +#define UI_MOVE_CURSOR_LEFT 3 +void _ui_textarea_move_cursor(lv_obj_t * target, int val) +; + + +void scr_unloaded_delete_cb(lv_event_t * e); + +void _ui_opacity_set(lv_obj_t * target, int val); + +/** Describes an animation*/ +typedef struct _ui_anim_user_data_t { + lv_obj_t * target; + lv_image_dsc_t ** imgset; + int32_t imgset_size; + int32_t val; +} ui_anim_user_data_t; +void _ui_anim_callback_free_user_data(lv_anim_t * a); + +void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v); + +void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v); + + +void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v); + + +int32_t _ui_anim_callback_get_x(lv_anim_t * a); + +int32_t _ui_anim_callback_get_y(lv_anim_t * a); + +int32_t _ui_anim_callback_get_width(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_height(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_opacity(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a); + + +int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a); + + +void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); + +void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); + +void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off); + +void _ui_spinbox_step(lv_obj_t * target, int val) +; + + +void _ui_switch_theme(int val) +; + + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/main/Application/Tasks/GUI/Private/guiHelper.cpp b/main/Application/Tasks/GUI/Private/guiHelper.cpp index e3eef3d..c3a27bd 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.cpp +++ b/main/Application/Tasks/GUI/Private/guiHelper.cpp @@ -27,6 +27,14 @@ #include "Application/application.h" #include "../Export/ui.h" +#if defined(CONFIG_TOUCH_I2C0_HOST) +#define TOUCH_I2C_HOST I2C_NUM_0 +#elif defined(CONFIG_TOUCH_I2C1_HOST) +#define TOUCH_I2C_HOST I2C_NUM_1 +#else +#error "No I2C host defined for Touch!" +#endif + #if defined(CONFIG_LCD_SPI2_HOST) #define LCD_SPI_HOST SPI2_HOST #elif defined(CONFIG_LCD_SPI3_HOST) @@ -37,9 +45,14 @@ #define GUI_DRAW_BUFFER_SIZE (CONFIG_GUI_WIDTH * CONFIG_GUI_HEIGHT * sizeof(uint16_t) / 10) +static const esp_lcd_panel_io_callbacks_t _GUI_Panel_Callbacks = { + .on_color_trans_done = NULL, +}; + static const esp_lcd_panel_dev_config_t _GUI_Panel_Config = { .reset_gpio_num = CONFIG_LCD_RST, .color_space = ESP_LCD_COLOR_SPACE_BGR, + .data_endian = LCD_RGB_DATA_ENDIAN_BIG, .bits_per_pixel = 16, .flags = { .reset_active_high = 0, @@ -47,7 +60,7 @@ static const esp_lcd_panel_dev_config_t _GUI_Panel_Config = { .vendor_config = NULL, }; -static esp_lcd_panel_io_spi_config_t _GUI_Panel_IO_Config = { +static const esp_lcd_panel_io_spi_config_t _GUI_Panel_IO_Config = { .cs_gpio_num = CONFIG_LCD_CS, .dc_gpio_num = CONFIG_LCD_DC, .spi_mode = 0, @@ -57,39 +70,88 @@ static esp_lcd_panel_io_spi_config_t _GUI_Panel_IO_Config = { .user_ctx = NULL, .lcd_cmd_bits = 8, .lcd_param_bits = 8, + .cs_ena_pretrans = 0, + .cs_ena_posttrans = 0, .flags = { + .dc_high_on_cmd = 0, .dc_low_on_data = 0, + .dc_low_on_param = 0, .octal_mode = 0, + .quad_mode = 0, .sio_mode = 0, .lsb_first = 0, - .cs_high_active = 0, + .cs_high_active = 0 + }, +}; + +static const i2c_master_bus_config_t _GUI_Touch_I2C_Config = { + .i2c_port = TOUCH_I2C_HOST, + .sda_io_num = static_cast(CONFIG_TOUCH_SDA), + .scl_io_num = static_cast(CONFIG_TOUCH_SCL), + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .intr_priority = 0, + .trans_queue_depth = 0, + .flags = { + .enable_internal_pullup = true, + .allow_pd = false, + }, +}; + +static const esp_lcd_panel_io_i2c_config_t _GUI_Touch_IO_Config = { +#if((CONFIG_TOUCH_IRQ != -1) && (CONFIG_TOUCH_RST != -1)) + .dev_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS, +#else + .dev_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP, +#endif + .on_color_trans_done = NULL, + .user_ctx = NULL, + .control_phase_bytes = 1, + .dc_bit_offset = 0, + .lcd_cmd_bits = 16, + .lcd_param_bits = 0, + .flags = + { + .dc_low_on_data = 0, + .disable_control_phase = 1, }, + .scl_speed_hz = 400000, +}; + +static esp_lcd_touch_io_gt911_config_t _GUI_Touch_GT911_Config = { + .dev_addr = static_cast(_GUI_Touch_IO_Config.dev_addr), }; -static esp_lcd_touch_config_t _GUI_Touch_Config = { +static const esp_lcd_touch_config_t _GUI_Touch_Config = { .x_max = CONFIG_GUI_WIDTH, .y_max = CONFIG_GUI_HEIGHT, .rst_gpio_num = static_cast(CONFIG_TOUCH_RST), .int_gpio_num = static_cast(CONFIG_TOUCH_IRQ), + .levels = { + .reset = 0, + .interrupt = 0, + }, .flags = { - .swap_xy = 0, + .swap_xy = 1, .mirror_x = 0, .mirror_y = 0, }, + .process_coordinates = NULL, + .interrupt_callback = NULL, + .user_data = NULL, + .driver_data = &_GUI_Touch_GT911_Config, }; -static esp_lcd_panel_io_spi_config_t _GUI_Touch_IO_Config = ESP_LCD_TOUCH_IO_SPI_XPT2046_CONFIG(CONFIG_TOUCH_CS); - static const char *TAG = "gui_helper"; -static void GUI_LVGL_TickTimer_CB(void *p_Arg) +inline void GUI_LVGL_TickTimer_CB(void *p_Arg) { lv_tick_inc(CONFIG_GUI_LVGL_TICK_PERIOD_MS); } static void GUI_LCD_Flush_CB(lv_display_t *p_Disp, const lv_area_t *p_Area, uint8_t *p_PxMap) { - esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)lv_display_get_user_data(p_Disp); + esp_lcd_panel_handle_t panel_handle = static_cast(lv_display_get_user_data(p_Disp)); int offsetx1 = p_Area->x1; int offsetx2 = p_Area->x2; @@ -103,7 +165,8 @@ static void GUI_LCD_Flush_CB(lv_display_t *p_Disp, const lv_area_t *p_Area, uint esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t Touch_Read_Callback) { -#if CONFIG_LCD_BL >= 0 +#if (CONFIG_LCD_BL != -1) + ESP_LOGI(TAG, "Configure LCD backlight GPIO..."); gpio_config_t bk_gpio_config = { .pin_bit_mask = 1ULL << CONFIG_LCD_BL, .mode = GPIO_MODE_OUTPUT, @@ -115,45 +178,50 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t gpio_set_level(static_cast(CONFIG_LCD_BL), LCD_BK_LIGHT_ON_LEVEL); #endif - _GUI_Panel_IO_Config.on_color_trans_done = NULL; + ESP_LOGI(TAG, "Create I2C bus for touch controller..."); + i2c_new_master_bus(&_GUI_Touch_I2C_Config, &p_GUITask_State->Touch_Bus_Handle); + + ESP_LOGI(TAG, "Create panel IO..."); ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(static_cast(LCD_SPI_HOST), &_GUI_Panel_IO_Config, &p_GUITask_State->Panel_IO_Handle)); - ESP_LOGD(TAG, "SPI panel IO created"); + ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(p_GUITask_State->Touch_Bus_Handle, &_GUI_Touch_IO_Config, + &p_GUITask_State->Touch_IO_Handle)); - ESP_LOGD(TAG, "Initialize LVGL library"); + ESP_LOGI(TAG, "Initialize LVGL library and display..."); lv_init(); - - /* Initialize LVGL display first (needed for callback) */ p_GUITask_State->Display = lv_display_create(CONFIG_GUI_WIDTH, CONFIG_GUI_HEIGHT); - ESP_LOGD(TAG, "LVGL display object created"); - /* Register event callbacks BEFORE installing panel driver */ - esp_lcd_panel_io_callbacks_t cbs = { - .on_color_trans_done = NULL, - }; - ESP_ERROR_CHECK(esp_lcd_panel_io_register_event_callbacks(p_GUITask_State->Panel_IO_Handle, &cbs, + ESP_LOGI(TAG, "Register LCD panel IO callbacks..."); + ESP_ERROR_CHECK(esp_lcd_panel_io_register_event_callbacks(p_GUITask_State->Panel_IO_Handle, &_GUI_Panel_Callbacks, p_GUITask_State->Display)); - ESP_LOGD(TAG, "LCD panel IO callbacks registered"); + + ESP_LOGI(TAG, "Install ILI9341 panel driver..."); ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(p_GUITask_State->Panel_IO_Handle, &_GUI_Panel_Config, &p_GUITask_State->PanelHandle)); - ESP_LOGD(TAG, "ILI9341 panel driver installed"); + ESP_LOGD(TAG, " ILI9341 panel driver installed"); + + ESP_LOGD(TAG, "Reset the panel..."); ESP_ERROR_CHECK(esp_lcd_panel_reset(p_GUITask_State->PanelHandle)); - ESP_LOGD(TAG, "Panel reset complete"); vTaskDelay(100 / portTICK_PERIOD_MS); + ESP_LOGD(TAG, " Panel reset complete"); + + ESP_LOGI(TAG, "Initialize the panel..."); ESP_ERROR_CHECK(esp_lcd_panel_init(p_GUITask_State->PanelHandle)); - ESP_LOGD(TAG, "Panel initialized"); vTaskDelay(100 / portTICK_PERIOD_MS); + ESP_LOGD(TAG, " Panel initialized"); - /* Set to landscape mode (320x240) - swap width and height */ + ESP_LOGI(TAG, "Configure panel for landscape mode..."); ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(p_GUITask_State->PanelHandle, true)); - ESP_LOGD(TAG, "Panel swap_xy enabled for landscape"); + ESP_LOGD(TAG, " Panel swap_xy enabled for landscape"); - /* 180 degree rotation: mirror both X and Y */ + ESP_LOGI(TAG, "Configure panel mirroring..."); ESP_ERROR_CHECK(esp_lcd_panel_mirror(p_GUITask_State->PanelHandle, true, true)); - ESP_LOGD(TAG, "Panel mirroring configured (180 degree rotation)"); + ESP_LOGD(TAG, " Panel mirroring configured (180 degree rotation)"); + + ESP_LOGI(TAG, "Turn ON the panel display..."); ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(p_GUITask_State->PanelHandle, true)); - ESP_LOGD(TAG, "Panel display turned ON"); vTaskDelay(100 / portTICK_PERIOD_MS); + ESP_LOGD(TAG, " Panel display turned ON"); /* Set LVGL display properties */ lv_display_set_flush_cb(p_GUITask_State->Display, GUI_LCD_Flush_CB); @@ -161,7 +229,6 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t p_GUITask_State->PanelHandle); /* Note: Color format set to RGB565 by default, matching thermal image BGR565 conversion */ - /* Allocate draw buffers in PSRAM */ p_GUITask_State->DisplayBuffer1 = heap_caps_malloc(GUI_DRAW_BUFFER_SIZE, MALLOC_CAP_SPIRAM); p_GUITask_State->DisplayBuffer2 = heap_caps_malloc(GUI_DRAW_BUFFER_SIZE, MALLOC_CAP_SPIRAM); ESP_LOGD(TAG, "Allocated LVGL buffers: %d bytes each in PSRAM", GUI_DRAW_BUFFER_SIZE); @@ -174,19 +241,10 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t p_GUITask_State->DisplayBuffer2, GUI_DRAW_BUFFER_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL); - ESP_LOGD(TAG, "LVGL display buffers configured"); - p_GUITask_State->EventGroup = xEventGroupCreate(); - if (p_GUITask_State->EventGroup == NULL) { - ESP_LOGE(TAG, "Failed to create GUI event group!"); - return ESP_ERR_NO_MEM; - } - - ESP_LOGD(TAG, "Initialize touch controller XPT2046"); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(static_cast(LCD_SPI_HOST), &_GUI_Touch_IO_Config, - &p_GUITask_State->Touch_IO_Handle)); - ESP_ERROR_CHECK(esp_lcd_touch_new_spi_xpt2046(p_GUITask_State->Touch_IO_Handle, &_GUI_Touch_Config, - &p_GUITask_State->TouchHandle)); + ESP_LOGD(TAG, "Initialize GT911 touch controller..."); + ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(p_GUITask_State->Touch_IO_Handle, &_GUI_Touch_Config, + &p_GUITask_State->TouchHandle)); /* Register touchpad input device */ ESP_LOGD(TAG, "Register touch input device to LVGL"); @@ -205,6 +263,12 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t .skip_unhandled_events = false, }; + p_GUITask_State->EventGroup = xEventGroupCreate(); + if (p_GUITask_State->EventGroup == NULL) { + ESP_LOGE(TAG, "Failed to create GUI event group!"); + return ESP_ERR_NO_MEM; + } + ESP_ERROR_CHECK(esp_timer_create(&LVGL_TickTimer_args, &p_GUITask_State->LVGL_TickTimer)); ESP_ERROR_CHECK(esp_timer_start_periodic(p_GUITask_State->LVGL_TickTimer, CONFIG_GUI_LVGL_TICK_PERIOD_MS * 1000)); diff --git a/main/Application/Tasks/GUI/Private/guiHelper.h b/main/Application/Tasks/GUI/Private/guiHelper.h index 7d8548e..f1d45ce 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.h +++ b/main/Application/Tasks/GUI/Private/guiHelper.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include @@ -51,6 +51,7 @@ #define LEPTON_TEMP_READY BIT12 #define LEPTON_PIXEL_TEMPERATURE_READY BIT13 #define LEPTON_CAMERA_READY BIT4 +#define LEPTON_CAMERA_ERROR BIT14 #define LEPTON_SPOTMETER_READY BIT5 #define LEPTON_SCENE_STATISTICS_READY BIT6 @@ -65,6 +66,7 @@ typedef struct { TaskHandle_t GUI_Handle; void *DisplayBuffer1; void *DisplayBuffer2; + i2c_master_bus_handle_t Touch_Bus_Handle; esp_timer_handle_t LVGL_TickTimer; esp_lcd_panel_handle_t PanelHandle; esp_lcd_touch_handle_t TouchHandle; diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp index ebc56d4..2cd4035 100644 --- a/main/Application/Tasks/GUI/guiTask.cpp +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -246,6 +246,8 @@ static void on_Lepton_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, break; } case LEPTON_EVENT_CAMERA_ERROR: { + xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_CAMERA_ERROR); + break; } case LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP: { @@ -453,34 +455,27 @@ static void UI_Canvas_AddTempGradient(void) } } -/** @brief LVGL touch read callback for XPT2046 touch controller. +/** @brief LVGL touch read callback. + * @param p_Indev Input device handle + * @param p_Data Input device data */ -static void XPT2046_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data) +static void Touch_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data) { uint8_t Count = 0; esp_lcd_touch_point_data_t Data[1]; esp_lcd_touch_handle_t Touch; - esp_err_t Error; Touch = (esp_lcd_touch_handle_t)lv_indev_get_user_data(p_Indev); esp_lcd_touch_read_data(Touch); - Error = esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])); - - if ((Error == ESP_OK) && (Count > 0)) { - uint16_t raw_x = Data[0].x; - uint16_t raw_y = Data[0].y; + if ((esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])) == ESP_OK) && (Count > 0)) { + p_Data->point.x = CONFIG_GUI_WIDTH - Data[0].x; + p_Data->point.y = Data[0].y; - /* Clamp raw values to calibrated range */ - int16_t clamped_x = (raw_x < TOUCH_RAW_X_MIN) ? TOUCH_RAW_X_MIN : (raw_x > TOUCH_RAW_X_MAX) ? TOUCH_RAW_X_MAX : raw_x; - int16_t clamped_y = (raw_y < TOUCH_RAW_Y_MIN) ? TOUCH_RAW_Y_MIN : (raw_y > TOUCH_RAW_Y_MAX) ? TOUCH_RAW_Y_MAX : raw_y; - - /* Swap axes and scale: Display X from Raw Y, Display Y from Raw X */ - p_Data->point.x = (clamped_y - TOUCH_RAW_Y_MIN) * (CONFIG_GUI_WIDTH - 1) / (TOUCH_RAW_Y_MAX - TOUCH_RAW_Y_MIN); - p_Data->point.y = (clamped_x - TOUCH_RAW_X_MIN) * (CONFIG_GUI_HEIGHT - 1) / (TOUCH_RAW_X_MAX - TOUCH_RAW_X_MIN); p_Data->state = LV_INDEV_STATE_PRESSED; - ESP_LOGD(TAG, "Touch RAW: (%d, %d) -> MAPPED: (%d, %d)", raw_x, raw_y, p_Data->point.x, p_Data->point.y); + ESP_LOGD(TAG, "Raw: (%d, %d)", Data[0].x, Data[0].y); + ESP_LOGD(TAG, "Mapped: (%d, %d)", p_Data->point.x, p_Data->point.y); #ifdef CONFIG_GUI_TOUCH_DEBUG /* Update touch debug visualization */ @@ -492,7 +487,7 @@ static void XPT2046_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Da if (_GUITask_State.TouchDebugLabel != NULL) { char buf[64]; - snprintf(buf, sizeof(buf), "Raw: %u,%u\nMap: %li,%li", raw_x, raw_y, p_Data->point.x, p_Data->point.y); + snprintf(buf, sizeof(buf), "Raw: %u,%u\nMap: %li,%li", Data[0].x, Data[0].y, p_Data->point.x, p_Data->point.y); lv_label_set_text(_GUITask_State.TouchDebugLabel, buf); lv_obj_clear_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); } @@ -513,6 +508,9 @@ static void XPT2046_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Da } } +/** @brief GUI Task main function. + * @param p_Parameters Task parameters + */ void Task_GUI(void *p_Parameters) { App_Context_t *App_Context; @@ -536,7 +534,12 @@ void Task_GUI(void *p_Parameters) if (EventBits & LEPTON_CAMERA_READY) { lv_bar_set_value(ui_SplashScreen_LoadingBar, 100, LV_ANIM_OFF); + xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_CAMERA_READY); + } else if (EventBits & LEPTON_CAMERA_ERROR) { + lv_label_set_text(ui_SplashScreen_StatusText, "Camera Error"); + + xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_CAMERA_ERROR); } // TODO: Add timeout @@ -711,27 +714,28 @@ void Task_GUI(void *p_Parameters) break; } else if (EventBits & BATTERY_VOLTAGE_READY) { - char buf[8]; + char Buffer[16]; + + snprintf(Buffer, sizeof(Buffer), "%d%%", _GUITask_State.BatteryInfo.Percentage); if (_GUITask_State.BatteryInfo.Percentage == 100) { - lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0x00FF00), 0); - lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_FULL); + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_FULL " %d%%", _GUITask_State.BatteryInfo.Percentage); + lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0x00FF00), 0); } else if (_GUITask_State.BatteryInfo.Percentage >= 75) { - lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0x00FF00), 0); - lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_3); + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_3 " %d%%", _GUITask_State.BatteryInfo.Percentage); + lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0x00FF00), 0); } else if (_GUITask_State.BatteryInfo.Percentage >= 50) { - lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0xFFFF00), 0); - lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_2); + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_2 " %d%%", _GUITask_State.BatteryInfo.Percentage); + lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0xFFFF00), 0); } else if (_GUITask_State.BatteryInfo.Percentage >= 25) { - lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0xFFFF00), 0); - lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_1); + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_1 " %d%%", _GUITask_State.BatteryInfo.Percentage); + lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0xFFFF00), 0); } else { - lv_obj_set_style_bg_color(ui_Image_Main_Battery, lv_color_hex(0xFF0000), 0); - lv_label_set_text(ui_Image_Main_Battery, LV_SYMBOL_BATTERY_EMPTY); + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_EMPTY " %d%%", _GUITask_State.BatteryInfo.Percentage); + lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0xFF0000), 0); } - snprintf(buf, sizeof(buf), "%d%%", _GUITask_State.BatteryInfo.Percentage); - lv_label_set_text(ui_Label_Main_Battery_Remaining, buf); + lv_label_set_text(ui_Label_Main_Battery_Remaining, Buffer); xEventGroupClearBits(_GUITask_State.EventGroup, BATTERY_VOLTAGE_READY); } else if ( EventBits & BATTERY_CHARGING_STATUS_READY) { @@ -855,7 +859,7 @@ esp_err_t GUI_Task_Init(void) return ESP_OK; } - ESP_ERROR_CHECK(GUI_Helper_Init(&_GUITask_State, XPT2046_LVGL_ReadCallback)); + ESP_ERROR_CHECK(GUI_Helper_Init(&_GUITask_State, Touch_LVGL_ReadCallback)); /* Initialize the UI elements and trigger a redraw to make all elements accessibile */ ui_init(); diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp index 32e83b8..3c0d99d 100644 --- a/main/Application/Tasks/Lepton/leptonTask.cpp +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -129,11 +129,12 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int } } -/** @brief Lepton camera task main loop. - * @param p_Parameters Pointer to App_Context_t structure +/** @brief Lepton camera task main loop. + * @param p_Parameters Task parameters */ static void Task_Lepton(void *p_Parameters) { + Lepton_Error_t Lepton_Error; App_Context_t *App_Context; App_Lepton_Device_t DeviceInfo; @@ -142,6 +143,16 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGD(TAG, "Lepton task started on core %d", xPortGetCoreID()); + /* Initialize Lepton (this creates I2C device handle) before framebuffer allocation */ + Lepton_Error = Lepton_Init(&_LeptonTask_State.Lepton, &_LeptonTask_State.LeptonConf); + if (Lepton_Error != LEPTON_ERR_OK) { + ESP_LOGE(TAG, "Lepton initialization failed with error: %d!", Lepton_Error); + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); + + esp_task_wdt_delete(NULL); + vTaskDelete(NULL); + } + /* Format serial number as readable string: XXXX-XXXX-XXXX-XXXX */ snprintf(DeviceInfo.SerialNumber, sizeof(DeviceInfo.SerialNumber), "%02X%02X-%02X%02X-%02X%02X-%02X%02X", @@ -183,8 +194,10 @@ static void Task_Lepton(void *p_Parameters) /* Critical error - cannot continue without capture task */ _LeptonTask_State.Running = false; _LeptonTask_State.TaskHandle = NULL; + esp_task_wdt_delete(NULL); vTaskDelete(NULL); + return; } @@ -446,8 +459,6 @@ static void Task_Lepton(void *p_Parameters) esp_err_t Lepton_Task_Init(void) { - Lepton_Error_t Lepton_Error; - if (_LeptonTask_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); return ESP_OK; @@ -456,8 +467,6 @@ esp_err_t Lepton_Task_Init(void) ESP_LOGD(TAG, "Initializing Lepton Task"); _LeptonTask_State.CurrentReadBuffer = 0; - Lepton_Error = LEPTON_ERR_OK; - /* Create event group */ _LeptonTask_State.EventGroup = xEventGroupCreate(); if (_LeptonTask_State.EventGroup == NULL) { @@ -473,22 +482,10 @@ esp_err_t Lepton_Task_Init(void) return ESP_ERR_NO_MEM; } - /* Initialize Lepton configuration and I2C BEFORE allocating large buffers */ _LeptonTask_State.LeptonConf = LEPTON_DEFAULT_CONF; LEPTON_ASSIGN_FUNC(_LeptonTask_State.LeptonConf, NULL, NULL, I2CM_Write, I2CM_Read); LEPTON_ASSIGN_I2C_HANDLE(_LeptonTask_State.LeptonConf, DevicesManager_GetI2CBusHandle()); - /* Initialize Lepton (this creates I2C device handle) before framebuffer allocation */ - Lepton_Error = Lepton_Init(&_LeptonTask_State.Lepton, &_LeptonTask_State.LeptonConf); - if (Lepton_Error != LEPTON_ERR_OK) { - ESP_LOGE(TAG, "Lepton initialization failed with error: %d!", Lepton_Error); - - vSemaphoreDelete(_LeptonTask_State.BufferMutex); - vEventGroupDelete(_LeptonTask_State.EventGroup); - - return ESP_FAIL; - } - /* Allocate RGB buffers - both RAW14 and RGB888 use 160x120 resolution * RAW14: 160x120x3 = 57,600 bytes (after conversion to RGB) * RGB888: 160x120x3 = 57,600 bytes (native RGB data) diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index ea696a1..3bb1ceb 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -44,7 +44,8 @@ #define NETWORK_TASK_OPEN_WIFI_REQUEST BIT5 #define NETWORK_TASK_PROV_TIMEOUT BIT6 #define NETWORK_TASK_SNTP_TIMEZONE_SET BIT7 -#define NETWORK_TASK_WIFI_CREDENTIALS_UPDATED BIT8 +#define NETWORK_TASK_SNTP_TIME_SYNCED BIT8 +#define NETWORK_TASK_WIFI_CREDENTIALS_UPDATED BIT10 typedef struct { bool isInitialized; @@ -66,6 +67,37 @@ static Network_Task_State_t _NetworkTask_State; static const char *TAG = "network_task"; +/** @brief SNTP event handler for task coordination. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_SNTP_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + switch (ID) { + case SNTP_EVENT_TZ_CHANGED: { + ESP_LOGD(TAG, "Timezone set"); + + _NetworkTask_State.Timezone = static_cast(p_Data); + + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); + + break; + } + case SNTP_EVENT_SNTP_SYNCED: { + ESP_LOGD(TAG, "SNTP time synchronized"); + + xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIME_SYNCED); + + break; + } + default: { + break; + } + } +} + /** @brief Network event handler for task coordination. * @param p_HandlerArgs Handler argument * @param Base Event base @@ -91,15 +123,6 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, break; } - case NETWORK_EVENT_SET_TZ: { - ESP_LOGD(TAG, "Timezone set"); - - _NetworkTask_State.Timezone = static_cast(p_Data); - - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); - - break; - } case NETWORK_EVENT_WIFI_CONNECTED: { ESP_LOGD(TAG, "WiFi connected"); @@ -178,7 +201,7 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int } /** @brief Network task main loop. - * @param p_Parameters Pointer to App_Context_t structure + * @param p_Parameters Task parameters */ static void Task_Network(void *p_Parameters) { @@ -392,7 +415,8 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) } if ((esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL) != ESP_OK) || - (esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL) != ESP_OK)) { + (esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL) != ESP_OK) || + (esp_event_handler_register(SNTP_EVENTS, ESP_EVENT_ANY_ID, on_SNTP_Event_Handler, NULL) != ESP_OK)) { ESP_LOGE(TAG, "Failed to register event handler: %d!", Error); vEventGroupDelete(_NetworkTask_State.EventGroup); @@ -424,6 +448,7 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to init WiFi manager: 0x%x!", Error); + esp_event_handler_unregister(SNTP_EVENTS, ESP_EVENT_ANY_ID, on_SNTP_Event_Handler); esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); vEventGroupDelete(_NetworkTask_State.EventGroup); @@ -458,6 +483,7 @@ void Network_Task_Deinit(void) Provisioning_Deinit(); NetworkManager_Deinit(); + esp_event_handler_unregister(SNTP_EVENTS, ESP_EVENT_ANY_ID, on_SNTP_Event_Handler); esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); diff --git a/main/Application/application.h b/main/Application/application.h index 0276f9c..d0b8145 100644 --- a/main/Application/application.h +++ b/main/Application/application.h @@ -39,8 +39,7 @@ ESP_EVENT_DECLARE_BASE(SD_EVENTS); */ enum { LEPTON_EVENT_CAMERA_READY, /**< Lepton camera is ready. */ - LEPTON_EVENT_CAMERA_ERROR, /**< Lepton camera error occurred. - Data is transmitted in a App_Lepton_Device_t structure. */ + LEPTON_EVENT_CAMERA_ERROR, /**< Lepton camera error occurred. */ LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP, /**< FPA and AUX temperatures are ready. Data is transmitted in a App_Lepton_Temperatures_t structure. */ LEPTON_EVENT_RESPONSE_SPOTMETER, /**< Spotmeter data is ready. @@ -95,7 +94,7 @@ typedef struct { */ typedef struct { int Voltage; /**< Battery voltage in millivolts. */ - int Percentage; /**< Battery percentage (0-100%). */ + uint8_t Percentage; /**< Battery percentage (0-100%). */ } App_Devices_Battery_t; /** @brief Structure representing a ready frame from the Lepton camera. diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index d11ddf4..09b18cd 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -5,6 +5,63 @@ menu "PyroVision" default "PyroVision" endmenu + menu "Settings" + config SETTINGS_NAMESPACE + string "Settings namespace for the NVS" + default "PyroVision" + endmenu + + menu "Battery" + choice + prompt "ADC Unit" + default BATTERY_ADC_1 + help + Select the used ADC unit. + + config BATTERY_ADC_1 + bool "ADC 1" + config BATTERY_ADC_2 + bool "ADC 2" + endchoice + + config BATTERY_ADC_CHANNEL + int "ADC channel used for battery measurement" + range 0 9 + default 0 + + choice + prompt "ADC Attenuation" + default BATTERY_ADC_ATT_0 + help + Select the used ADC attenuation. + + config BATTERY_ADC_ATT_0 + bool "0 dB ADC attenuation" + config BATTERY_ADC_ATT_2_5 + bool "2.5 dB ADC attenuation" + config BATTERY_ADC_ATT_6 + bool "6 dB ADC attenuation" + config BATTERY_ADC_ATT_12 + bool "12 dB ADC attenuation" + endchoice + + config BATTERY_ADC_MIN_MV + int "Minimal battery voltage in Millivolt" + default 3000 + + config BATTERY_ADC_MAX_MV + int "Maximal battery voltage in Millivolt" + default 4200 + + config BATTERY_ADC_R1 + int "Value of the R1 resistor of the voltage divider" + default 10000 + + config BATTERY_ADC_R2 + int "Value of the R2 resistor of the voltage divider" + default 3300 + endmenu + menu "Network" menu "Task" config NETWORK_TASK_STACKSIZE @@ -80,20 +137,30 @@ menu "PyroVision" menu "Touch" choice - prompt "Touch SPI Bus" - default TOUCH_SPI3_HOST + prompt "Touch I2C Bus" + default TOUCH_I2C0_HOST help Select the SPI Bus the Touch Controller is attached to. - config TOUCH_SPI2_HOST - bool "SPI2_HOST" - config TOUCH_SPI3_HOST - bool "SPI3_HOST" + config TOUCH_I2C0_HOST + bool "I2C0_HOST" + config TOUCH_I2C1_HOST + bool "I2C1_HOST" endchoice config TOUCH_CLOCK - int "Touch SPI clock" - default 2000000 + int "Touch bus clock" + default 400000 + + config TOUCH_SDA + int "Touch interrupt GPIO number" + range -1 48 + default 39 + + config TOUCH_SCL + int "Touch interrupt GPIO number" + range -1 48 + default 40 config TOUCH_IRQ int "Touch interrupt GPIO number" @@ -104,11 +171,6 @@ menu "PyroVision" int "Touch reset GPIO number" range -1 48 default -1 - - config TOUCH_CS - int "Touch chip select GPIO number" - range 0 48 - default 41 endmenu menu "SD-Card" @@ -155,11 +217,11 @@ menu "PyroVision" endchoice config LCD_CLOCK - int "LCD SPI clock" + int "SPI clock" default 80000000 config LCD_CS - int "LCD Chip Select GPIO" + int "Chip Select GPIO" range 0 48 default 18 @@ -169,7 +231,7 @@ menu "PyroVision" default 3 config LCD_RST - int "RST GPIO" + int "Reset GPIO" range -1 48 default 8 diff --git a/main/idf_component.yml b/main/idf_component.yml index 83cdafc..94819cd 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -5,11 +5,11 @@ dependencies: version: "^0.1.0" espressif/esp_lcd_ili9341: version: "^2.0.1" + espressif/esp_lcd_touch_gt911: + version: "^1.2.0" espressif/esp32-camera: version: "^2.1.0" lvgl/lvgl: version: "^9.4.0" - atanisoft/esp_lcd_touch_xpt2046: - version: "^1.0.6" joltwallet/littlefs: version: "^1.20.3" \ No newline at end of file diff --git a/sdkconfig.debug b/sdkconfig.debug index 8c7f16e..bc7a47d 100644 --- a/sdkconfig.debug +++ b/sdkconfig.debug @@ -601,6 +601,28 @@ CONFIG_PARTITION_TABLE_MD5=y CONFIG_DEVICE_MANUFACTURER="PyroVision" # end of Device +# +# Settings +# +CONFIG_SETTINGS_NAMESPACE="Calendar" +# end of Settings + +# +# Battery +# +CONFIG_BATTERY_ADC_1=y +# CONFIG_BATTERY_ADC_2 is not set +CONFIG_BATTERY_ADC_CHANNEL=0 +CONFIG_BATTERY_ADC_ATT_0=y +# CONFIG_BATTERY_ADC_ATT_2_5 is not set +# CONFIG_BATTERY_ADC_ATT_6 is not set +# CONFIG_BATTERY_ADC_ATT_12 is not set +CONFIG_BATTERY_ADC_MIN_MV=3000 +CONFIG_BATTERY_ADC_MAX_MV=4200 +CONFIG_BATTERY_ADC_R1=10000 +CONFIG_BATTERY_ADC_R2=3300 +# end of Battery + # # Network # @@ -654,12 +676,13 @@ CONFIG_SPI_TRANSFER_SIZE=4096 # # Touch # -# CONFIG_TOUCH_SPI2_HOST is not set -CONFIG_TOUCH_SPI3_HOST=y -CONFIG_TOUCH_CLOCK=2000000 +CONFIG_TOUCH_I2C0_HOST=y +# CONFIG_TOUCH_I2C1_HOST is not set +CONFIG_TOUCH_CLOCK=400000 +CONFIG_TOUCH_SDA=39 +CONFIG_TOUCH_SCL=40 CONFIG_TOUCH_IRQ=38 CONFIG_TOUCH_RST=-1 -CONFIG_TOUCH_CS=41 # end of Touch # @@ -713,16 +736,6 @@ CONFIG_GUI_TASK_CORE=0 # end of GUI # end of PyroVision -# -# XPT2046 -# -CONFIG_XPT2046_Z_THRESHOLD=400 -# CONFIG_XPT2046_INTERRUPT_MODE is not set -# CONFIG_XPT2046_VREF_ON_MODE is not set -CONFIG_XPT2046_CONVERT_ADC_TO_COORDS=y -# CONFIG_XPT2046_ENABLE_LOCKING is not set -# end of XPT2046 - # # Bootloader config (Custom) # diff --git a/ui/PyroVision.sll b/ui/PyroVision.sll index c5a6be7..60a203f 100644 --- a/ui/PyroVision.sll +++ b/ui/PyroVision.sll @@ -11,8 +11,8 @@ "description": "", "board": "ESP WROVER KIT", "board_version": "2.0.0", - "editor_version": "1.5.4", - "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQBLa273V3Dbx/flkVF+pOK7q8Phvw9J/Z76SupXMQxNIz7FDegOCTXJ+Hf+Rn0n/r8h/9DFXtf/5GPU/+vuX/ANDNbQfLDmtrcpaK5q/274d/6FGD/wACT/8AE10Og6GfE1i97pHgCC5t0kMTP/aCJhgASMNg9GH515zXpOg2Olah8Hni1fWf7Ktxr5ZZ/srT7m+zgBdq8jgk59vel7aXZfcv8guUtftLfwvPDDrPgOO1aZS0ZN2HVgDg4ZQRkcZGcjI9RWR/bvh3/oUYP/Ak/wDxNdJ40jtdD+HGg6HYX02q2V3cvfxagzBYxgFTEkeSy435YHGGJ7khfNqPbS7L7l/kFzrrM+G/EMn9nppK6bcyjEMivvUt6E4BFcLdW72t3NbyffikZG+oOK3NA/5GPTP+vuL/ANDFUfEX/Iz6t/1+Tf8AoZpzfNDmtrcHqrmZRRRWJIUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBYsLprHULa8RQzQSrKAe5Ug/wBK7O/8Py6/eS6poLR3cFyxlaPzVWSJjyQwJHeuEorSE0lyyV0NM7L/AIQfxH/0Dv8AyPH/APFV12g2t9p/hV9A1fwZ/atub03qn+1Fg2tsCD7vJ4B79+nFeP0U70v5X96/yHdHqfinT/EfiH7Da2vh6HTdK0+Mx2lnFcRts3YLszkgszEZJP8APJPPf8IP4j/6B3/keP8A+KrjaKL0v5X96/yC6O7sPD8ugXkWqa80dpBbMJVj81WklYcgKAT3rjL+6a+1C5vHUK08rSkDsWJP9ar0UpzTXLFWQmwooorMQUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB0Wp6Da2XhDw7q0ckxuNS+0+crEbV8uQKu0YyODzkmsLy19TXY6//wAk08E/9v3/AKOFcvaxJNdRpLII4yfnYnovf8cUDK3lr6mjy19TW62owzSLeMPKkXdDiPG5FI+RlHGSBkfgOealh1C0kMLzysUjubcyPIoLyBfMJYqD7gd+MdaAOd8tfU1O2nyrB52FKAAnbIrEA9MgHI/GtSHVljgnSSWaZmWRVLKQW3Ltyx39vcHp+Stq0Jtpk3Tsskcarbso8tCrKTg56Haew60AYflr6mjy19TWzf6lDdD9286t82DzgAj7mCxGPcY6dKyaBDPLX1NHlr6mn0UAM8tfU0eWvqafRQAzy19TR5a+pp9FADPLX1NHlr6mn0UAM8tfU0eWvqafRQAzy19TR5a+pp9FADPLX1NHlr6mn0UAM8tfU0eWvqafRQAzy19TR5a+pp9FADPLX1NHlr6mn0UAM8tfU0eWvqafRQAzy19TR5a+pp9FADPLX1NHlr6mn11un6rpNr4YuTFpdk161ubW5WWeUPJl1ZZFG8Aj5cFQMggHkEgAHH+WvqaPLX1NdvpGtarL4dvbe81xo7BopXQjUAkySqmFXy9251fCoRggZzxg1neHNSi8P2lxq4EE140i20Nu5B/dnmUkdgVxHnuJGxyKBnM+Wvqa3dM0G1vfCHiLVpJJhcab9m8lVI2t5khVtwxk8DjBFUtWtra01W4hs51ntQ26GQEHKMMrnHRsEAjscjtXQ6B/yTTxt/24/wDo40AcTRRRQI7bX/8Akmngn/t+/wDRwrka67X/APkmngn/ALfv/RwrmLLH22HdMYV3jMg/h96BkFFb0l9GizCWaSOQQbYZFmE8hJdScupGOAePQn8Ug1a2c2kdwz7FnhkkJQ7VCAjAG45Bz2A6dDQBhUVrwav9nlt2E1w+24MkzHrIvy4B5OSMHr60waigsYYEmuI2XG443YxnlSWwPwA+tAGXRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoor0dNT0azvVaK5tp7q90DyppmYbbbbp2wRKf+ejSKAfThepYUAecUV6Dp3i7Rnv7EX0179i8+0JtJYVa3shGyFmjAYk5CkHCg4ds7j1r2uuabBa6Rqd7qN9d3dlq892gKK0k2FtyvmZclASmAfm6HjigZw1XLDS7nUt/wBnNuNpAPnXMcWSegG9hnp2rfj1fTl0eGyvDcIsuj/ZN8CxylXF6Zsld4wMDGDg85xggmceK7PdOsNxqNgMWyR3FtGpkmjhhWLY43AAHaGxlhk8g4BoA5CaGS3nkgmjaOWNijowwVYHBBHrXV6B/wAk08bf9uP/AKONYWv6hFq3iTVNRgV1iu7uWdFcAMFdywBx3wa3dA/5Jp42/wC3H/0caAOJooooEdtr/wDyTTwT/wBv3/o4VyNddr//ACTTwT/2/f8Ao4U2zhkTw3p8trFpIkkkmEjXqwbmwVxgycnGT0rSEOdsq1zk6K6+azsH159JngjilubVA7W8YOy4A3Dy844YYXAIBLemKzryDTrHQfMtjLNNeybUNzAqtGiH5iuGbGWwM8fdYVTotXd9gsYNFautwxRJpflxom+xjdtqgbmJbk+pqzeW8K32hKsMYWW2haQBRhyXOSfWp9m7tCsYNFdV4h+0W8t/GsWiLbLKyKsK2/mqu7A4X5gf1FXHstFHif7OuVvHijWCB7dfs4laNducHJGTn7vU88db9g72uPlOJoroNF0prqx1NpEi8108i2DjlpgQ5VOOu1SP+BAd65+s5QaSb6isFFFFQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK67QP+SaeNv+3H/wBHGuRrrtA/5Jp42/7cf/RxoGjiaKKKBHba/wD8k08E/wDb9/6OFYsGteXp8NlNp9ncxwszRtMH3DdjP3WA7CtDQ/E2mLoJ0DxFYz3OnrKZree1cLPbsfvbc8EH0Pf14xZ8z4a+niz/AMlqqMnHYZz15qVxeX4vHKxyrtCCIbRGFAChR2xgVPd61Lf6qt9dWttJtXaLfawixz2BB6knr1NbXmfDX08Wf+S1HmfDX08Wf+S1Pnl3Azp/Ea3IiE2i6Y3lRiNPll4UdB/rPc0258RNdCDOl6fG8CosTosmUCnIAy5H/wCutPzPhr6eLP8AyWo8z4a+niz/AMlqftZ9x3Zj32tJf+ez6VYRzTMWaaMSbgSckjLkfpVh/FE5n+1JYWEd4FCi5EbF1wAARuYrnAHOK0PM+Gvp4s/8lqPM+Gvp4s/8lqPaz3uF2c9PqdxMlmgIiFoP3Xl5HzZyXJz94nv7Cory6a9vJbl4442lbcyxjC57kD36103mfDX08Wf+S1HmfDX08Wf+S1S5N7iOSorrfM+Gvp4s/wDJajzPhr6eLP8AyWqQOSorrfM+Gvp4s/8AJajzPhr6eLP/ACWoA5Kiut8z4a+niz/yWo8z4a+niz/yWoA5Kiut8z4a+niz/wAlqPM+Gvp4s/8AJagDkqK63zPhr6eLP/JajzPhr6eLP/JagDkqK63zPhr6eLP/ACWo8z4a+niz/wAlqAOSorrfM+Gvp4s/8lqPM+Gvp4s/8lqAOSorrfM+Gvp4s/8AJajzPhr6eLP/ACWoA5Kiut8z4a+niz/yWo8z4a+niz/yWoA5Kiut8z4a+niz/wAlqPM+Gvp4s/8AJagDkqK63zPhr6eLP/JajzPhr6eLP/JagDkqK63zPhr6eLP/ACWo8z4a+niz/wAlqAOSorrfM+Gvp4s/8lqPM+Gvp4s/8lqAOSrrtA/5Jp42/wC3H/0caTzPhr6eLP8AyWqtrnibTG0EaB4dsZ7bT2lE1xPdOGnuGH3d2OAB6Dv6c5AOTooooEbugeEtT8RRT3Fube3srfAmvLuURwxn0Lev09vWtb/hXbf9Df4T/wDBl/8AY1LrTtD8LvCMMbFY7iW8mlUdHdZAqsfcAkVx9Azq/wDhXbf9Df4T/wDBl/8AY0f8K7b/AKG/wn/4Mv8A7GuUooA6v/hXbf8AQ3+E/wDwZf8A2NH/AArtv+hv8J/+DL/7GuUooA6v/hXbf9Df4T/8GX/2NH/Cu2/6G/wn/wCDL/7GuUooA6v/AIV23/Q3+E//AAZf/Y0f8K7b/ob/AAn/AODL/wCxrlKKAOr/AOFdt/0N/hP/AMGX/wBjR/wrtv8Aob/Cf/gy/wDsa5SigDq/+Fdt/wBDf4T/APBl/wDY0f8ACu2/6G/wn/4Mv/sa5SigDq/+Fdt/0N/hP/wZf/Y0f8K7b/ob/Cf/AIMv/sa5SigDq/8AhXbf9Df4T/8ABl/9jR/wrtv+hv8ACf8A4Mv/ALGuUooA6v8A4V23/Q3+E/8AwZf/AGNH/Cu2/wChv8J/+DL/AOxrlKKAOr/4V23/AEN/hP8A8GX/ANjR/wAK7b/ob/Cf/gy/+xrlKKAOr/4V23/Q3+E//Bl/9jR/wrtv+hv8J/8Agy/+xrlKKAOr/wCFdt/0N/hP/wAGX/2NH/Cu2/6G/wAJ/wDgy/8Asa5SigDq/wDhXbf9Df4T/wDBl/8AY0f8K7b/AKG/wn/4Mv8A7GuUooA6v/hXbf8AQ3+E/wDwZf8A2NH/AArtv+hv8J/+DL/7GuUooA6v/hXbf9Df4T/8GX/2NH/Cu2/6G/wn/wCDL/7GuUooA6v/AIV23/Q3+E//AAZf/Y0f8K7b/ob/AAn/AODL/wCxrlKKAOr/AOFdt/0N/hP/AMGX/wBjR/wrtv8Aob/Cf/gy/wDsa5SigDq/+Fdt/wBDf4T/APBl/wDY1k6/4S1Pw7FBcXBt7iyuMiG8tJRJDIfQN6/X39Kyq7DRXab4XeLoZGLR28tnNEp6I7SFWYe5AAoA4eiiigR22v8A/JNPBP8A2/f+jhXI112v/wDJNPBP/b9/6OFcjQNhRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACuu0D/AJJp42/7cf8A0ca5Guu0D/kmnjb/ALcf/RxoGjiaKKKBHba//wAk08E/9v3/AKOFcpEqvKqsxUE4JC5P5d66vX/+SaeCf+37/wBHCuVt53triOePG9GDDNAzSOihQXed4kCbmWVFSQc4HylsYPqTUf8AZDefbRNIV865MGSoO37uDwf9vpntVU3brKJLdRbNjGYWYZ/EkmiK9uInBE0hUP5hUuwBbOcnB68DnrQBOmnxvYPcLcgskYcoAOMuFx97PfPTFQXlulrcywCQu0UjxklcDg4B696Z9pn8kQmaQwg5Ee47fypbm6lu55JZD992faCdqljk4FAENFFFAgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKv6Tpw1O7eN5vIgiieeaULuKooycLkZJ6AZHJHIHNUKt6bqMumXf2iJI5AUaOSKUEpIjAhlOCDgg9iCOoIIoA1z4atljN8+oyjSTai5WcWwMpzIYtnl78btyt/FjAznoKWXwzbWXnT6hqTxWQaEQTQ23mNKJY/MUlSw2gKRnkkE4APWq//CTTmUq1jZtZG3FsLEh/KCB94wd2/O8ls7s5J5wcUo8UXEks5urKyu4JWjZbeZGEcRjXYm3awIAX5cEkEYznFAy4ng7y7xLC+v8AyL6e8ksrVI4fMR5EYLlmyNqliACAx6kgd68XhqN7SNWvWTUprSS8jtvJynloGYgybuGKoxA2kdOQTw2HxbfxyGeaG2urtbl7qG5mRt8ErkFmXBA6gHDAgEZA65ij8SXMdgtuLe2adIHto7xlbzkifO5B823ozDJUkBsA9MAFqXwsojmggvGl1O2iimuLYw7UAkKKAr7vmYGRAcqB1wTjlt54bt4hJ9k1Frj7PeJZXW6DYEdt2GT5juX5H5O08DjmoJvE13NaPGsFtFcSRxxTXkYYSyohUqGy20cohyACSoyTzmWXxVNNMsjabp4DXAurhFWRVuZQCAz4fIxuYgKVGSeKAMnUbT7Bqd3Z7/M+zzPFvxjdtYjOO3Sul0D/AJJp42/7cf8A0ca5i9unvr64u5QoknlaVgo4BY5OPbmun0D/AJJp42/7cf8A0caARzWgqra1bhgCMscH/dNGvKq61cBQAMqcD/dFL4f/AOQ3b/8AAv8A0E0eIP8AkN3H/Af/AEEV6Vl/Zt/7/wD7aX/y7+Z0mv8A/JNPBP8A2/f+jhXL2dv9rvre23bPOkWPdjOMnGcV1Gv/APJNPBP/AG/f+jhXLW07Wt1DcIAXidXUN0JBzzXmkFg6ZMba3niKP5sZk2b1DDDMOFzk/dzkD+VVHCB8IxZeOSMGrcepPHFCoghMkKFI5Tu3KCSfXHVj2qo7vI252LMe7HJoENooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK1tP0q1uLBL69vmtbb7YltIyQeYUDKzb8bhnG3p/+qsmtSDWjBpcOn/YLN4kuPPkLhyZjggBvmwBhj90A+9AF6fw3br4jt9Ht76ZjcL+6mmt1RJGIPl7SsjAqx2jdnjPTjFVNO0m1ura4ubq8mt4rRc3IW3DsCWCoqgsNxJJznbgKevAqc+Jw4SOTRdMkgijWOCJhMPICu7/I4kD8tIxOWPb0FRv4knl1bUb6Wys5E1Ek3NqVcRMSwbIwwYHcM5DevYkUDJh4bhGpS2r37COOEXZmEGQbYxeYGxuzvwVG3pk/ewM1BdaLawy2nl30skN9Gslq5twpYGQxsHG47SCrdC2cDpmox4gu/wC2G1Jo4GLx+Q0BU+UYtmwR4BztCgAc5GAc55ok115dSs7p7G0MNmoSC0G8RIoJbHDbz8zFsls5PpxQBT1G0+wand2e/wAz7PM8W/GN21iM47dK6XQP+SaeNv8Atx/9HGuYvbp76+uLuUKJJ5WlYKOAWOTj25rp9A/5Jp42/wC3H/0caARzfh//AJDdv/wL/wBBNHiD/kN3H/Af/QRR4f8A+Q3b/wDAv/QTR4g/5Ddx/wAB/wDQRXp/8y3/ALf/APbS/wDl38zpNf8A+SaeCf8At+/9HCuXs7f7XfW9tu2edIse7GcZOM4rqNf/AOSaeCf+37/0cK5a2na1uobhAC8Tq6huhIOea8wgsjS5Rb+c7KF8syYHJHQgH0yCCPannSX3MyyoYfL3qwZdzA/d+XORkkD2qBdRuFN0Swb7SpEmR79R6H/GkN7KbNLX5QqNuDAfN3IGfQEk/jQA+a2tYZGia6dpEba+2H5ffad3P4gVTq3LfvKTIIYo52O5po9wYn164H4AVUoEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAblh4XutWsrS40+a3kaaYwPHNPHCUkzwBuYFgVIOQPUY45uHwcJruGSz1O3m0qQO5u3aON1RCfMbyS+44Ck4HUY6ZrJ0zW7rSre8ggWJluo9h8xclDgrvXnhgrOufRj3wQW+t3VtotzpSLEYZ23b2X50+7uCnPAbYmfXYOnOQZsad4Rj1LS47+2fV7lJbl7dUs9L84qVSNiW/eDbkyEDrnaT7VJbeCTPbyyJNqF4U1CeyB0vT/tKHywh37t64Db+OOxrNtfFFxDa28NzZ2189vcNcxTXLyl0crGvVXAIAiTAIPSlg8UTRxItxp9ldvHeSXsckvmKySybN2NjqMfu1OCKAFXw/bCfUBLqQ+z6c7rcTxRb1YBwieV8w3liSedoAHWmpo+mG3mv21ScaajpEri0BmeRgTt8vftwAOTv7jGe0MHiK+jmuDMUuoLnd51rNnym3MHOACNp3AHKkHjrT08QbRND/AGVp5sZSjGyIk8sMoIDBt+8H5jzu5zz0GACWy0fSrsahKdUuhbWUBnd0sgWYebFGoCmQc5lyeeNvfNTw+GbGS1m1E6pP/ZcdqbhZUtAZSwmjiKFDIACDKrZDEYx34FO28RzW73itZWs1ncxGE2UhkEMal0k+QK4YHdGvOecc5qaPxVLGJYTptg1jJbfZvsREojVTIspIIcOW3IvJY8cdMYAJbXwza3uo6VDBqUpt9UnSC3ma2wysZFRw67+CoYNwSDkcjnE0XhGObWrbTg2swtLDPMRc6V5chEcbPiNPNO8naR1HJHWqMXiq/ttQsLm0jhtobGRJIrOLeISVcSDcCxZssASSSeByMDDINfjtNQju7XRdPg2xTQvErTlJVkjMbBt0hI+VjjaR1oAtR+G7aXxJZ6N9o1K2lupYYlN5p4iZS8gUkr5h4AOQc8njjrUdp4P1m4+3Ryabfw3Vva/aYrdrR98482OMhR148zdkA/d/EV7bX5bDV7bUNOtLez8iSKU28TymKVo3DrvDOSeQOM9uMHmpYPEUNsbhYdB0xIbmDyJot9wVdd6SA5MuQQ0Y6EdTnNAGRcW09pcPb3MMkMyHDxyKVZT6EHkV1Ogf8k08bf8Abj/6ONcvdTR3Fy8sVtFbI2MQxFiq8dtzMffkmuo0D/kmnjb/ALcf/RxoA5vw/wD8hu3/AOBf+gmjxB/yG7j/AID/AOgijw//AMhu3/4F/wCgmjxB/wAhu4/4D/6CK9P/AJlv/b//ALaX/wAu/mdJr/8AyTTwT/2/f+jhWNb6IZdPhvJdRsraOZmWNZi+TtxnopHcd62df/5Jp4J/7fv/AEcKpfZBqPhvTIoruySSGScyJNcpGRuK44Jz2NcNOKd9LkopLoF4dWttP3Qh7kAxSh90bqc8gjPHBqK702G2gMiarY3BBA8uEybj/wB9IB+tb9heWdprGgWX2uGRLJnM1xuxHuc5wCccDjn1JqtNp8dzNbRTJolnC0wEktreBmC98gyNxj264rR0o293+th2Mq70a7stLtNQlCeTdZ2gH5l9Nw7ZHI9qcuhXkk9rDH5bNcW4uAd2FRMkEsTgDGDWiNUi1a+1S2mZIba7T/R95CrE0Y/dDJ4Hygr/AMCqx9us2jtrOS6jjW50lLczA7hE4kLANjkDgA/UUKnTbunp/X5isjIn0Vo/L8rULC53yLGfJlJKk9MggEj3ANOvdESx89X1bT3mhJVokMm4sDggZQDP405dMXTrq1ml1Cwf9+mEhnEhxnliRwAPcitLxFGk0l/NFBomxpmdZoLwNKw3Zzt8w8nvxS5Fyt21CxytFFFc5IUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFddoH/JNPG3/bj/6ONcjXXaB/yTTxt/24/wDo40DRzfh//kN2/wDwL/0E0eIP+Q3cf8B/9BFHh/8A5Ddv/wAC/wDQTR4g/wCQ3cf8B/8AQRXp/wDMt/7f/wDbS/8Al38zr10658UfDTR49JjNzdaLLcJc20fMu2Vw6uF6kcY45/I1z3/CJeJP+he1b/wCk/wrGtLy6sLgXFnczW8y9JIXKMPxHNaX/CX+Jv8AoYtW/wDA2T/4qvMIJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4Uf8ACJeJP+he1b/wCk/wqD/hL/E3/Qxat/4Gyf8AxVH/AAl/ib/oYtW/8DZP/iqAJ/8AhEvEn/Qvat/4BSf4V0Ladc+F/hprEerRm2utalt0traTiXbE5dnK9QOcc8/mK5f/AIS/xN/0MWrf+Bsn/wAVWbd3l1f3BuLy5muJm6yTOXY/ieaALfh//kN2/wDwL/0E0eIP+Q3cf8B/9BFM0WaODV4JJXCICQWPQZUijWpo59XnkicOhIAYdDhQK9Hmj/Z/LfXn/wDbS7/u/mUKK3P+EWvv+etv/wB9N/hR/wAItff89bf/AL6b/Co/s3F/8+2L2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cuxh0Vuf8Itff8APW3/AO+m/wAKP+EWvv8Anrb/APfTf4Uf2bi/+fbD2cux11FFFfeHaFFFFABRRRQAUUUUAFT2Ks9/bqluLl2kULC2cSHPC8EHmoKltriW0uormByk0Th0YdiDkGpkm07AdLqr26aTdQ6gmkrf5X7PHYRgPGQ3zB2T5SMZGCSc1Xu9J8rwfaz7IvtSyGeZQP3iwyYWNm4+7lT9N49apXetrdjnStOiJkDu0cTAvg5wfm4B7hcU3+3bs6tcajII5JLhWSWNgdjIRjbgHoBjHPGB6VxwpVYpW0s7/pZdlv8AMlJm9YmG2gtjrFpo9rp7wgmIxbrmVSOGUjLgnqCSB+FY2mwxSeHtbleJGkjWHYzKCVzJg4PbikPiCWS2jjnsLCeWOIQpcSxEyBQMDvtOB0JBPFSWviMWlg9mujaa8cqIspdZcybeQTh+ueeMUlTqRTdtW1100d/xFZmtZQyR+FdNmtIdGEsks4le/WAM2Cu3Bk5OMnpUdppq6vpFxJMltCyaiDcXEEahY4ljYtt28Y44A4Jx61mr4i/0SO1l0jTpoYpHkiVxL+73kEgYcccDrnpVdtcuf7Mu9Ohjht7W6mE0iRBu3RRkn5eh/Ac1Ko1dbKzvv5X9ewWZszaZYjQ9W1KyhzZTQRNbmQBngcSqrpnsRn8VYVmaXBFJ4e12V4kaSKOExuyglCZVBwe3HFVbbWLu10i90tCptbsozqwJ2lSCCvoeADUdtqEtrY3toioY7tUWQsDkBWDDHPqK2jSqKLTd/eTXorf5P1HZnXz6LYweJWvr2BE05Gt44bdFC/aJTGhwB/dGcsfw6mq99pmnyWWs75bWx8rWWjjleFjhcP8AINikgd8dOKwtQ8Q3+p6hbXdyyE2wRYowCEULjtnvjmpl8SylbxLjT7G5S6ujdOkqvhXOem1hxyeuawWHrpRbeqS28vUVmS2NtZ6fY6jqW2DUjbSRQwblbysuGJdlIBONuADxk96V5Ida0LULqSxtre6sfLdZbaMRq6s4UqyjjPIIIHY1Sh1yW2vJZra0tIoZkCS2gQtC4HqGJOc85zx2pL7W5ry0FpHb21na7t7Q2yFQ7dixJJOMnqa29lUc7+a1vstLr56+Wo7O51MthoQ8WfZlyt68UawQSWy/ZhM0S7c4OSMnONuMnnI658GlW0mhade3kIS3t2uHu2RQrSYZAseR3JOB6DJ7VTfxbcNcfa007To70KqrdCNi64UKCNzFc4A5xWdNrF3Po0GlMwFtDK0oAzlmbu3POOcfU1jChXtFN9r6+TTt9+gkmdE1nZ6Lpi3xtoru0bUYXieSMEyW7Rvlc+vBB9GX2pP7J0bSbm+uvOuboWEYdEuLZPJmZx+653HIOd3TkKelc82sXb6EujuVa1Sfz0yDuVsEYB9OScetOutau7zSbXTpfL8m3PDAfM/XbuPfaCQPQGr+r1r6y3evp/V9u/kHKycQxHwa8/lJ539oBPM2jdt8snGfTPatk2FikVreyWkci22jJcmADaJpDKUBfHJAyCfXAFZv/CTr9iNn/YWlfZzJ5uzbL97GM/6z0qqviC9S5tJ4/KRra3+zBQuVePJJDg5DZ3HP4USp1p9Lavr+GgWbNC1uYdfgv7e406zglhtZLiGe1hERUoM7SBwQRxzzkirM2i2skWmXtyi2+nQ6dHLdPGoDSuXfCj1dsAZ7AZPSse51+aa0ltrezsrKObAm+yxFTIOuCSScZ7DAqK/1u91GwsrGZ1FtZpsjjQEA/wC0fU9v8mj2NW65fdV++2n9fmFmWvF0UEPia5W2t47eHZEyxRjAXMan+tYlW9S1CXVL57udUWRlRSEBAwqhR1J7AVUrqoxcKcYy3SRS2CiiitRhRRRQAUUUUAFFFFAH/9k=", + "editor_version": "1.6.0", + "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQBLa273V3Dbx/flkVF+pOK7q8Phvw9J/Z76SupXMQxNIz7FDegOCTXJ+Hf+Rn0n/r8h/9DFXtf/5GPU/+vuX/ANDNbQfLDmtrcpaK5q/274d/6FGD/wACT/8AE1d1GbS9J+yfbvBUEX2u2S6g/wBMDb4nztbgHGcHg81xte1XGh2L/wDCP+Kdej36Fo/hyyaWIxM/2mVt4SMdAcMVJyccqCMMSF7aXZfcv8gucPp02l6t9r+w+CoJfsls91P/AKYF2RJjc3IGcZHA5ql/bvh3/oUYP/Ak/wDxNei2+h2Kf8JB4p0GPZoWseHL1oohEyfZpV2B4z1AywYjBxwwAwoJ8Vo9tLsvuX+QXOusz4b8Qyf2emkrptzKMQyK+9S3oTgEVwt1bva3c1vJ9+KRkb6g4rc0D/kY9M/6+4v/AEMVR8Rf8jPq3/X5N/6Gac3zQ5ra3B6q5reF9KsGsLrWdVBa0t3ESxqATI5GcDP1FaB1rw4DgeE4COxNwef/AB2qdn/yTc/9hf8A9o1kVTlyJKKW3ZP8x7HTQ6poVxPHBB4OjlmkYIkaTszMxOAAAvJJrQ+z2n/CQ/2D/wAIGv8AanmeV9m+0HOeuc7cbcc7s4xznHNRfDqGK31q71+6jR7XRLSS8KyqNkkuNsUe48KxY5U4JyvA9O98+P7d/wALO+yw+V/YO/z8v5f9pZ8nZs3btv8AB/dxznPNT7aXZfcv8guebzapoVvPJBP4OjimjYo8bzsrKwOCCCvBBpg1rw4Tg+E4AO5FweP/AB2tH4lwWs3iGDXtOH/Ev1q2S7jKxhQr/dkQlSQXBGW7gtz6ni6PbS7L7l/kFzT8UaVYLYWus6UCtpcOYmjYAGNwM4OPoa5u1t3uruG3j+/LIqL9ScV1F5/yTcf9hf8A9o1i+Hf+Rn0n/r8h/wDQxROKc1bS9hNanWXh8N+HpP7PfSV1K5iGJpGfYob0BwSarf274d/6FGD/AMCT/wDE1la//wAjHqf/AF9y/wDoZrPpzqtSaSVvRDbPRtB0M+JrF73SPAEFzbpIYmf+0ETDAAkYbB6MPzo17Qz4ZsUvdX8AQW1u8giV/wC0EfLEEgYXJ6Kfyrk/B3/I76B/2Erf/wBGLR4x/wCR31//ALCVx/6Map9tLsvuX+Qrlv8At3w7/wBCjB/4En/4mrNmfDfiGT+z00ldNuZRiGRX3qW9CcAiuRrQ0D/kY9M/6+4v/QxVQqtySaVvRDTMO6t3tbua3k+/FIyN9QcV0nhfSrBrC61nVQWtLdxEsagEyORnAz9RWT4i/wCRn1b/AK/Jv/QzW1Z/8k3P/YX/APaNKEUpu+triS1Lh1rw4DgeE4COxNwef/Hams7/AES/vreztvB8ElxcSLFEn2rG5mOAMlcDk965atrwf/yO2g/9hG3/APRi0e2l2X3L/IdzZiXT59eOhw+B45NSEzQGBLrJDqSGGQMYGDk5wACc4qreX+iWF9cWdz4PgjuLeRopU+1Z2spwRkLg8jtXf2t74Lg8ea1ZWx1e31/Ubm4s47+dEaO1ndnUtFsIYZY4BPOMcqCxryHUrGXS9Uu9PnZGmtZngdkJKllYqcZxxkUe2l2X3L/ILmyNa8OE4PhOADuRcHj/AMdrP8UaVYLYWus6UCtpcOYmjYAGNwM4OPoazK17z/km4/7C/wD7RqlLnTUktuyX5BuclRRRXOQFFFFABRRRQAUUUUAFFFFAFiwumsdQtrxFDNBKsoB7lSD/AErs7/w/Lr95LqmgtHdwXLGVo/NVZImPJDAkd64SitITSXLJXQ0zsv8AhB/Ef/QO/wDI8f8A8VXSeJIPF/iHStG0s6Y9vY6baRwCAXcbLJIq7TKeRyRgAHOOcHk15TRTvS/lf3r/ACHdHq3huDxf4e0rWdLGmPcWOpWkkBgN3GqxyMu0Sjk8gZBAxnjJ4Fc3/wAIP4j/AOgd/wCR4/8A4quNoovS7P7/APgBdHd2Hh+XQLyLVNeaO0gtmEqx+arSSsOQFAJ71xl/dNfahc3jqFaeVpSB2LEn+tV6KU5prlirITZ1fhy4tr/Q7nQJ7iO3macXNrJKcIz7dpUntkdKt/8ACE+Ie1gGHYiaPB/8eriaKpVItJTW3nb9GO/c9Tt9N8SWvgq88PQaIiNeXaz3F0J4t0kagbYiOuAw3A59Rjk5meHxbJ4Aj8KNpriGO789ZVuo1Bj5PlFQfmG8l8knnHHAryaijmpfyv7/APgBdHqdxpviS68FWfh6fREdrO7ae3ujPFujjYHdEB1wWO4nPoMcDGF/whPiHvYBR3JmjwP/AB6uJoo5qX8r+/8A4AXR1fiO4trDQ7bQILiO4mWc3N1JEcor7doUHvgda5ywumsdQtrxFDNBKsoB7lSD/Sq9FRKblK60E2d3f+H5dfvJdU0Fo7uC5YytH5qrJEx5IYEjvVb/AIQfxH/0Dv8AyPH/APFVxtFW505O7i7+v/AHdHrXhXSZ9A8qe+8Ef2lqEFyJ4Lr+1RD5e3aVGwEg4YE5PrijxVpM+v8Amz2Pgj+zdQnuTPPdf2qJvM3biw2EgDLEHI9MV5LRS5qX8r+9f5BdHZf8IP4j/wCgd/5Hj/8Aiqs2Hh+XQLyLVNeaO0gtmEqx+arSSsOQFAJ71wlFNTpxd1F39f8AgBdFi/umvtQubx1CtPK0pA7FiT/Wuj8OXFtf6Hc6BPcR28zTi5tZJThGfbtKk9sjpXKUVEZuMrvUSZ23/CE+Ie1gGHYiaPB/8eq7o/hjxFpOt2Gpf2V5v2S5jn8v7RGu/YwbGcnGcdcV55RV81L+V/f/AMAd0e7G4Eery61bfDeFdWaR50uJtX81FmbJ3mM4BwTnAx7EHBHC3nhTxRf31xeXNl5lxcSNLK/mxDczHJOAcDk9q4Oijmpfyv7/APgBdHbf8IT4h72AUdyZo8D/AMeqp4juLaw0O20CC4juJlnNzdSRHKK+3aFB74HWuUoodSKTUFv53/RBfsFFFFYkhRRRQAUUUUAek3XgrR4vF+oaUhf7Tb3E8/2Pedi2oLbFDZ3FwoRzycq3qprAt9L0i60hRHLaJfNpAlXzbsRj7R9sKkfMwAbyR909ucZ5rnTf3hvXvTdzm7dmZp/MO9iepLdSTk5+tRyTyzLEssrusS7IwzEhFyTgegyScepNAy9r0Nlbap5NiY2ijggV2jk3qZREnmkNk5Hmb+nHpxis2iigR2HhvRtKs9DufE2vMz2sR2xQqN24k4ACngsSG68ADNX4dV065uGih8CLxCk5eS+gRVjcAoWYxbRkEcE57Vm6lEZ/hLp8SlFZ9UiUF2CqCRcDkngD3NRal9nv7KXR4tQsEukisH3tcp5Unl25jdRJnblWb155rScpKbinZK22m8U366sxhCNRc0tdX+Da/Q2YNS0+e8uLQeAwk1t/rvNvIY1j7DLNCAM9uee1Nl1fSoGkSXwMUkjmWBozcxbt7AkADycnODyOPzFZV5NaarZXOk21/aCeH7JieWURx3PlQmNsM2BwTxnqKi/tSztfGemXJlWa3shbRSzoCQ5jRVZxxzgjj1wKXPP+Z/eyvYU+x0N/e6XpkayXfglERmKblvIXAYdVJWI4b2PNVB4i8Nk/8imv/gRH/wDGay7iGPStAu7SS9tLqa6uYnjW3lEgCoHy5I6Z3AAHB68VkJ1o55/zP72HsKfY68a74bP/ADKi/wDf+P8A+M1KuseG2P8AyKy/9/4//jNcmnUfWrMfWjnn/M/vYewp9jp11Pw2xH/FLr/3+j/+NVIt74bb/mWV/wC/0f8A8arnY+oqzH1/Cjnn/M/vY/YU+xvLceG2/wCZbX/v7H/8aqRX8Nt/zLi/9/I//jVYsfX8Ksx9KOef8z+9i9hT7Gqq+Gz/AMy8v/fyP/41Uq2/htv+ZfX/AL7j/wDjVZqd60YLuWO3MKeWF3bt3lruB46NjI6etHPP+Z/ew9hT7FpNK0B4JJh4dHlxkKx3x8E5x/yz9jVp/DejRQiWTw4qqcZ+eLK56ZHl5GferVxrdzPaCQXTsszKJ4WlPBHXaM/dYHkYxnj0qadokbUbr7TFKl0CIlVssdzhuR2wB370c8/5n97H7Cn2KcPhbRZ2dU8PplH2NmSEDd6AlOT9Ki/sDw4GKtogVh1B8vI/8h1oW6Ld6bBCs8UTxSuzCR9uQwX5h69OnXpS3kyXF/PNH9x3JB9RnrRzz/mf3sPYU+xRHh3w2f8AmDr/AOQ//jdSjwx4bP8AzCV/KP8A+N1ZToPpVlaOef8AM/vYewp9iiPCXhsnH9lL+Uf/AMRUo8G+Gyf+QYv/AHzH/wDEVpJ94fWrCdR9aOef8z+9h7Cn2MlfBHhtj/yDl/74j/8AiKkXwH4bb/mHr/3xH/8AEVtx9asp1FHPP+Z/ew9hT7GAvw98Nt/y4r/37j/+IqRfhx4bb/lyX/v3H/8AEV0cdWY+v4Uc8/5n97D2FPscuvwz8Nt/y6L/AN+o/wD4mpV+F3htv+XVf+/Mf/xNdjAB5Y+6CWwSwzmp1AUEherHr/Kjnn/M/vYewp9ji1+FHhth/wAe6/8AfmP/AOJqO6+GGkWEBu7GytJpIxny7i1jdX9sba79AAxHYE06Xm1l/wB0/wAqipVqQg5KTul6/gxqhT6I+QfGcVlD4svU063Fva/u2WEdEJjUsB7bice1YNbfi7/kaLz/AIB/6AtYlbYiKjVlFdG/zJpSc6cZPqkFFFFYmgVreFbaG98X6La3MYkgmv4I5EboymRQQfwNZNbXg448b6Af+olb/wDoxaAPsSMxxRrHGoRFGFVQAAPQCneaKo+b7mjzfc1RZ89fHS0tbXx9C9tCkRuLFJpdoxvfe67j74UflXmVen/HVt3jeyOf+Yan/oyWvMKklnVax/yR+z/7CUf8rmuCT7orvdY/5I/Z/wDYSj/lc1wSfdFXU/iy/wC3f/SImVD4PnL/ANKZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hVmPpVaPr+FWY+lAFhO9Wo+n41VTvVqPp+NAFiPp+NWU+6KrR9Pxqyn3RQBYT7oqynQfSqyfdFWU6D6UAWU6D6VZWqydB9KsrQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FIC3C7KMA8delTxswzz71Wj6GrEfegCzGT196klObWX/dP8qjj6fjUkn/AB6y/wC6f5VnX/hS9H+Q1ufH3i7/AJGi8/4B/wCgLWJW34u/5Gi8/wCAf+gLWJXViv48/V/mcuH/AIMPRfkFFFFYGwVs+EjjxnoR9NQt/wD0YtY1a/hU48YaIf8Ap/g/9GLQB9Xed9KPO+lUfOo86qLPEvjc27xnZn/qHp/6MkrzWvRPjM27xhaH/pwT/wBGSV53Uks6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETKh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8Ksx9KALCd6tR9PxqqnerUfT8aALEfT8asp90VWj6fjVlPuigCwn3RVlOg+lVk+6Ksp0H0oAsp0H0qytVk6D6VZWgCyn3h9asJ1H1qun3h9asJ1H1oAsx9asp1FVo+tWU6imMsR1Zj6/hVaOrMfX8KQFmPoasR96rx9DViPvQBZj6fjUkn/AB6y/wC6f5VHH0/GpJP+PWX/AHT/ACrOv/Cl6P8AIa3Pj7xd/wAjRef8A/8AQFrErb8Xf8jRef8AAP8A0BaxK6sV/Hn6v8zlw/8ABh6L8gooorA2CtXwwceLNGPpfQf+jFrKrY8JRef4z0OHdt8zULdc4zjMiigD6R84+9HnH3rZ/wCEVb/n+/8AIP8A9ej/AIRVv+f7/wAg/wD16ZR8+fF5t3iy1P8A04p/6MkrgK9J+NmnnTfGdnCZfN3aejZ27f8AlpIPX2rzakI6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETKh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8K1NJ0271e9js7KEyzv0A7D1J7CgBid6tR9PxrvbX4S3BhBudXjjkPVY4C4H4lh/Kra/CnaP+Q1/wCSv/2dAHn8fT8asp90V3a/C3aP+Qz/AOSv/wBnUi/DPaP+Qv8A+S3/ANnQBxCfdFWU6D6V2S/DjaP+Qr/5L/8A2VSj4e4H/IU/8l//ALKgDkU6D6VZWtPVPC15pURmDLPAv3nUYK/UVmLQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf8AhS9H+Q1ufH3i7/kaLz/gH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBWt4VNyPF+imzEZuhfweSJc7C/mLt3Y5xnGaya3fBX/I+eHf8AsJ23/o1aAPpfzviL/wA+3hz/AL6m/wAaPO+Iv/Pt4c/76m/xrsaKZR8u/GRtabxfaHXUskuvsCbRZltmzzJMZ3c5zn9K88r0/wCPF5b3fj6BbeZZDb2CQy7Tna4kkJX64YV5hSEdVrH/ACR+z/7CUf8AK5rgk+6K73WP+SP2f/YSj/lc1wSfdFXU/iy/7d/9IiZUPg+cv/SmWU6D6VYToPpVdOg+lWE6D6VBqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4V7H8IbGJdIvtQ2gzPP5O7uFVQ382/QV45H1/CvbfhH/wAipc/9fr/+gR0AXvFPi2907V7TQ9DskvdWuBvKyE7I09Tgj0PcYA96YJviKRn7L4dHsWl/xrOtefjle57WAx/3yleh0Acd53xF/wCfbw5/31N/jR53xF/59vDn/fU3+NdjRQBx3nfEX/n28Of99S/41y2qfEfxXo+sNpk9hpNxcINzpaiR8DGSPvcEAZ6cV1HjXxbNpzR6Hoi/aNdvPljRBnyQf4j2zjpnp1PHWbwx4OtvDekzPPtudTuI2N1ctyWJ5KgnnH8+p9AAbOhavB4j0C21KOIpFcocxvzgglWHuMg/WvPruEW9/cwL92OVkH0BIrqPhp/yT3SvpL/6Neub1T/kMX3/AF8Sf+hGgBqfeH1qwnUfWq6feH1qwnUfWgCzH1qynUVWj61ZTqKYyxHVmPr+FVo6sx9fwpAWY+hqxH3qvH0NWI+9AFmPp+NSSf8AHrL/ALp/lUcfT8akk/49Zf8AdP8AKs6/8KXo/wAhrc+PvF3/ACNF5/wD/wBAWsStvxd/yNF5/wAA/wDQFrErqxX8efq/zOXD/wAGHovyCiiisDYK3fBX/I+eHf8AsJ23/o1awq2/BjKnjnw+zMFVdStiSTgAeatAH2VXFeMvFVzb3Mfh3w+vn63dfKdvP2dSPvH0OOfYcntl/i7xsmmKmmaLsvdaujsijjIcR5/ib39B+J4qz4N8Ir4etpLu8k+06xd/Pc3DHJBPJUH0z1Pc/hhlHz58U/DieGPEOn2XnNPPJp6TXEpOd0hkkBI9uBXDV6t+0B/yPlj/ANgyP/0bLXlNIR1Wsf8AJH7P/sJR/wArmuCT7orvdY/5I/Z/9hKP+VzXBJ90VdT+LL/t3/0iJlQ+D5y/9KZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hXtvwj/5FS5/6/X/APQI68Sj6/hXtvwj/wCRUuf+v1//AECOgDA1jX4PDnxmlvLoH7M8KQysOSisi/N+BA/DNen3+rafpmky6reXcUVjFH5jTlsrtPTGOucjAHJJAGc15pqugWXiT4wX1hf+Z5P2MP8Au2wQQigH8M5rA8XSat4c8J6t4Kvle6t5lSTTbkcZVZVYr+QPHUHjkEUAdxZ+OPFmq2qX2l/D+aawny1vLPqkULyR5+VijDIyOe454JGDWdcfFt55tR02z0C+ttURoorSC8QrK7OpJLx4+XHGBk7tw6c1pal8W/DcHhmLU7C9hnurhf3Vm7hZEbv5i5yoB/PsSDmuA8DaVr/ivxfret2/iH+ztQRLeQzSaesxdZUJG0SY2gKoAIHIPBx1AO00Czbwl4m0W31OD7brfiH7S0940v8Ax7+WgfaBj5s5wTkdO4r0W4/49pf9w/yry+bS9d034peC/wC2/Ef9seZ9u8r/AEJLfysQfN90/NnI69Me9eoXH/HtL/uH+VAHL/DP/knul/SX/wBGvXN6p/yGL7/r4k/9CNdJ8M/+Se6X9Jf/AEa9c3qn/IYvv+viT/0I0ANT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf+FL0f5DW58feLv+RovP8AgH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBWr4XtItQ8W6NZT58m4voIn2nB2tIoOPwNZVbngshfHfh4kgAanbEk/8AXVaAPqrQPBmieG3aWwtf37DBmlbc+PQHt+Fb9Rfabf8A57xf99ij7Tb/APPeL/vsUyj5m+N2qR6l8QWSJGUWdslsSf4mDOxP/j2PwrzivT/jvFbJ4+gktwmZrCOSVkOdzb5FyffCr+VeYUhHVax/yR+z/wCwlH/K5rgk+6K73WP+SP2f/YSj/lc1wSfdFXU/iy/7d/8ASImVD4PnL/0pllOg+lWE6D6VXToPpVhOg+lQalkVZTrVYVZTrTAsJ1H1qzH1qsnUfWrMfWgZZj6irMfX8KrR9RVmPr+FAFiPr+Fe2/CP/kVLn/r9f/0COvEo+v4V7b8I/wDkVLn/AK/X/wDQI6AIbT/kuV9/14D/ANBSu01fRdP12yNpqVsk8RORngqfUEcg1wt1cw6L8aPtN+4ggvbMJFK5wucAcntyuPxFeiC6tyMieLH++KAOV034YeEdNleUaRDdSP3u1EoH4EY/HGa6G10ewstVv9Tt4Nl5qHl/aZN7HzPLXanBOBgHsB71Z+02/wDz3i/77FH2m3/57xf99igDz7xlqF3deNtNstEsbebWdOgkuIZ53Ybd67WRRkKSVA5b8MVt+DPFEnirwzPc3EKxXUDNFKE+6x25BHp16e1WNc8OaNrszXE04iuWt2tzNFIMlD2OfTtTLeLQfBPhaaGG4jjto1Z2Z5AXlcj9ScAce1AEPwz/AOSe6X9Jf/Rr1zeqf8hi+/6+JP8A0I10nw0GPh7pWfSX/wBGvXN6p/yGL7/r4k/9CNADU+8PrVhOo+tV0+8PrVhOo+tAFmPrVlOoqtH1qynUUxliOrMfX8KrR1Zj6/hSAsx9DViPvVePoasR96ALMfT8akk/49Zf90/yqOPp+NSSf8esv+6f5VnX/hS9H+Q1ufH3i7/kaLz/AIB/6AtYlbfi7/kaLz/gH/oC1iV1Yr+PP1f5nLh/4MPRfkFFFFYGwVq+GbOLUfFej2UxYRXF9BC5U4O1nAOPfmsqrel3U1jq9leW77J4J0ljbAO1lYEHB4PIoA+nP+FQeGv+el//AN/l/wDiaP8AhUHhr/npf/8Af5f/AImvMP8AhaXjD/oLj/wGi/8AiKP+FpeMP+guP/AaL/4imUYvxd8N2PhfxXa2Vg0zRPYpMTKwY7i8g7AcfKK4Guh8Y6/qXiLV4rzVLn7ROkAiVvLVMKGY4woA6k1z1IR1Wsf8kfs/+wlH/K5rgk+6K73WP+SP2f8A2Eo/5XNcEn3RV1P4sv8At3/0iJlQ+D5y/wDSmWU6D6VYToPpVdOg+lWE6D6VBqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4V6p8J9dgt/tOjTuEeZxNASfvNgBl+uAMfjXlcfX8KtREqQykgjBBHagD6M1zw9pniOzFtqdsJVU5RgcMh9iOlcqfhD4aJ4e/H0mH/AMTXC2njjxLbQiKPVZCo6eYiSH82BNXU8e+JiOdS7/8APCP/AOJoA63/AIVB4a/56X//AH+X/wCJo/4VB4a/56X/AP3+X/4muYTx14kI51Hv/wA8I/8A4mp08beISBnUP/IMf/xNAHQf8Kg8Nf8APXUP+/y//E1NbfCjwvbzLI8VzOFOdks3yn64Arn08Za+QM3/AP5Bj/8AiamXxdrpHN92/wCeSf8AxNAHpE01ppGnbiEht4U2qigAADooFeZTTNcXMszcNI5c/UnNR3Wo3moOHu7h5SOgJ4H0HQULQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf+FL0f5DW58feLv+RovP8AgH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBUkBxPGf9ofzqOnIcSKfcUAbXmj1o80etUvOHqaPOHqaBkeoNunU/7P8AU1UqW4bdID7VFQI6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETOh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8Ksx9KALCd6tR9PxqqnerUfT8aALEfT8asp90VWj6fjVlPuigCwn3RVlOg+lVk+6Ksp0H0oAsp0H0qytVk6D6VZWgCyn3h9asJ1H1qun3h9asJ1H1oAsx9asp1FVo+tWU6imMsR1Zj6/hVaOrMfX8KQFmPoasR96rx9DViPvQBZj6fjUkn/AB6y/wC6f5VHH0/GpJP+PWX/AHT/ACrOv/Cl6P8AIa3Pj7xd/wAjRef8A/8AQFrErb8Xf8jRef8AAP8A0BaxK6sV/Hn6v8zlw/8ABh6L8gooorA2CjOOfSimucIx9jQA/wA76Ued9Ko+b7Ueb7Uxl3du5oqKBtyE+9S0hHVax/yR+z/7CUf8rmuCT7orvdY/5I/Z/wDYSj/lc1wSfdFXU/iy/wC3f/SImdD4PnL/ANKZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hVmPpVaPr+FWY+lAFhO9Wo+n41VTvVqPp+NAFiPp+NWU+6KrR9Pxqyn3RQBYT7oqynQfSqyfdFWU6D6UAWU6D6VZWqydB9KsrQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/wB0/wAqjj6fjUkn/HrL/un+VZ1/4UvR/kNbnx94u/5Gi8/4B/6AtYlbfi7/AJGi8/4B/wCgLWJXViv48/V/mcuH/gw9F+QUUUVgbBTXUsjKOpBFOq9ounf2xr2naZ5vk/bLqK38zbu2b2C5xkZxnpmgDn/s1x/d/wDHhR9muP7v/jwrsl8JXi6aL6aWNIzavcbV+ZkIAZVccbSysGHXIPscWn8J2I06K8TWfNRri3t38qFZMGVHbIVZC/BQjBVSew4xQM4+2jeOLD9Sc1NWnr2jtoOpHT5phJcxopm2rhFY8gKf4hgjnA5JxkYJzKBHVax/yR+z/wCwlH/K5rgk+6K9A1SKSX4OwMilhFqEbvj+Ff365P4so/EV5+n3RVVP4sv+3f8A0iJnR+D5y/8ASmWU6D6VYToPpVdOg+lWE6D6VJqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4VZj6VWj6/hVmPpQBYTvVqPp+NVU71aj6fjQBYj6fjVlPuiq0fT8asp90UAWE+6Ksp0H0qsn3RVlOg+lAFlOg+lWVqsnQfSrK0AWU+8PrVhOo+tV0+8PrVhOo+tAFmPrVlOoqtH1qynUUxliOrMfX8KrR1Zj6/hSAsx9DViPvVePoasR96ALMfT8akk/49Zf90/yqOPp+NPmYLaSliANp5P0rOv8Awpej/Ia3Pj/xd/yNF5/wD/0BaxK2/F3/ACNF5/wD/wBAWsSurFfx5+r/ADObD/wYei/IKKKKwNQq3peoS6Tq1lqUCo01pOk8ayAlSyMGAOCDjI9aqUUAbEXibU431ZjKsn9qoUuQ68HJzuAHQjkD0BI6Gqp1rVWS2RtTvStrzADO2IuMfLz8vHHFUaKAJJJ5ZljWWV3WJdkYZidi5JwPQZJOPc1HRRQB0XhnxVLoiz2d1Al3ps4IeFwGwD1G08EHAOOMHmrp1PwIWLf8IsQSc8STAfl51chRV8yfxJN/12sZumm7ptHYDVfAo6eF2/7+zf8Ax6nDWfBA6eGG/wC/s3/x6uNopXj/AC/i/wDMXsv7zO1/tzwV/wBCy3/fyX/49Th4g8GDp4bb/v5L/wDHq4iii8f5fxf+Yez/ALzO5HiTweOnhxv++5f/AI9Th4o8Ijp4db/vuT/49XCUUXj/AC/i/wDMPZv+ZnejxX4THTw83/fUn/x6njxf4VHTw+3/AH1J/wDHq8/oovH+X8X/AJh7N/zM9CHjPwwOmgN+cn/x2nDxv4aHTQW/N/8A47XndFF4/wAv4v8AzD2b/mZ6MPHXhwdNCb83/wDjtOHj7w+OmiN/4/8A/Ha83oovH+X8X/mHs3/Mz0ofELQR00Vv/H//AI7Tx8RdDHTRm/Jv/jteZUUXj/L+L/zD2b/mZ6ePiToo6aO35N/8dpw+JukDppDf98t/8dry6ii8f5fxf+Y/Zv8AmZ6mPihpQ6aS3/fLf/Had/wtTTB/zCm/75P/AMcryqii8f5fxf8AmHs3/Mz1gfFjTx00tv8Avg//ABynD4uWI6aY3/fB/wDjleS0UXj/AC/i/wDMPZv+Znrg+MFmOmnN/wB+/wD7ZTh8Y7YdNPb/AL9//bK8hoovH+X8X/mHs3/Mz2AfGeAdLBv+/X/2ynD41xDpYt/36/8AtleO0UXj/L+L/wAw9m/5meyj43KOlk3/AH5H/wAcpw+OWOlm3/fkf/F14xRReP8AL+L/AMw9m/5me0j47MOlo3/fkf8AxdRz/GmHUU+z3q3kNs3EhtoE3EenL141RT5o78q/F/m7B7Lu395reJtXh13xDd6jb232aCQqscWclVVQgye5IUE+5NZNFFS227s0CiiikAqKXdUXqxwKtfYc3ZhEo2gZEmOD6fqcVDbyCGUSEElQduPXHFP+0j7GIgCJAcbv9kc4/M1lPnv7v9f8MehhVhVC9bV79enT/t5vfdW8yuQQcHrU6wRiNXml2b+VAXJx6mmTuskzOoIDHJHv3/WpBJDJGizeYGQYBQA5HWnJysmZ0oUlUlF2dtr3Sevlbp5kDABiAcgHqO9JStjcduQM8ZpK0OR7hRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArrdH8IWN+umC71mS2l1G0kuLeNLUSF3WV4/KBMijcdmRkjJOOuM8lXW3mo+FryDS7F5tZFvYWjRLcrbxK+8zPIcx7yCMPj74PFAzNfTdEF4YRrdxEiyqjNc2BRlXaxYlVduQQqgZ53dsGr58Gf2hHaTeH9QW+guWmQG6VbRkaJVd8hnK42sDkN65xiodZ1zTtb1u4eWCSCznliZ7ryhJdYSPYT95VJc/Owz178c3PEvimC7vNFvtJ1HVHvdPiCNJcxLEoKEbGRFdwCR94cAkZxyaAK2p+Dxo+m2N7e6tZ7buCVwttNHORIpcKo2OcqxQAuOFLYPIpq+GtPvdPupNJ1pr29tIFnlgNo0aMpZVOxy2WILjgquecVW1TWrW41E3Fpa5t3t3QWlyC0dq8gO/wAoBuFDMWXpgnkHGTr6j4psZfD8Ftpt3eWcyW9sklpFp0EcUskYXczzK29gWUv8ynnHTqACpq3hK306DU44dVNxqGkhft0BtiiLl1jOx9x34dlByq9cjIrl67TxT4xi8Q2M7Jd30c11KJZ7RreLy85Jx5wId1BPyhhxxzxXF0AFFFFAgrVbRl/sOx1RLsGKa5a2uN0ZAt3GCucZLAqSRgfwsO1ZVdlJqfhGDSdYtLJ9X2XsUbQ20trHshnQ5Vt/mkkcuv3ejmgDNv8AQNPXRrjUtI1d7+O1mjhuFktTARvDbWX5juX5COcHpxU0PhITMzC9YwStGtnKsORN5iuVLfN8gHlsG+9ggjnBNa+teL9Kur+GaxnvUs1vPPGnjTYLeKEEMAwMb/vHTI27h+I75WpeKftdrd2kdzfbWjQRzk7XmO1VkEoDEFXxu6tyo/vMaBnL0UUUCP/Z", "export_temp_image": false, "force_export_images": false, "flat_export": false, @@ -23,9 +23,12 @@ "theme_color1": 5, "theme_color2": 0, "custom_variable_prefix": "uic", + "separate_screen_save": false, + "hierarchy_state_save": false, "backup_cnt": 73, "autosave_cnt": 0, "group_color_cnt": 0, + "imagebytearrayprefix": "", "lvgl_version": "9.1.0", "callfuncsexport": "CPP_FILE", "imageexport": "SOURCE", diff --git a/ui/PyroVision.spj b/ui/PyroVision.spj index ed99082..8b03b22 100644 --- a/ui/PyroVision.spj +++ b/ui/PyroVision.spj @@ -1,17 +1,12 @@ { "root": { "guid": "GUID93537733-852890S2924354", - "deepid": 0, "children": [ { "guid": "GUID66987770-852891S3274354", - "deepid": 660259650, "children": [ { "guid": "GUID20182961-853099S6974354", - "deepid": -1317681897, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -68,11 +63,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "IMAGE/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -191,14 +197,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "IMAGE", - "tree_closed": true + "saved_objtypeKey": "IMAGE" }, { "guid": "GUID96239662-853101S6354354", - "deepid": 1934206739, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -255,11 +257,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "IMAGE/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -382,9 +395,6 @@ }, { "guid": "GUID34075349-853103S185294354", - "deepid": -2129229824, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -441,11 +451,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -568,9 +589,6 @@ }, { "guid": "GUID88043540-853107S6554354", - "deepid": 585145805, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -632,6 +650,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "BAR/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -786,14 +810,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "BAR", - "tree_closed": true + "saved_objtypeKey": "BAR" }, { "guid": "GUID59878104-853109S3084354", - "deepid": 666115346, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -850,11 +870,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -977,9 +1008,6 @@ }, { "guid": "GUID86331474-853111S462274354", - "deepid": 321879940, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -1036,11 +1064,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -1171,7 +1210,6 @@ "isPage": true, "editor_posx": 400, "editor_posy": -400, - "dont_export": false, "locked": true, "properties": [ { @@ -1208,6 +1246,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "SCREEN/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -1315,17 +1359,12 @@ }, { "guid": "GUID63572141-853113S4094354", - "deepid": -737127933, "children": [ { "guid": "GUID10271921-68975S5384354", - "deepid": 1511971373, "children": [ { "guid": "GUID70542204-68979S8364354", - "deepid": 1497257154, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -1382,6 +1421,11 @@ "strval": "TOP_LEFT", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -1509,9 +1553,6 @@ }, { "guid": "GUID85409111-68983S431164354", - "deepid": -1585715219, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -1568,6 +1609,11 @@ "strval": "TOP_LEFT", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -1691,14 +1737,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID59467401-68985S7174354", - "deepid": 1628791549, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -1756,190 +1798,9 @@ "InheritedType": 3 }, { - "nid": 90, - "strtype": "OBJECT/Flags", - "InheritedType": 1 - }, - { - "nid": 110, - "strtype": "OBJECT/Clickable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 130, - "strtype": "OBJECT/Press_lock", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 140, - "strtype": "OBJECT/Click_focusable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 210, - "strtype": "OBJECT/Gesture_bubble", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 220, - "strtype": "OBJECT/Snappable", - "strval": "False", - "InheritedType": 2 - }, - { - "nid": 225, - "flags": 1048576, - "strtype": "OBJECT/Scrolling", - "InheritedType": 1 - }, - { - "nid": 300, - "strtype": "OBJECT/Scrollbar_mode", - "strval": "AUTO", - "InheritedType": 3 - }, - { - "nid": 310, - "strtype": "OBJECT/Scroll_direction", - "strval": "ALL", - "InheritedType": 3 - }, - { - "nid": 314, - "strtype": "OBJECT/Scroll_snap_x", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 315, - "strtype": "OBJECT/Scroll_snap_y", - "strval": "NONE", - "InheritedType": 3 - }, - { - "nid": 320, - "flags": 1048576, - "strtype": "OBJECT/States", - "InheritedType": 1 - }, - { - "nid": 1010, - "strtype": "LABEL/Label", - "InheritedType": 1 - }, - { - "nid": 1020, - "strtype": "LABEL/Long_mode", - "strval": "WRAP", - "InheritedType": 3 - }, - { - "nid": 1030, - "strtype": "LABEL/Text", - "strval": "12:34:56", - "InheritedType": 10 - }, - { - "part": "lv.PART.MAIN", - "childs": [ - { - "nid": 10000, - "strtype": "_style/StyleState", - "strval": "DEFAULT", - "childs": [ - { - "nid": 10410, - "strtype": "_style/Text_Color", - "intarray": [ - 255, - 255, - 255, - 255 - ], - "InheritedType": 7 - }, - { - "nid": 10450, - "strtype": "_style/Text_Font", - "strval": "montserrat_12", - "InheritedType": 3 - } - ], - "InheritedType": 1 - } - ], - "nid": 1040, - "strtype": "LABEL/Style_main", - "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", - "InheritedType": 11 - } - ], - "saved_objtypeKey": "LABEL" - }, - { - "guid": "GUID78701249-68993S566594354", - "deepid": -314691173, - "dont_export": false, - "locked": false, - "properties": [ - { - "nid": 10, - "strtype": "OBJECT/Name", - "strval": "Image Main Battery", - "InheritedType": 10 - }, - { - "nid": 20, - "strtype": "OBJECT/Layout", - "InheritedType": 1 - }, - { - "Flow": 0, - "Wrap": false, - "Reversed": false, - "MainAlignment": 0, - "CrossAlignment": 0, - "TrackAlignment": 0, - "LayoutType": 0, - "nid": 30, - "strtype": "OBJECT/Layout_type", - "strval": "No_layout", - "InheritedType": 13 - }, - { - "nid": 40, - "strtype": "OBJECT/Transform", - "InheritedType": 1 - }, - { - "nid": 50, - "flags": 17, - "strtype": "OBJECT/Position", - "intarray": [ - 260, - 0 - ], - "InheritedType": 7 - }, - { - "nid": 60, - "flags": 51, - "strtype": "OBJECT/Size", - "intarray": [ - 1, - 1 - ], - "InheritedType": 7 - }, - { - "nid": 70, - "strtype": "OBJECT/Align", - "strval": "TOP_LEFT", - "InheritedType": 3 + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 }, { "nid": 90, @@ -2026,7 +1887,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "B", + "strval": "12:34:56", "InheritedType": 10 }, { @@ -2064,14 +1925,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID38841759-68991S6814354", - "deepid": 478918629, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -2107,7 +1964,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 290, + 280, 0 ], "InheritedType": 7 @@ -2128,6 +1985,11 @@ "strval": "TOP_LEFT", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -2228,12 +2090,9 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -2290,6 +2149,11 @@ "strval": "TOP_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -2414,17 +2278,12 @@ }, { "guid": "GUID69843562-430548S5034357", - "deepid": 1933161859, "children": [ { "guid": "GUID40000558-68999S1814355", - "deepid": -1577322599, "children": [ { "guid": "GUID90690797-862847S1705954", - "deepid": 1275935300, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -2481,6 +2340,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -2599,14 +2463,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "PANEL", - "tree_closed": true + "saved_objtypeKey": "PANEL" }, { "guid": "GUID41153353-862846S1193154", - "deepid": 1275935300, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -2663,6 +2523,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -2781,14 +2646,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "PANEL", - "tree_closed": true + "saved_objtypeKey": "PANEL" }, { "guid": "GUID326283-862848S2227654", - "deepid": 1275935300, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -2845,6 +2706,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -2963,14 +2829,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "PANEL", - "tree_closed": true + "saved_objtypeKey": "PANEL" }, { "guid": "GUID34728151-155431S6754356", - "deepid": 1275935300, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -3027,6 +2889,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -3145,14 +3012,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "PANEL", - "tree_closed": true + "saved_objtypeKey": "PANEL" }, { "guid": "GUID49515181-98916S7624362", - "deepid": 869040931, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -3209,6 +3072,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -3302,9 +3170,6 @@ }, { "guid": "GUID79401473-98918S8004362", - "deepid": -262194236, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -3361,6 +3226,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -3465,13 +3335,9 @@ }, { "guid": "GUID87870619-989445S5396453", - "deepid": 565092003, "children": [ { "guid": "GUID1108541-989447S92453", - "deepid": -1719762389, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -3528,6 +3394,11 @@ "strval": "LEFT_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -3649,9 +3520,6 @@ }, { "guid": "GUID15732503-989449S57553", - "deepid": -1719762389, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -3708,6 +3576,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -3818,9 +3691,6 @@ }, { "guid": "GUID77339875-989450S1050253", - "deepid": -1719762389, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -3877,6 +3747,11 @@ "strval": "RIGHT_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -3997,8 +3872,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -4055,6 +3928,11 @@ "strval": "BOTTOM_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -4129,8 +4007,6 @@ "saved_objtypeKey": "CONTAINER" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -4187,6 +4063,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -4357,13 +4238,9 @@ }, { "guid": "GUID78751988-155420S8764356", - "deepid": -1253876820, "children": [ { "guid": "GUID884834-155424S6724356", - "deepid": 809747492, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -4420,6 +4297,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -4532,14 +4414,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID79834816-155425S5454356", - "deepid": -1310920733, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -4596,6 +4474,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -4732,14 +4615,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "IMAGE", - "tree_closed": true + "saved_objtypeKey": "IMAGE" }, { "guid": "GUID76026531-155422S4054356", - "deepid": 809747492, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -4796,6 +4675,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -4902,12 +4786,9 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -4964,6 +4845,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -5038,8 +4924,6 @@ "saved_objtypeKey": "CONTAINER" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -5096,6 +4980,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -5171,17 +5060,12 @@ }, { "guid": "GUID12873756-430552S3484357", - "deepid": -741119918, "children": [ { "guid": "GUID15522018-73173S422354359", - "deepid": -755641011, "children": [ { "guid": "GUID60809533-73172S422354359", - "deepid": -1351592592, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -5238,6 +5122,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -5341,8 +5230,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -5399,6 +5286,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -5578,13 +5470,9 @@ }, { "guid": "GUID29848968-155427S6724356", - "deepid": -755641011, "children": [ { "guid": "GUID77308716-155429S1584356", - "deepid": -1351592592, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -5641,6 +5529,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -5744,8 +5637,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -5802,6 +5693,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -5917,13 +5813,9 @@ }, { "guid": "GUID61733416-934770S366964356", - "deepid": -211345156, "children": [ { "guid": "GUID96116950-934769S366964356", - "deepid": 986580644, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -5980,6 +5872,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -6069,12 +5966,9 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -6131,6 +6025,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -6321,13 +6220,9 @@ }, { "guid": "GUID93999632-650710S271964356", - "deepid": -211345156, "children": [ { "guid": "GUID5832432-650712S5674356", - "deepid": 986580644, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -6384,6 +6279,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -6473,12 +6373,9 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -6535,6 +6432,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -6724,8 +6626,6 @@ "saved_objtypeKey": "BUTTON" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -6782,6 +6682,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -6859,8 +6764,6 @@ "isPage": true, "editor_posx": 800, "editor_posy": -400, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -7067,17 +6970,12 @@ }, { "guid": "GUID40629891-934771S164356", - "deepid": 871077125, "children": [ { "guid": "GUID32876125-838323S38634360", - "deepid": 1097060484, "children": [ { "guid": "GUID67585624-838322S38634360", - "deepid": 894182266, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -7134,6 +7032,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -7260,8 +7163,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -7318,6 +7219,11 @@ "strval": "TOP_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", @@ -7452,9 +7358,6 @@ }, { "guid": "GUID16541557-838428S3954360", - "deepid": -1892524658, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -7511,6 +7414,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -7586,17 +7494,12 @@ }, { "guid": "GUID84576620-989468S627153", - "deepid": -741119918, "children": [ { "guid": "GUID258430-989467S627153", - "deepid": -211345156, "children": [ { "guid": "GUID30745183-989466S627153", - "deepid": 986580644, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -7653,6 +7556,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -7742,12 +7650,9 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -7804,6 +7709,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -7993,8 +7903,6 @@ "saved_objtypeKey": "BUTTON" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -8051,6 +7959,11 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, @@ -8128,8 +8041,6 @@ "isPage": true, "editor_posx": 1200, "editor_posy": -400, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -8411,17 +8322,12 @@ }, { "guid": "GUID10820859-155348S7984356", - "deepid": -1552217072, "children": [ { "guid": "GUID98621717-155354S7474356", - "deepid": 1097060484, "children": [ { "guid": "GUID15718204-155356S9244356", - "deepid": 894182266, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -8478,11 +8384,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -8604,8 +8521,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -8662,11 +8577,22 @@ "strval": "TOP_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -8796,17 +8722,12 @@ }, { "guid": "GUID28971676-155358S944356", - "deepid": 612547169, "children": [ { "guid": "GUID70698399-430607S5284357", - "deepid": 1127433331, "children": [ { "guid": "GUID72017967-430596S5254357", - "deepid": -467179531, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -8863,11 +8784,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -8986,22 +8918,16 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID64856691-430605S5284357", - "deepid": 1755922259, "children": [ { "guid": "GUID83225215-430600S5254357", - "deepid": 1424256055, "children": [ { "guid": "GUID95020504-430597S5254357", - "deepid": -567540342, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -9058,11 +8984,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -9192,14 +9129,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID55120083-47164S4384359", - "deepid": -567540342, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -9256,11 +9189,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -9390,14 +9334,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID56191097-584542S741516", - "deepid": -567540342, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -9454,11 +9394,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -9588,12 +9539,9 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -9650,11 +9598,22 @@ "strval": "LEFT_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -9748,13 +9707,9 @@ }, { "guid": "GUID62902718-430604S5284357", - "deepid": 398216300, "children": [ { "guid": "GUID41923710-430601S5284357", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -9811,11 +9766,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -9955,9 +9921,6 @@ }, { "guid": "GUID97387059-584544S524516", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -10014,11 +9977,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -10158,9 +10132,6 @@ }, { "guid": "GUID64451864-584545S24208516", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -10217,11 +10188,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -10360,8 +10342,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -10418,11 +10398,22 @@ "strval": "RIGHT_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -10515,8 +10506,6 @@ "saved_objtypeKey": "CONTAINER" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -10573,12 +10562,23 @@ "strval": "TOP_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -10667,8 +10667,6 @@ "saved_objtypeKey": "CONTAINER" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -10725,12 +10723,23 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -10879,13 +10888,9 @@ }, { "guid": "GUID57862356-155360S1954356", - "deepid": 1127433331, "children": [ { "guid": "GUID71204662-155362S3724356", - "deepid": -467179531, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -10942,11 +10947,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -11065,22 +11081,16 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID64214999-155378S3394356", - "deepid": 1755922259, "children": [ { "guid": "GUID53593748-155370S562344356", - "deepid": 1424256055, "children": [ { "guid": "GUID91214090-155380S114356", - "deepid": -567540342, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -11137,11 +11147,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -11271,14 +11292,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID48938903-155382S2754356", - "deepid": -422483377, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -11335,11 +11352,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -11473,9 +11501,6 @@ }, { "guid": "GUID95955079-155384S188854356", - "deepid": -1993817609, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -11532,11 +11557,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -11669,8 +11705,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -11727,11 +11761,22 @@ "strval": "LEFT_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -11825,13 +11870,9 @@ }, { "guid": "GUID61454612-155376S624356", - "deepid": 398216300, "children": [ { "guid": "GUID69353012-155390S9964356", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -11888,11 +11929,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -12032,9 +12084,6 @@ }, { "guid": "GUID31824688-155392S5694356", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -12091,11 +12140,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -12235,9 +12295,6 @@ }, { "guid": "GUID1425477-155393S19884356", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -12294,11 +12351,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -12437,8 +12505,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -12495,11 +12561,22 @@ "strval": "RIGHT_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -12592,8 +12669,6 @@ "saved_objtypeKey": "CONTAINER" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -12650,12 +12725,23 @@ "strval": "TOP_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -12745,9 +12831,6 @@ }, { "guid": "GUID34128925-155388S7674356", - "deepid": -249429836, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -12810,6 +12893,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "BAR/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -12976,8 +13065,6 @@ "saved_objtypeKey": "BAR" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -13034,12 +13121,23 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -13188,13 +13286,9 @@ }, { "guid": "GUID44018081-155417S20174356", - "deepid": 1127433331, "children": [ { "guid": "GUID18558271-155406S20134356", - "deepid": -467179531, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -13251,11 +13345,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -13374,22 +13479,16 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID43255-155453S4464356", - "deepid": 1865632034, "children": [ { "guid": "GUID70722931-155449S3594356", - "deepid": -969207466, "children": [ { "guid": "GUID7903402-155437S25564356", - "deepid": -567540342, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -13446,11 +13545,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -13580,14 +13690,10 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" }, { "guid": "GUID29520723-155438S25564356", - "deepid": -422483377, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -13644,11 +13750,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -13782,9 +13899,6 @@ }, { "guid": "GUID44302939-208082S5004365", - "deepid": -422483377, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -13841,11 +13955,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -13979,9 +14104,6 @@ }, { "guid": "GUID94008783-430544S7064357", - "deepid": -422483377, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -14038,11 +14160,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -14176,9 +14309,6 @@ }, { "guid": "GUID52254882-430562S8524357", - "deepid": -422483377, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -14235,11 +14365,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -14373,9 +14514,6 @@ }, { "guid": "GUID68439637-430563S113094357", - "deepid": -422483377, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -14432,11 +14570,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -14569,8 +14718,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -14627,12 +14774,23 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -14702,13 +14860,9 @@ }, { "guid": "GUID93580312-155451S318044356", - "deepid": 1436268651, "children": [ { "guid": "GUID84647470-155445S108144356", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -14765,11 +14919,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -14909,9 +15074,6 @@ }, { "guid": "GUID97949053-155446S108144356", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -14968,11 +15130,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -15112,9 +15285,6 @@ }, { "guid": "GUID43761664-208083S206274365", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -15171,11 +15341,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -15315,9 +15496,6 @@ }, { "guid": "GUID13171702-430545S82544357", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -15374,11 +15552,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -15518,9 +15707,6 @@ }, { "guid": "GUID86685667-430564S195944357", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -15577,11 +15763,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -15721,9 +15918,6 @@ }, { "guid": "GUID453239-430565S279304357", - "deepid": -1317032992, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -15780,11 +15974,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -15923,8 +16128,6 @@ "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -15981,12 +16184,23 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -16055,8 +16269,6 @@ "saved_objtypeKey": "CONTAINER" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -16113,12 +16325,23 @@ "strval": "TOP_MID", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -16187,8 +16410,6 @@ "saved_objtypeKey": "CONTAINER" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -16245,12 +16466,23 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -16398,8 +16630,6 @@ "saved_objtypeKey": "PANEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -16456,11 +16686,22 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -16594,17 +16835,12 @@ }, { "guid": "GUID26295868-989474S771453", - "deepid": -741119918, "children": [ { "guid": "GUID79481689-989473S771453", - "deepid": -211345156, "children": [ { "guid": "GUID14912377-989472S771453", - "deepid": 986580644, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -16661,12 +16897,23 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -16750,12 +16997,9 @@ "InheritedType": 11 } ], - "saved_objtypeKey": "LABEL", - "tree_closed": true + "saved_objtypeKey": "LABEL" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -16812,12 +17056,23 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "BUTTON/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -17001,8 +17256,6 @@ "saved_objtypeKey": "BUTTON" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -17059,12 +17312,23 @@ "strval": "CENTER", "InheritedType": 3 }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, { "nid": 90, "flags": 1048576, "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -17136,8 +17400,6 @@ "isPage": true, "editor_posx": 800, "editor_posy": -740, - "dont_export": false, - "locked": false, "properties": [ { "nid": 10, @@ -17173,6 +17435,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "SCREEN/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -17419,8 +17687,6 @@ "saved_objtypeKey": "SCREEN" } ], - "dont_export": false, - "locked": false, "properties": [ { "nid": 1000201, @@ -17433,6 +17699,7 @@ }, "animations": [], "selected_theme": "Default", + "selected_screen": "GUID63572141-853113S4094354", "info": { "name": "SquareLine_Project.spj", "depth": 1, @@ -17446,7 +17713,7 @@ "description": "", "board": "ESP WROVER KIT", "board_version": "2.0.0", - "editor_version": "1.5.4", + "editor_version": "1.6.0", "image": "", "export_temp_image": false, "force_export_images": false, @@ -17458,9 +17725,12 @@ "theme_color1": 5, "theme_color2": 0, "custom_variable_prefix": "uic", - "backup_cnt": 72, + "separate_screen_save": false, + "hierarchy_state_save": false, + "backup_cnt": 73, "autosave_cnt": 0, "group_color_cnt": 0, + "imagebytearrayprefix": null, "lvgl_version": "9.1.0", "callfuncsexport": "CPP_FILE", "imageexport": "SOURCE", diff --git a/ui/project.info b/ui/project.info index 5bb3305..97571ee 100644 --- a/ui/project.info +++ b/ui/project.info @@ -1,7 +1,7 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-01-16T13:29:19.5084763+01:00", - "editor_version": "1.5.4", - "project_version": 94, + "datetime": "2026-01-29T19:31:57.7621353+01:00", + "editor_version": "1.6.0", + "project_version": 95, "user": "Kampert Daniel" } \ No newline at end of file From 2cad09d8731f5ea39a86792b059207c4777b1aa9 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Thu, 5 Feb 2026 22:44:20 +0100 Subject: [PATCH 09/26] Add first version of settings menu --- .github/copilot-instructions.md | 9 +- README.md | 14 + main/Application/Manager/Devices/ADC/adc.h | 12 +- .../Devices/PortExpander/portexpander.h | 21 +- .../Server/ImageEncoder/imageEncoder.cpp | 60 +- .../Manager/Network/Server/http_server.cpp | 14 +- .../Manager/Network/Server/http_server.h | 4 +- .../Manager/Network/Server/server.h | 11 +- .../Network/Server/websocket_handler.cpp | 9 +- .../Manager/Network/networkTypes.h | 41 +- .../Private/settingsDefaultLoader.cpp | 4 +- .../Settings/Private/settingsJSONLoader.cpp | 2 + .../Manager/Settings/Private/settingsLoader.h | 2 + .../Manager/Settings/settingsManager.cpp | 21 +- .../Manager/Settings/settingsManager.h | 16 +- .../Manager/Settings/settingsTypes.h | 28 +- main/Application/Tasks/Devices/devicesTask.h | 14 + .../Application/Tasks/GUI/Export/project.info | 8 +- .../Tasks/GUI/Export/screens/ui_Info.c | 215 ++- .../Tasks/GUI/Export/screens/ui_Info.h | 6 +- .../Tasks/GUI/Export/screens/ui_Main.c | 20 +- .../Tasks/GUI/Export/screens/ui_Menu.c | 41 +- .../Tasks/GUI/Export/screens/ui_Menu.h | 3 + .../Tasks/GUI/Export/screens/ui_Splash.c | 10 + .../Tasks/GUI/Export/screens/ui_Splash.h | 1 + .../Tasks/GUI/Export/ui_events.cpp | 17 +- main/Application/Tasks/GUI/Export/ui_events.h | 3 +- .../Tasks/GUI/Private/guiHelper.cpp | 49 +- .../GUI/UI/Private/ui_Settings_Events.cpp | 135 ++ .../Tasks/GUI/UI/Private/ui_Settings_Events.h | 78 + main/Application/Tasks/GUI/UI/ui_Settings.cpp | 448 +++++ main/Application/Tasks/GUI/UI/ui_Settings.h | 38 + main/Application/Tasks/GUI/guiTask.cpp | 261 +-- main/Application/Tasks/Lepton/leptonTask.cpp | 79 +- .../Application/Tasks/Network/networkTask.cpp | 32 +- main/Application/application.h | 12 +- main/Kconfig.projbuild | 4 +- sdkconfig.debug | 10 +- ui/PyroVision.sll | 6 +- ui/PyroVision.spj | 1456 ++++++++++++++--- ui/PyroVision_events.py | 12 + ui/project.info | 4 +- 42 files changed, 2670 insertions(+), 560 deletions(-) create mode 100644 main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp create mode 100644 main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h create mode 100644 main/Application/Tasks/GUI/UI/ui_Settings.cpp create mode 100644 main/Application/Tasks/GUI/UI/ui_Settings.h diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b2f425d..4d804cb 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -622,11 +622,17 @@ Documentation is automatically built and deployed via GitHub Actions workflow (` **CRITICAL**: After making ANY code changes, you MUST perform the following validation steps: -#### 1. Syntax Validation +#### 1. Syntax and Spelling Validation - Verify code compiles without errors using `pio run` or `idf.py build` - Check for correct bracket matching, semicolons, and C++ syntax - Validate all include statements and dependencies - Ensure no missing header files or forward declarations +- **Check for spelling errors** in: + - Variable names, function names, and type names + - Comments and documentation strings + - String literals and user-facing messages + - Log messages (TAG names, error messages) +- Use consistent spelling and terminology across the codebase #### 2. Error and Warning Analysis - **Zero tolerance for compiler warnings** - all warnings must be addressed @@ -654,6 +660,7 @@ Documentation is automatically built and deployed via GitHub Actions workflow (` ``` ☐ Code compiles without errors (pio run -e debug) ☐ No compiler warnings introduced +☐ No spelling errors in code, comments, or documentation ☐ All new/modified functions have complete Doxygen documentation ☐ All return values and parameters documented ☐ Error handling implemented for all ESP-IDF calls diff --git a/README.md b/README.md index 21ac99a..c0f09ef 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ - [PyroVision - Firmware](#pyrovision---firmware) - [Table of Contents](#table-of-contents) - [License](#license) + - [Color palette](#color-palette) - [Maintainer](#maintainer) ## License @@ -17,6 +18,19 @@ This project is licensed under the **GNU General Public License v3.0**. See [LICENSE](LICENSE) for full text. +## Color palette + +| Name | Hex | Description | +| ------------------ | ------- | ---------------------------- | +| Violet | #7B3FF0 | Primary color, iconic accents | +| Blue | #2196F3 | Cool heatmap colors | +| Red | #FF3B3B | Heat/hotspots | +| Orange | #FF9500 | Medium heat | +| Yellow | #FFD500 | Maximum hot areas | +| Light Purple | #B998FF | Accent color | +| Light Red/Orange | #FF6F3C | Accent color | +| Dark Gray/Black | #1E1E1E | Background color | + ## Maintainer **Daniel Kampert** diff --git a/main/Application/Manager/Devices/ADC/adc.h b/main/Application/Manager/Devices/ADC/adc.h index 5c6c76e..8dc7e41 100644 --- a/main/Application/Manager/Devices/ADC/adc.h +++ b/main/Application/Manager/Devices/ADC/adc.h @@ -29,14 +29,20 @@ #include +/** @brief Initializes the ADC driver. + * @return ESP_OK on success, error code otherwise + */ esp_err_t ADC_Init(void); +/** @brief Deinitializes the ADC driver. + * @return ESP_OK on success, error code otherwise + */ esp_err_t ADC_Deinit(void); -/** @brief Read battery voltage and calculate percentage - * @param p_Voltage Pointer to store battery voltage in mV +/** @brief Read battery voltage and calculate percentage + * @param p_Voltage Pointer to store battery voltage in mV * @param p_Percentage Pointer to store battery percentage (0-100%) - * @return ESP_OK on success + * @return ESP_OK on success, error code otherwise */ esp_err_t ADC_ReadBattery(int *p_Voltage, uint8_t *p_Percentage); diff --git a/main/Application/Manager/Devices/PortExpander/portexpander.h b/main/Application/Manager/Devices/PortExpander/portexpander.h index 3d90a95..0128c1b 100644 --- a/main/Application/Manager/Devices/PortExpander/portexpander.h +++ b/main/Application/Manager/Devices/PortExpander/portexpander.h @@ -28,20 +28,39 @@ #include "../I2C/i2c.h" +/** @brief Initializes the port expander driver. + * @param p_Config Pointer to the I2C master bus configuration. + * @param Bus_Handle Pointer to the I2C master bus handle. + * @return ESP_OK on success, error code otherwise + */ esp_err_t PortExpander_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *Bus_Handle); +/** @brief Deinitializes the port expander driver. + * @return ESP_OK on success, error code otherwise + */ esp_err_t PortExpander_Deinit(void); #ifdef DEBUG -/** @brief Dump the content of the registers from the Port Expander. +/** @brief Dump the content of the registers from the Port Expander. */ void PortExpander_DumpRegister(void); #endif +/** @brief Sets the port expander to its default configuration. + * @return ESP_OK on success, error code otherwise + */ esp_err_t PortExpander_DefaultConfig(void); +/** @brief Enables or disables the LED. + * @param Enable true to enable the LED, false to disable it. + * @return ESP_OK on success, error code otherwise + */ esp_err_t PortExpander_EnableLED(bool Enable); +/** @brief + * @param Enable true to enable battery voltage measurement, false to disable it. + * @return ESP_OK on success, error code otherwise + */ esp_err_t PortExpander_EnableBatteryVoltage(bool Enable); #endif /* PORTEXPANDER_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp b/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp index 5b41e8a..d20812b 100644 --- a/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp +++ b/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp @@ -67,32 +67,32 @@ static esp_err_t ImageEncoder_ApplyPalette(const Network_Thermal_Frame_t *p_Fram Server_Palette_t palette, uint8_t *p_Output) { - if ((p_Frame == NULL) || (p_Output == NULL) || (p_Frame->buffer == NULL)) { + if ((p_Frame == NULL) || (p_Output == NULL) || (p_Frame->Buffer == NULL)) { return ESP_ERR_INVALID_ARG; } - memcpy(p_Output, p_Frame->buffer, p_Frame->width * p_Frame->height * 3); + memcpy(p_Output, p_Frame->Buffer, p_Frame->Width * p_Frame->Height * 3); return ESP_OK; } /** @brief Encode RGB data to JPEG. * @param p_RGB RGB pixel data - * @param width Image width - * @param height Image height - * @param quality JPEG quality (1-100) + * @param Width Image width + * @param Height Image height + * @param Quality JPEG quality (1-100) * @param p_Encoded Output encoded image * @return ESP_OK on success */ -static esp_err_t ImageEncoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, uint16_t height, - uint8_t quality, Network_Encoded_Image_t *p_Encoded) +static esp_err_t ImageEncoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t Width, uint16_t Height, + uint8_t Quality, Network_Encoded_Image_t *p_Encoded) { jpeg_enc_config_t enc_config = { - .width = width, - .height = height, + .width = Width, + .height = Height, .src_type = JPEG_PIXEL_FORMAT_RGB888, .subsampling = JPEG_SUBSAMPLE_420, - .quality = quality, + .quality = Quality, .rotate = JPEG_ROTATE_0D, .task_enable = false, .hfm_task_priority = 0, @@ -106,29 +106,29 @@ static esp_err_t ImageEncoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t width, u return ESP_FAIL; } ; - p_Encoded->data = (uint8_t *)heap_caps_malloc(width * height * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (p_Encoded->data == NULL) { + p_Encoded->Data = (uint8_t *)heap_caps_malloc(Width * Height * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (p_Encoded->Data == NULL) { jpeg_enc_close(encoder); ESP_LOGE(TAG, "Failed to allocate JPEG output buffer!"); return ESP_ERR_NO_MEM; } int out_size = 0; - err = jpeg_enc_process(encoder, p_RGB, width * height * 3, p_Encoded->data, width * height * 3, &out_size); + err = jpeg_enc_process(encoder, p_RGB, Width * Height * 3, p_Encoded->Data, Width * Height * 3, &out_size); jpeg_enc_close(encoder); if (err != JPEG_ERR_OK) { - heap_caps_free(p_Encoded->data); - p_Encoded->data = NULL; + heap_caps_free(p_Encoded->Data); + p_Encoded->Data = NULL; ESP_LOGE(TAG, "JPEG encoding failed: %d!", err); return ESP_FAIL; } - p_Encoded->size = out_size; - p_Encoded->format = NETWORK_IMAGE_FORMAT_JPEG; - p_Encoded->width = width; - p_Encoded->height = height; + p_Encoded->Size = out_size; + p_Encoded->Format = NETWORK_IMAGE_FORMAT_JPEG; + p_Encoded->Width = Width; + p_Encoded->Height = Height; return ESP_OK; } @@ -180,7 +180,7 @@ esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, memset(p_Encoded, 0, sizeof(Network_Encoded_Image_t)); - size_t pixel_count = p_Frame->width * p_Frame->height; + size_t pixel_count = p_Frame->Width * p_Frame->Height; uint8_t *rgb_buffer = (uint8_t *)heap_caps_malloc(pixel_count * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (rgb_buffer == NULL) { @@ -196,7 +196,7 @@ esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, switch (Format) { case NETWORK_IMAGE_FORMAT_JPEG: { - Error = ImageEncoder_EncodeJPEG(rgb_buffer, p_Frame->width, p_Frame->height, + Error = ImageEncoder_EncodeJPEG(rgb_buffer, p_Frame->Width, p_Frame->Height, _Encoder_State.JpegQuality, p_Encoded); break; } @@ -208,11 +208,11 @@ esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, case NETWORK_IMAGE_FORMAT_RAW: default: { /* Return raw RGB data */ - p_Encoded->data = rgb_buffer; - p_Encoded->size = pixel_count * 3; - p_Encoded->format = NETWORK_IMAGE_FORMAT_RAW; - p_Encoded->width = p_Frame->width; - p_Encoded->height = p_Frame->height; + p_Encoded->Data = rgb_buffer; + p_Encoded->Size = pixel_count * 3; + p_Encoded->Format = NETWORK_IMAGE_FORMAT_RAW; + p_Encoded->Width = p_Frame->Width; + p_Encoded->Height = p_Frame->Height; return ESP_OK; } @@ -229,12 +229,12 @@ void ImageEncoder_Free(Network_Encoded_Image_t *p_Encoded) return; } - if (p_Encoded->data != NULL) { - heap_caps_free(p_Encoded->data); - p_Encoded->data = NULL; + if (p_Encoded->Data != NULL) { + heap_caps_free(p_Encoded->Data); + p_Encoded->Data = NULL; } - p_Encoded->size = 0; + p_Encoded->Size = 0; } void ImageEncoder_SetQuality(uint8_t Quality) diff --git a/main/Application/Manager/Network/Server/http_server.cpp b/main/Application/Manager/Network/Server/http_server.cpp index e06e82a..170f951 100644 --- a/main/Application/Manager/Network/Server/http_server.cpp +++ b/main/Application/Manager/Network/Server/http_server.cpp @@ -253,13 +253,13 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) } } - if (xSemaphoreTake(_HTTPServer_State.ThermalFrame->mutex, 100 / portTICK_PERIOD_MS) != pdTRUE) { + if (xSemaphoreTake(_HTTPServer_State.ThermalFrame->Mutex, 100 / portTICK_PERIOD_MS) != pdTRUE) { return HTTP_Server_SendError(p_Request, 503, "Frame busy"); } Error = ImageEncoder_Encode(_HTTPServer_State.ThermalFrame, format, palette, &encoded); - xSemaphoreGive(_HTTPServer_State.ThermalFrame->mutex); + xSemaphoreGive(_HTTPServer_State.ThermalFrame->Mutex); if (Error != ESP_OK) { return HTTP_Server_SendError(p_Request, 500, "Image encoding failed"); @@ -283,7 +283,7 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) } /* Send image data */ - Error = httpd_resp_send(p_Request, (const char *)encoded.data, encoded.size); + Error = httpd_resp_send(p_Request, (const char *)encoded.Data, encoded.Size); ImageEncoder_Free(&encoded); @@ -304,22 +304,19 @@ static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); } - /* Build telemetry response */ cJSON *json = cJSON_CreateObject(); - /* Uptime */ uint32_t uptime = (esp_timer_get_time() / 1000000); cJSON_AddNumberToObject(json, "uptime_s", uptime); /* Sensor temperature (from thermal frame if available) */ if (_HTTPServer_State.ThermalFrame != NULL) { - cJSON_AddNumberToObject(json, "sensor_temp_c", _HTTPServer_State.ThermalFrame->temp_avg); + // TODO + //cJSON_AddNumberToObject(json, "sensor_temp_c", _HTTPServer_State.ThermalFrame->temp_avg); } - /* Supply voltage (placeholder) */ cJSON_AddNumberToObject(json, "supply_voltage_v", 0); - /* WiFi RSSI */ wifi_ap_record_t ap_info; if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { cJSON_AddNumberToObject(json, "wifi_rssi_dbm", ap_info.rssi); @@ -327,7 +324,6 @@ static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) cJSON_AddNumberToObject(json, "wifi_rssi_dbm", 0); } - /* SD card info (placeholder) */ cJSON *sdcard = cJSON_CreateObject(); cJSON_AddBoolToObject(sdcard, "present", false); cJSON_AddNumberToObject(sdcard, "free_mb", 0); diff --git a/main/Application/Manager/Network/Server/http_server.h b/main/Application/Manager/Network/Server/http_server.h index 01580b6..6194e13 100644 --- a/main/Application/Manager/Network/Server/http_server.h +++ b/main/Application/Manager/Network/Server/http_server.h @@ -54,8 +54,8 @@ esp_err_t HTTP_Server_Stop(void); */ bool HTTP_Server_isRunning(void); -/** @brief Set thermal frame data for image endpoint. - * @param p_Frame Pointer to thermal frame data. +/** @brief Set thermal frame data for image endpoint. + * @param p_Frame Pointer to thermal frame data. */ void HTTP_Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame); diff --git a/main/Application/Manager/Network/Server/server.h b/main/Application/Manager/Network/Server/server.h index 5fe3515..32e36a0 100644 --- a/main/Application/Manager/Network/Server/server.h +++ b/main/Application/Manager/Network/Server/server.h @@ -123,7 +123,7 @@ static inline bool Server_isRunning(void) return HTTP_Server_isRunning(); } -/** @brief Set thermal frame data for both HTTP and WebSocket endpoints. +/** @brief Set the thermal frame data for both HTTP and WebSocket endpoints. * @param p_Frame Pointer to thermal frame data */ static inline void Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) @@ -132,4 +132,13 @@ static inline void Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) WebSocket_Handler_SetThermalFrame(p_Frame); } +/** @brief Notify all clients that a new frame is ready (non-blocking). + */ +static inline void Server_NotifyClients(void) +{ + if (WebSocket_Handler_HasClients()) { + WebSocket_Handler_NotifyFrameReady(); + } +} + #endif /* SERVER_H_ */ diff --git a/main/Application/Manager/Network/Server/websocket_handler.cpp b/main/Application/Manager/Network/Server/websocket_handler.cpp index a9db677..0bf9bfb 100644 --- a/main/Application/Manager/Network/Server/websocket_handler.cpp +++ b/main/Application/Manager/Network/Server/websocket_handler.cpp @@ -589,10 +589,10 @@ static void WS_BroadcastTask(void *p_Param) } /* Encode frame ONCE for all clients (assume JPEG format for simplicity) */ - if (xSemaphoreTake(_WSHandler_State.ThermalFrame->mutex, 50 / portTICK_PERIOD_MS) == pdTRUE) { + if (xSemaphoreTake(_WSHandler_State.ThermalFrame->Mutex, 50 / portTICK_PERIOD_MS) == pdTRUE) { esp_err_t err = ImageEncoder_Encode(_WSHandler_State.ThermalFrame, NETWORK_IMAGE_FORMAT_JPEG, PALETTE_IRON, &Encoded); - xSemaphoreGive(_WSHandler_State.ThermalFrame->mutex); + xSemaphoreGive(_WSHandler_State.ThermalFrame->Mutex); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to encode frame: %d!", err); @@ -622,7 +622,7 @@ static void WS_BroadcastTask(void *p_Param) uint8_t client_idx = i; xSemaphoreGive(_WSHandler_State.ClientsMutex); - esp_err_t send_err = WS_SendBinary(client_fd, Encoded.data, Encoded.size); + esp_err_t send_err = WS_SendBinary(client_fd, Encoded.Data, Encoded.Size); xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); /* Re-validate client is still active and same FD */ @@ -690,7 +690,8 @@ esp_err_t WebSocket_Handler_BroadcastTelemetry(void) cJSON *data = cJSON_CreateObject(); if (_WSHandler_State.ThermalFrame != NULL) { - cJSON_AddNumberToObject(data, "temp", _WSHandler_State.ThermalFrame->temp_avg); + // TODO + //cJSON_AddNumberToObject(data, "temp", _WSHandler_State.ThermalFrame->temp_avg); } xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); diff --git a/main/Application/Manager/Network/networkTypes.h b/main/Application/Manager/Network/networkTypes.h index cfcb0ec..20be394 100644 --- a/main/Application/Manager/Network/networkTypes.h +++ b/main/Application/Manager/Network/networkTypes.h @@ -130,24 +130,26 @@ typedef enum { /** @brief Thermal frame data structure. */ typedef struct { - uint8_t *buffer; /**< Pointer to RGB888 image data */ - uint16_t width; /**< Frame width in pixels */ - uint16_t height; /**< Frame height in pixels */ - float temp_min; /**< Minimum temperature in frame */ - float temp_max; /**< Maximum temperature in frame */ - float temp_avg; /**< Average temperature in frame */ - uint32_t timestamp; /**< Timestamp in milliseconds */ - SemaphoreHandle_t mutex; /**< Mutex for thread-safe access */ + uint8_t *Buffer; /**< Pointer to RGB888 image data */ + uint16_t Width; /**< Frame width in pixels */ + uint16_t Height; /**< Frame height in pixels */ + uint32_t Timestamp; /**< Timestamp in milliseconds */ + SemaphoreHandle_t Mutex; /**< Mutex for thread-safe access */ } Network_Thermal_Frame_t; +/** @brief Thermal telemetry data structure. + */ +typedef struct { +} Network_Thermal_Telemetry_t; + /** @brief Encoded image data. */ typedef struct { - uint8_t *data; /**< Encoded image data */ - size_t size; /**< Size of encoded data */ - Network_ImageFormat_t format; /**< Image format */ - uint16_t width; /**< Image width */ - uint16_t height; /**< Image height */ + uint8_t *Data; /**< Encoded image data */ + size_t Size; /**< Size of encoded data */ + Network_ImageFormat_t Format; /**< Image format */ + uint16_t Width; /**< Image width */ + uint16_t Height; /**< Image height */ } Network_Encoded_Image_t; /** @brief IP info event data (for NETWORK_EVENT_WIFI_GOT_IP). @@ -164,19 +166,6 @@ typedef struct { uint8_t MAC[6]; } Network_Event_STA_Info_t; -/** @brief OTA progress event data (for NETWORK_EVENT_OTA_PROGRESS). - */ -typedef struct { - uint32_t bytes_written; - uint32_t total_bytes; -} Network_Event_OTA_Progress_t; - -/** @brief WebSocket client event data. - */ -typedef struct { - int client_fd; -} Network_Event_WS_Client_t; - /** @brief WiFi credentials. */ typedef struct { diff --git a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp index 1ca0482..f1a31a0 100644 --- a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp @@ -70,9 +70,11 @@ void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settin { /* No emissiviy values available */ p_Settings->Lepton.EmissivityCount = 1; - p_Settings->Lepton.EmissivityPresets[0].Value = 100.0f; + p_Settings->Lepton.EmissivityPresets[0].Value = 1.0f; strncpy(p_Settings->Lepton.EmissivityPresets[0].Description, "Unknown", sizeof(p_Settings->Lepton.EmissivityPresets[0].Description)); + + p_Settings->Lepton.CurrentEmissivity = SETTINGS_DEFAULT_LEPTON_EMISSIVITY; } void SettingsManager_InitDefaults(SettingsManager_State_t *p_State) diff --git a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp index f60fc1a..d2b89c5 100644 --- a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp @@ -79,6 +79,8 @@ static void SettingsManager_LoadLepton(SettingsManager_State_t *p_State, const c ESP_LOGD(TAG, " Preset %d: %s = %.2f", i, name->valuestring, value->valuedouble); } } + + p_State->Settings.Lepton.CurrentEmissivity = SETTINGS_DEFAULT_LEPTON_EMISSIVITY; } else { SettingsManager_InitDefaultLeptonEmissivityPresets(&p_State->Settings); } diff --git a/main/Application/Manager/Settings/Private/settingsLoader.h b/main/Application/Manager/Settings/Private/settingsLoader.h index e0b426a..c3a683f 100644 --- a/main/Application/Manager/Settings/Private/settingsLoader.h +++ b/main/Application/Manager/Settings/Private/settingsLoader.h @@ -36,6 +36,8 @@ #include "../settingsTypes.h" +#define SETTINGS_DEFAULT_LEPTON_EMISSIVITY 100 + #define SETTINGS_DEFAULT_VISA_PORT 5025 #define SETTINGS_DEFAULT_HTTP_PORT 80 diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index 9045ed5..a611d65 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -43,14 +43,15 @@ ESP_EVENT_DEFINE_BASE(SETTINGS_EVENTS); static SettingsManager_State_t _State; -/** @brief Update a specific settings section in the Settings Manager RAM and emit the corresponding event. - * @param p_Src Pointer to source settings structure - * @param p_Dst Pointer to destination settings structure in RAM - * @param Size Size of the settings structure to copy - * @param EventID Event identifier to emit after update - * @return ESP_OK on success +/** @brief Update a specific settings section in the Settings Manager RAM and emit the corresponding event. + * @param p_Src Pointer to source settings structure + * @param p_Dst Pointer to destination settings structure in RAM + * @param Size Size of the settings structure to copy + * @param EventID Event identifier to emit after update + * @param p_ChangedSetting Pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) + * @return ESP_OK on success */ -static esp_err_t SettingsManager_Update(void* p_Src, void* p_Dst, size_t Size, int EventID) +static esp_err_t SettingsManager_Update(void* p_Src, void* p_Dst, size_t Size, int EventID, SettingsManager_Setting_t* p_ChangedSetting = NULL) { if (_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; @@ -64,7 +65,7 @@ static esp_err_t SettingsManager_Update(void* p_Src, void* p_Dst, size_t Size, i xSemaphoreGive(_State.Mutex); - esp_event_post(SETTINGS_EVENTS, EventID, p_Dst, Size, portMAX_DELAY); + esp_event_post(SETTINGS_EVENTS, EventID, p_ChangedSetting, sizeof(SettingsManager_Setting_t), portMAX_DELAY); return ESP_OK; } @@ -288,10 +289,10 @@ esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings) return ESP_OK; } -esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings) +esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings, SettingsManager_Setting_t* p_ChangedSetting) { return SettingsManager_Update(p_Settings, &_State.Settings.Lepton, sizeof(App_Settings_Lepton_t), - SETTINGS_EVENT_LEPTON_CHANGED); + SETTINGS_EVENT_LEPTON_CHANGED, p_ChangedSetting); } esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t* p_Settings) diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h index 884634d..3303344 100644 --- a/main/Application/Manager/Settings/settingsManager.h +++ b/main/Application/Manager/Settings/settingsManager.h @@ -62,11 +62,13 @@ esp_err_t SettingsManager_GetInfo(App_Settings_Info_t* p_Settings); */ esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings); -/** @brief Update Lepton settings in the Settings Manager RAM. - * @param p_Settings Pointer to Lepton settings structure - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Update Lepton settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_LEPTON_CHANGED event. + * @param p_Settings Pointer to Lepton settings structure + * @param p_ChangedSetting Optional pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings); +esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings, SettingsManager_Setting_t* p_ChangedSetting = NULL); /** @brief Get the WiFi settings from the Settings Manager RAM. * @param p_Settings Pointer to WiFi settings structure to populate @@ -75,6 +77,7 @@ esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings); esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t* p_Settings); /** @brief Update WiFi settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_WIFI_CHANGED event. * @param p_Settings Pointer to WiFi settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ @@ -87,6 +90,7 @@ esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t* p_Settings); esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t* p_Settings); /** @brief Update Provisioning settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_PROVISIONING_CHANGED event. * @param p_Settings Pointer to Provisioning settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ @@ -99,6 +103,7 @@ esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t* p_Sett esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t* p_Settings); /** @brief Update Display settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_DISPLAY_CHANGED event. * @param p_Settings Pointer to Display settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ @@ -111,6 +116,7 @@ esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t* p_Settings); esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t* p_Settings); /** @brief Update HTTP Server settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_HTTP_SERVER_CHANGED event. * @param p_Settings Pointer to HTTP Server settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ @@ -123,6 +129,7 @@ esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t* p_Setting esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t* p_Settings); /** @brief Update VISA Server settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_VISA_SERVER_CHANGED event. * @param p_Settings Pointer to VISA Server settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ @@ -135,6 +142,7 @@ esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t* p_Setting esp_err_t SettingsManager_GetSystem(App_Settings_System_t* p_Settings); /** @brief Update System settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_SYSTEM_CHANGED event. * @param p_Settings Pointer to System settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ diff --git a/main/Application/Manager/Settings/settingsTypes.h b/main/Application/Manager/Settings/settingsTypes.h index 7b58ae8..26e1f2c 100644 --- a/main/Application/Manager/Settings/settingsTypes.h +++ b/main/Application/Manager/Settings/settingsTypes.h @@ -40,24 +40,30 @@ enum { SETTINGS_EVENT_LOADED, /**< Settings loaded from NVS. */ SETTINGS_EVENT_SAVED, /**< Settings saved to NVS. */ SETTINGS_EVENT_LEPTON_CHANGED, /**< Lepton settings changed. - Data contains App_Settings_Lepton_t. */ + Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_WIFI_CHANGED, /**< WiFi settings changed. - Data contains App_Settings_WiFi_t. */ + Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_PROVISIONING_CHANGED, /**< Provisioning settings changed. - Data contains App_Settings_Provisioning_t. */ + Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_DISPLAY_CHANGED, /**< Display settings changed. - Data contains App_Settings_Display_t. */ + Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_HTTP_SERVER_CHANGED, /**< HTTP server settings changed. - Data contains App_Settings_HTTP_Server_t. */ + Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_VISA_SERVER_CHANGED, /**< VISA server settings changed. - Data contains App_Settings_VISA_Server_t. */ + Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_SYSTEM_CHANGED, /**< System settings changed. - Data contains App_Settings_System_t. */ + Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_REQUEST_GET, /**< Request to get current settings. */ SETTINGS_EVENT_REQUEST_SAVE, /**< Request to save settings to NVS. */ SETTINGS_EVENT_REQUEST_RESET, /**< Request to reset settings to factory defaults. */ }; +/** @brief Settings identifiers. + */ +enum { + SETTINGS_ID_LEPTON_EMISSIVITY, /**< Emissivity setting changed. Data contains uint8_t with new emissivity value. */ +}; + /** @brief GUI ROI types. */ typedef enum { @@ -67,6 +73,13 @@ typedef enum { ROI_TYPE_VIDEO_FOCUS, /**< Video focus ROI. */ } App_Settings_ROI_Type_t; +/** @brief Structure to hold the modified settings value. + */ +typedef struct { + bool ID; /**< Identifier for the changed setting. */ + uint32_t Value; /**< New value of the changed setting (can be cast to the appropriate type based on ID). */ +} SettingsManager_Setting_t; + /** @brief Emissivity setting definition. */ typedef struct { @@ -90,6 +103,7 @@ typedef struct { App_Settings_ROI_t ROI[4]; /**< Camera ROIs. */ App_Settings_Emissivity_t EmissivityPresets[128]; /**< Array of emissivity presets. */ size_t EmissivityCount; /**< Number of emissivity presets. */ + uint8_t CurrentEmissivity; /**< Currently selected emissivity value in the range from 0 to 100. */ } __attribute__((packed)) App_Settings_Lepton_t; /** @brief WiFi settings. diff --git a/main/Application/Tasks/Devices/devicesTask.h b/main/Application/Tasks/Devices/devicesTask.h index 763ee41..3eddb6f 100644 --- a/main/Application/Tasks/Devices/devicesTask.h +++ b/main/Application/Tasks/Devices/devicesTask.h @@ -31,14 +31,28 @@ #include "Application/application.h" +/** @brief Initializes the devices task. + * @return ESP_OK on success, error code otherwise + */ esp_err_t DevicesTask_Init(void); +/** @brief Deinitializes the devices task. + */ void DevicesTask_Deinit(void); +/** @brief Starts the devices task. + * @return ESP_OK on success, error code otherwise + */ esp_err_t DevicesTask_Start(App_Context_t *p_AppContext); +/** @brief Stops the devices task. + * @return ESP_OK on success, error code otherwise + */ esp_err_t DevicesTask_Stop(void); +/** @brief Checks if the devices task is running. + * @return false if the task is not running, true if it is running + */ bool DevicesTask_isRunning(void); #endif /* DEVICESTASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/Export/project.info b/main/Application/Tasks/GUI/Export/project.info index 7e33403..91a5839 100644 --- a/main/Application/Tasks/GUI/Export/project.info +++ b/main/Application/Tasks/GUI/Export/project.info @@ -1,9 +1,9 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-01-16T13:29:19.5084763+01:00", - "editor_version": "1.5.4", - "project_version": 94, + "datetime": "2026-02-06T07:11:20.7294523+01:00", + "editor_version": "1.6.0", + "project_version": 105, "user": "Kampert Daniel", - "export_datetime": "2026-01-29T11:38:03.9082624+01:00", + "export_datetime": "2026-02-06T10:10:56.7827177+01:00", "export_user": "Kampert Daniel" } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.c b/main/Application/Tasks/GUI/Export/screens/ui_Info.c index 1169b49..307ea58 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.c @@ -38,14 +38,16 @@ lv_obj_t * ui_Container_Lepton = NULL; lv_obj_t * ui_Info_Container1 = NULL; lv_obj_t * ui_Label_Info_Lepton_Serial_Name = NULL; lv_obj_t * ui_Label_Info_Lepton_Part_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_Revision_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_GPP_Revision_Name = NULL; +lv_obj_t * ui_Label_Info_Lepton_DSP_Revision_Main = NULL; lv_obj_t * ui_Label_Info_Lepton_Uptime_Name = NULL; lv_obj_t * ui_Label_Info_Lepton_FPA_Name = NULL; lv_obj_t * ui_Label_Info_Lepton_AUX_Name = NULL; lv_obj_t * ui_Info_Container7 = NULL; lv_obj_t * ui_Label_Info_Lepton_Serial = NULL; lv_obj_t * ui_Label_Info_Lepton_Part = NULL; -lv_obj_t * ui_Label_Info_Lepton_Revision = NULL; +lv_obj_t * ui_Label_Info_Lepton_GPP_Revision = NULL; +lv_obj_t * ui_Label_Info_Lepton_DSP_Revision = NULL; lv_obj_t * ui_Label_Info_Lepton_Uptime = NULL; lv_obj_t * ui_Label_Info_Lepton_FPA = NULL; lv_obj_t * ui_Label_Info_Lepton_AUX = NULL; @@ -126,12 +128,11 @@ void ui_Info_screen_init(void) lv_obj_set_style_radius(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_color(ui_Panel_Info_Content, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_opa(ui_Panel_Info_Content, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_border_color(ui_Panel_Info_Content, lv_color_hex(0x1E1E1E), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_border_opa(ui_Panel_Info_Content, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_left(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Panel_Info_Content, 5, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_top(ui_Panel_Info_Content, 10, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_bottom(ui_Panel_Info_Content, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Panel_Info_Content, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_radius(ui_Panel_Info_Content, 2, LV_PART_SCROLLBAR | LV_STATE_DEFAULT); lv_obj_set_style_bg_color(ui_Panel_Info_Content, lv_color_hex(0x7B3FF0), LV_PART_SCROLLBAR | LV_STATE_DEFAULT); @@ -140,7 +141,7 @@ void ui_Info_screen_init(void) ui_Panel_Device = lv_obj_create(ui_Panel_Info_Content); lv_obj_set_width(ui_Panel_Device, 300); - lv_obj_set_height(ui_Panel_Device, 100); + lv_obj_set_height(ui_Panel_Device, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Panel_Device, LV_ALIGN_CENTER); lv_obj_set_flex_flow(ui_Panel_Device, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(ui_Panel_Device, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); @@ -156,8 +157,8 @@ void ui_Info_screen_init(void) lv_obj_set_style_pad_bottom(ui_Panel_Device, 0, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Label_Info_Device = lv_label_create(ui_Panel_Device); - lv_obj_set_height(ui_Label_Info_Device, lv_pct(15)); lv_obj_set_width(ui_Label_Info_Device, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Device, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Label_Info_Device, LV_ALIGN_CENTER); lv_label_set_text(ui_Label_Info_Device, "DEVICE"); lv_obj_remove_flag(ui_Label_Info_Device, @@ -170,7 +171,7 @@ void ui_Info_screen_init(void) ui_Container_Info_Device = lv_obj_create(ui_Panel_Device); lv_obj_remove_style_all(ui_Container_Info_Device); lv_obj_set_width(ui_Container_Info_Device, lv_pct(100)); - lv_obj_set_height(ui_Container_Info_Device, lv_pct(50)); + lv_obj_set_height(ui_Container_Info_Device, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Container_Info_Device, LV_ALIGN_TOP_MID); lv_obj_set_flex_flow(ui_Container_Info_Device, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(ui_Container_Info_Device, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); @@ -183,7 +184,7 @@ void ui_Info_screen_init(void) ui_Info_Container4 = lv_obj_create(ui_Container_Info_Device); lv_obj_remove_style_all(ui_Info_Container4); lv_obj_set_width(ui_Info_Container4, lv_pct(50)); - lv_obj_set_height(ui_Info_Container4, lv_pct(100)); + lv_obj_set_height(ui_Info_Container4, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Info_Container4, LV_ALIGN_LEFT_MID); lv_obj_set_flex_flow(ui_Info_Container4, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(ui_Info_Container4, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); @@ -199,9 +200,9 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_MAC_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_MAC_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_MAC_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_MAC_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_MAC_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_MAC_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_MAC_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_MAC_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_MAC_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -215,9 +216,9 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_IP_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_IP_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_IP_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_IP_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_IP_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_IP_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_IP_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_IP_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_IP_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -227,13 +228,13 @@ void ui_Info_screen_init(void) lv_obj_set_width(ui_Label_Info_Serial_Name, LV_SIZE_CONTENT); /// 1 lv_obj_set_height(ui_Label_Info_Serial_Name, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Label_Info_Serial_Name, LV_ALIGN_CENTER); - lv_label_set_text(ui_Label_Info_Serial_Name, "Serial:\n"); + lv_label_set_text(ui_Label_Info_Serial_Name, "Serial:"); lv_obj_remove_flag(ui_Label_Info_Serial_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Serial_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_Serial_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Serial_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Serial_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Serial_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -242,7 +243,7 @@ void ui_Info_screen_init(void) ui_Info_Container5 = lv_obj_create(ui_Container_Info_Device); lv_obj_remove_style_all(ui_Info_Container5); lv_obj_set_width(ui_Info_Container5, lv_pct(50)); - lv_obj_set_height(ui_Info_Container5, lv_pct(100)); + lv_obj_set_height(ui_Info_Container5, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Info_Container5, LV_ALIGN_RIGHT_MID); lv_obj_set_flex_flow(ui_Info_Container5, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(ui_Info_Container5, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_END); @@ -261,7 +262,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_MAC, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_MAC, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_MAC, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_MAC, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_MAC, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_MAC, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_MAC, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_MAC, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -278,7 +279,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_IP, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_IP, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_IP, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_IP, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_IP, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_IP, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_IP, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_IP, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -295,7 +296,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_Serial, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Serial, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Serial, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Serial, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Serial, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -303,7 +304,7 @@ void ui_Info_screen_init(void) ui_Panel_Battery = lv_obj_create(ui_Panel_Info_Content); lv_obj_set_width(ui_Panel_Battery, 300); - lv_obj_set_height(ui_Panel_Battery, 100); + lv_obj_set_height(ui_Panel_Battery, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Panel_Battery, LV_ALIGN_CENTER); lv_obj_set_flex_flow(ui_Panel_Battery, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(ui_Panel_Battery, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); @@ -320,8 +321,8 @@ void ui_Info_screen_init(void) lv_obj_set_style_pad_bottom(ui_Panel_Battery, 0, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Label_Info_Battery = lv_label_create(ui_Panel_Battery); - lv_obj_set_height(ui_Label_Info_Battery, lv_pct(15)); lv_obj_set_width(ui_Label_Info_Battery, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Battery, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Label_Info_Battery, LV_ALIGN_CENTER); lv_label_set_text(ui_Label_Info_Battery, "BATTERY"); lv_obj_remove_flag(ui_Label_Info_Battery, @@ -334,7 +335,7 @@ void ui_Info_screen_init(void) ui_Container_Battery = lv_obj_create(ui_Panel_Battery); lv_obj_remove_style_all(ui_Container_Battery); lv_obj_set_width(ui_Container_Battery, lv_pct(100)); - lv_obj_set_height(ui_Container_Battery, lv_pct(50)); + lv_obj_set_height(ui_Container_Battery, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Container_Battery, LV_ALIGN_TOP_MID); lv_obj_set_flex_flow(ui_Container_Battery, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(ui_Container_Battery, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); @@ -347,7 +348,7 @@ void ui_Info_screen_init(void) ui_Info_Container2 = lv_obj_create(ui_Container_Battery); lv_obj_remove_style_all(ui_Info_Container2); lv_obj_set_width(ui_Info_Container2, lv_pct(50)); - lv_obj_set_height(ui_Info_Container2, lv_pct(100)); + lv_obj_set_height(ui_Info_Container2, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Info_Container2, LV_ALIGN_LEFT_MID); lv_obj_set_flex_flow(ui_Info_Container2, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(ui_Info_Container2, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); @@ -363,9 +364,9 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_Battery_Status_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Battery_Status_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_Battery_Status_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Battery_Status_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Battery_Status_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Status_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Battery_Status_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Battery_Status_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Battery_Status_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -379,7 +380,7 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_Battery_Voltage_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Battery_Voltage_Name, lv_color_hex(0x888888), + lv_obj_set_style_text_color(ui_Label_Info_Battery_Voltage_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Battery_Voltage_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_Label_Info_Battery_Voltage_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -396,10 +397,10 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_Battery_Remaining_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Battery_Remaining_Name, lv_color_hex(0x888888), + lv_obj_set_style_text_color(ui_Label_Info_Battery_Remaining_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Battery_Remaining_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Battery_Remaining_Name, &lv_font_montserrat_10, + lv_obj_set_style_text_font(ui_Label_Info_Battery_Remaining_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Battery_Remaining_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Battery_Remaining_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -409,8 +410,8 @@ void ui_Info_screen_init(void) ui_Info_Container3 = lv_obj_create(ui_Container_Battery); lv_obj_remove_style_all(ui_Info_Container3); lv_obj_set_width(ui_Info_Container3, lv_pct(50)); - lv_obj_set_height(ui_Info_Container3, lv_pct(100)); - lv_obj_set_align(ui_Info_Container3, LV_ALIGN_RIGHT_MID); + lv_obj_set_height(ui_Info_Container3, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Info_Container3, LV_ALIGN_BOTTOM_RIGHT); lv_obj_set_flex_flow(ui_Info_Container3, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(ui_Info_Container3, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_END); lv_obj_remove_flag(ui_Info_Container3, @@ -420,7 +421,7 @@ void ui_Info_screen_init(void) ui_Label_Info_Battery_Status = lv_label_create(ui_Info_Container3); lv_obj_set_width(ui_Label_Info_Battery_Status, lv_pct(100)); lv_obj_set_height(ui_Label_Info_Battery_Status, LV_SIZE_CONTENT); /// 1 - lv_obj_set_align(ui_Label_Info_Battery_Status, LV_ALIGN_CENTER); + lv_obj_set_align(ui_Label_Info_Battery_Status, LV_ALIGN_TOP_RIGHT); lv_label_set_text(ui_Label_Info_Battery_Status, "Nothing"); lv_obj_remove_flag(ui_Label_Info_Battery_Status, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | @@ -428,7 +429,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_Battery_Status, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Battery_Status, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Battery_Status, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Battery_Status, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Status, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Battery_Status, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Battery_Status, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Battery_Status, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -445,7 +446,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_Battery_Voltage, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Battery_Voltage, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Battery_Voltage, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Battery_Voltage, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Voltage, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Battery_Voltage, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Battery_Voltage, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Battery_Voltage, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -462,7 +463,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_Battery_Remaining, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Battery_Remaining, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Battery_Remaining, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Battery_Remaining, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Battery_Remaining, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Battery_Remaining, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Battery_Remaining, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Battery_Remaining, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -492,7 +493,7 @@ void ui_Info_screen_init(void) lv_obj_get_style_pad_right(ui_Info_Bar2, LV_PART_MAIN) + 1, LV_PART_MAIN); ui_Panel_Lepton = lv_obj_create(ui_Panel_Info_Content); lv_obj_set_width(ui_Panel_Lepton, 300); - lv_obj_set_height(ui_Panel_Lepton, 140); + lv_obj_set_height(ui_Panel_Lepton, LV_SIZE_CONTENT); /// 1 lv_obj_set_x(ui_Panel_Lepton, 0); lv_obj_set_y(ui_Panel_Lepton, 80); lv_obj_set_align(ui_Panel_Lepton, LV_ALIGN_CENTER); @@ -510,10 +511,10 @@ void ui_Info_screen_init(void) lv_obj_set_style_pad_bottom(ui_Panel_Lepton, 0, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Label_Info_Lepton = lv_label_create(ui_Panel_Lepton); - lv_obj_set_height(ui_Label_Info_Lepton, lv_pct(15)); lv_obj_set_width(ui_Label_Info_Lepton, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Label_Info_Lepton, LV_ALIGN_CENTER); - lv_label_set_text(ui_Label_Info_Lepton, "LEPTON\n"); + lv_label_set_text(ui_Label_Info_Lepton, "LEPTON"); lv_obj_remove_flag(ui_Label_Info_Lepton, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags @@ -524,7 +525,7 @@ void ui_Info_screen_init(void) ui_Container_Lepton = lv_obj_create(ui_Panel_Lepton); lv_obj_remove_style_all(ui_Container_Lepton); lv_obj_set_width(ui_Container_Lepton, lv_pct(100)); - lv_obj_set_height(ui_Container_Lepton, lv_pct(100)); + lv_obj_set_height(ui_Container_Lepton, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Container_Lepton, LV_ALIGN_TOP_MID); lv_obj_set_flex_flow(ui_Container_Lepton, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(ui_Container_Lepton, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); @@ -533,7 +534,7 @@ void ui_Info_screen_init(void) ui_Info_Container1 = lv_obj_create(ui_Container_Lepton); lv_obj_remove_style_all(ui_Info_Container1); lv_obj_set_width(ui_Info_Container1, lv_pct(50)); - lv_obj_set_height(ui_Info_Container1, lv_pct(100)); + lv_obj_set_height(ui_Info_Container1, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Info_Container1, LV_ALIGN_CENTER); lv_obj_set_flex_flow(ui_Info_Container1, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(ui_Info_Container1, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); @@ -547,9 +548,9 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_Lepton_Serial_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Lepton_Serial_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Serial_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Serial_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_Serial_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Serial_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Serial_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -563,30 +564,49 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_Lepton_Part_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Lepton_Part_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Part_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Part_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_Part_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Part_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Part_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Part_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Part_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Part_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Label_Info_Lepton_Revision_Name = lv_label_create(ui_Info_Container1); - lv_obj_set_width(ui_Label_Info_Lepton_Revision_Name, LV_SIZE_CONTENT); /// 1 - lv_obj_set_height(ui_Label_Info_Lepton_Revision_Name, LV_SIZE_CONTENT); /// 1 - lv_obj_set_align(ui_Label_Info_Lepton_Revision_Name, LV_ALIGN_CENTER); - lv_label_set_text(ui_Label_Info_Lepton_Revision_Name, "Software Revision:"); - lv_obj_remove_flag(ui_Label_Info_Lepton_Revision_Name, + ui_Label_Info_Lepton_GPP_Revision_Name = lv_label_create(ui_Info_Container1); + lv_obj_set_width(ui_Label_Info_Lepton_GPP_Revision_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton_GPP_Revision_Name, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_GPP_Revision_Name, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_GPP_Revision_Name, "GPP Revision:"); + lv_obj_remove_flag(ui_Label_Info_Lepton_GPP_Revision_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Lepton_Revision_Name, lv_color_hex(0x888888), + lv_obj_set_style_text_color(ui_Label_Info_Lepton_GPP_Revision_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Revision_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_Revision_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Revision_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_GPP_Revision_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_GPP_Revision_Name, &lv_font_montserrat_12, + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_GPP_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_GPP_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_GPP_Revision_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_GPP_Revision_Name, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_DSP_Revision_Main = lv_label_create(ui_Info_Container1); + lv_obj_set_width(ui_Label_Info_Lepton_DSP_Revision_Main, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Info_Lepton_DSP_Revision_Main, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_DSP_Revision_Main, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_DSP_Revision_Main, "DSP Revision:"); + lv_obj_remove_flag(ui_Label_Info_Lepton_DSP_Revision_Main, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_DSP_Revision_Main, lv_color_hex(0xFFFFFF), + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_DSP_Revision_Main, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_DSP_Revision_Main, &lv_font_montserrat_12, + LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_DSP_Revision_Main, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_DSP_Revision_Main, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_DSP_Revision_Main, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_DSP_Revision_Main, 5, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Label_Info_Lepton_Uptime_Name = lv_label_create(ui_Info_Container1); lv_obj_set_width(ui_Label_Info_Lepton_Uptime_Name, LV_SIZE_CONTENT); /// 1 @@ -596,9 +616,9 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_Lepton_Uptime_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Lepton_Uptime_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_Lepton_Uptime_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Uptime_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_Uptime_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Uptime_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Uptime_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Uptime_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Uptime_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -614,9 +634,9 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_Lepton_FPA_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Lepton_FPA_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_Lepton_FPA_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_FPA_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_FPA_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_FPA_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_FPA_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_FPA_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_FPA_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -630,9 +650,9 @@ void ui_Info_screen_init(void) lv_obj_remove_flag(ui_Label_Info_Lepton_AUX_Name, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Lepton_AUX_Name, lv_color_hex(0x888888), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_Lepton_AUX_Name, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_AUX_Name, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_AUX_Name, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_AUX_Name, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_AUX_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_AUX_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_AUX_Name, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -641,7 +661,7 @@ void ui_Info_screen_init(void) ui_Info_Container7 = lv_obj_create(ui_Container_Lepton); lv_obj_remove_style_all(ui_Info_Container7); lv_obj_set_width(ui_Info_Container7, lv_pct(50)); - lv_obj_set_height(ui_Info_Container7, lv_pct(100)); + lv_obj_set_height(ui_Info_Container7, LV_SIZE_CONTENT); /// 1 lv_obj_set_x(ui_Info_Container7, 172); lv_obj_set_y(ui_Info_Container7, -2); lv_obj_set_align(ui_Info_Container7, LV_ALIGN_CENTER); @@ -660,7 +680,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_Lepton_Serial, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Serial, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Lepton_Serial, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_Serial, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Serial, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Serial, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -677,28 +697,45 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_Lepton_Part, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Part, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Lepton_Part, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_Part, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Part, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Part, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Part, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Part, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Part, 5, LV_PART_MAIN | LV_STATE_DEFAULT); - ui_Label_Info_Lepton_Revision = lv_label_create(ui_Info_Container7); - lv_obj_set_width(ui_Label_Info_Lepton_Revision, lv_pct(100)); - lv_obj_set_height(ui_Label_Info_Lepton_Revision, LV_SIZE_CONTENT); /// 1 - lv_obj_set_align(ui_Label_Info_Lepton_Revision, LV_ALIGN_CENTER); - lv_label_set_text(ui_Label_Info_Lepton_Revision, "Nothing"); - lv_obj_remove_flag(ui_Label_Info_Lepton_Revision, + ui_Label_Info_Lepton_GPP_Revision = lv_label_create(ui_Info_Container7); + lv_obj_set_width(ui_Label_Info_Lepton_GPP_Revision, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Lepton_GPP_Revision, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_GPP_Revision, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_GPP_Revision, "Nothing"); + lv_obj_remove_flag(ui_Label_Info_Lepton_GPP_Revision, + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | + LV_OBJ_FLAG_SNAPPABLE); /// Flags + lv_obj_set_style_text_color(ui_Label_Info_Lepton_GPP_Revision, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_GPP_Revision, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Lepton_GPP_Revision, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_GPP_Revision, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_GPP_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_GPP_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_GPP_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_GPP_Revision, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Info_Lepton_DSP_Revision = lv_label_create(ui_Info_Container7); + lv_obj_set_width(ui_Label_Info_Lepton_DSP_Revision, lv_pct(100)); + lv_obj_set_height(ui_Label_Info_Lepton_DSP_Revision, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Info_Lepton_DSP_Revision, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Info_Lepton_DSP_Revision, "Nothing"); + lv_obj_remove_flag(ui_Label_Info_Lepton_DSP_Revision, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags - lv_obj_set_style_text_color(ui_Label_Info_Lepton_Revision, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Revision, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_align(ui_Label_Info_Lepton_Revision, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_Revision, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_Revision, 5, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_color(ui_Label_Info_Lepton_DSP_Revision, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Info_Lepton_DSP_Revision, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_align(ui_Label_Info_Lepton_DSP_Revision, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_DSP_Revision, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(ui_Label_Info_Lepton_DSP_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(ui_Label_Info_Lepton_DSP_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(ui_Label_Info_Lepton_DSP_Revision, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_bottom(ui_Label_Info_Lepton_DSP_Revision, 5, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Label_Info_Lepton_Uptime = lv_label_create(ui_Info_Container7); lv_obj_set_width(ui_Label_Info_Lepton_Uptime, lv_pct(100)); @@ -711,7 +748,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_Lepton_Uptime, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_Uptime, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Lepton_Uptime, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_Uptime, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_Uptime, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_Uptime, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_Uptime, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_Uptime, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -728,7 +765,7 @@ void ui_Info_screen_init(void) lv_obj_set_style_text_color(ui_Label_Info_Lepton_FPA, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_FPA, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Lepton_FPA, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_FPA, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_FPA, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_FPA, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_FPA, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_FPA, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -738,14 +775,14 @@ void ui_Info_screen_init(void) lv_obj_set_width(ui_Label_Info_Lepton_AUX, lv_pct(100)); lv_obj_set_height(ui_Label_Info_Lepton_AUX, LV_SIZE_CONTENT); /// 1 lv_obj_set_align(ui_Label_Info_Lepton_AUX, LV_ALIGN_CENTER); - lv_label_set_text(ui_Label_Info_Lepton_AUX, "0\n"); + lv_label_set_text(ui_Label_Info_Lepton_AUX, "0"); lv_obj_remove_flag(ui_Label_Info_Lepton_AUX, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE); /// Flags lv_obj_set_style_text_color(ui_Label_Info_Lepton_AUX, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Info_Lepton_AUX, 255, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_align(ui_Label_Info_Lepton_AUX, LV_TEXT_ALIGN_RIGHT, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Info_Lepton_AUX, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Info_Lepton_AUX, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_left(ui_Label_Info_Lepton_AUX, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_right(ui_Label_Info_Lepton_AUX, 0, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_pad_top(ui_Label_Info_Lepton_AUX, 0, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -825,14 +862,16 @@ void ui_Info_screen_destroy(void) ui_Info_Container1 = NULL; ui_Label_Info_Lepton_Serial_Name = NULL; ui_Label_Info_Lepton_Part_Name = NULL; - ui_Label_Info_Lepton_Revision_Name = NULL; + ui_Label_Info_Lepton_GPP_Revision_Name = NULL; + ui_Label_Info_Lepton_DSP_Revision_Main = NULL; ui_Label_Info_Lepton_Uptime_Name = NULL; ui_Label_Info_Lepton_FPA_Name = NULL; ui_Label_Info_Lepton_AUX_Name = NULL; ui_Info_Container7 = NULL; ui_Label_Info_Lepton_Serial = NULL; ui_Label_Info_Lepton_Part = NULL; - ui_Label_Info_Lepton_Revision = NULL; + ui_Label_Info_Lepton_GPP_Revision = NULL; + ui_Label_Info_Lepton_DSP_Revision = NULL; ui_Label_Info_Lepton_Uptime = NULL; ui_Label_Info_Lepton_FPA = NULL; ui_Label_Info_Lepton_AUX = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.h b/main/Application/Tasks/GUI/Export/screens/ui_Info.h index 3e61723..44372dc 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.h @@ -47,14 +47,16 @@ extern lv_obj_t * ui_Container_Lepton; extern lv_obj_t * ui_Info_Container1; extern lv_obj_t * ui_Label_Info_Lepton_Serial_Name; extern lv_obj_t * ui_Label_Info_Lepton_Part_Name; -extern lv_obj_t * ui_Label_Info_Lepton_Revision_Name; +extern lv_obj_t * ui_Label_Info_Lepton_GPP_Revision_Name; +extern lv_obj_t * ui_Label_Info_Lepton_DSP_Revision_Main; extern lv_obj_t * ui_Label_Info_Lepton_Uptime_Name; extern lv_obj_t * ui_Label_Info_Lepton_FPA_Name; extern lv_obj_t * ui_Label_Info_Lepton_AUX_Name; extern lv_obj_t * ui_Info_Container7; extern lv_obj_t * ui_Label_Info_Lepton_Serial; extern lv_obj_t * ui_Label_Info_Lepton_Part; -extern lv_obj_t * ui_Label_Info_Lepton_Revision; +extern lv_obj_t * ui_Label_Info_Lepton_GPP_Revision; +extern lv_obj_t * ui_Label_Info_Lepton_DSP_Revision; extern lv_obj_t * ui_Label_Info_Lepton_Uptime; extern lv_obj_t * ui_Label_Info_Lepton_FPA; extern lv_obj_t * ui_Label_Info_Lepton_AUX; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.c b/main/Application/Tasks/GUI/Export/screens/ui_Main.c index 9783889..dcb94e4 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.c @@ -163,10 +163,10 @@ void ui_Main_screen_init(void) lv_obj_remove_flag(ui_Image_Thermal, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_image_set_rotation(ui_Image_Thermal, 1800); lv_obj_set_style_radius(ui_Image_Thermal, 3, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_color(ui_Image_Thermal, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_opa(ui_Image_Thermal, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_bg_grad_color(ui_Image_Thermal, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_grad_dir(ui_Image_Thermal, LV_GRAD_DIR_HOR, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Image_Main_Thermal_Scene_ROI = lv_obj_create(ui_Image_Thermal); @@ -184,10 +184,10 @@ void ui_Main_screen_init(void) lv_obj_set_style_border_width(ui_Image_Main_Thermal_Scene_ROI, 2, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Image_Main_Thermal_Spotmeter_ROI = lv_obj_create(ui_Image_Thermal); - lv_obj_set_width(ui_Image_Main_Thermal_Spotmeter_ROI, 1); - lv_obj_set_height(ui_Image_Main_Thermal_Spotmeter_ROI, 1); - lv_obj_set_x(ui_Image_Main_Thermal_Spotmeter_ROI, 119); - lv_obj_set_y(ui_Image_Main_Thermal_Spotmeter_ROI, 89); + lv_obj_set_width(ui_Image_Main_Thermal_Spotmeter_ROI, 2); + lv_obj_set_height(ui_Image_Main_Thermal_Spotmeter_ROI, 2); + lv_obj_set_x(ui_Image_Main_Thermal_Spotmeter_ROI, -1); + lv_obj_set_y(ui_Image_Main_Thermal_Spotmeter_ROI, -1); lv_obj_set_align(ui_Image_Main_Thermal_Spotmeter_ROI, LV_ALIGN_CENTER); lv_obj_remove_flag(ui_Image_Main_Thermal_Spotmeter_ROI, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | @@ -254,6 +254,8 @@ void ui_Main_screen_init(void) lv_obj_remove_style_all(ui_Container_Main_Thermal_Scene_Statistics); lv_obj_set_height(ui_Container_Main_Thermal_Scene_Statistics, 20); lv_obj_set_width(ui_Container_Main_Thermal_Scene_Statistics, lv_pct(100)); + lv_obj_set_x(ui_Container_Main_Thermal_Scene_Statistics, 0); + lv_obj_set_y(ui_Container_Main_Thermal_Scene_Statistics, -5); lv_obj_set_align(ui_Container_Main_Thermal_Scene_Statistics, LV_ALIGN_BOTTOM_MID); lv_obj_remove_flag(ui_Container_Main_Thermal_Scene_Statistics, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags @@ -261,6 +263,8 @@ void ui_Main_screen_init(void) ui_Label_Main_Thermal_Scene_Max = lv_label_create(ui_Container_Main_Thermal_Scene_Statistics); lv_obj_set_width(ui_Label_Main_Thermal_Scene_Max, LV_SIZE_CONTENT); /// 1 lv_obj_set_height(ui_Label_Main_Thermal_Scene_Max, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Label_Main_Thermal_Scene_Max, 10); + lv_obj_set_y(ui_Label_Main_Thermal_Scene_Max, 0); lv_obj_set_align(ui_Label_Main_Thermal_Scene_Max, LV_ALIGN_LEFT_MID); lv_label_set_text(ui_Label_Main_Thermal_Scene_Max, "100.0"); lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Max, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -285,16 +289,14 @@ void ui_Main_screen_init(void) ui_Label_Main_Thermal_Scene_Mean = lv_label_create(ui_Container_Main_Thermal_Scene_Statistics); lv_obj_set_width(ui_Label_Main_Thermal_Scene_Mean, LV_SIZE_CONTENT); /// 1 lv_obj_set_height(ui_Label_Main_Thermal_Scene_Mean, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_Label_Main_Thermal_Scene_Mean, -10); + lv_obj_set_y(ui_Label_Main_Thermal_Scene_Mean, 0); lv_obj_set_align(ui_Label_Main_Thermal_Scene_Mean, LV_ALIGN_RIGHT_MID); lv_label_set_text(ui_Label_Main_Thermal_Scene_Mean, "80.0"); lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Mean, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_Label_Main_Thermal_Scene_Mean, 192, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_Label_Main_Thermal_Scene_Mean, &lv_font_montserrat_12, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_bg_image_opa(ui_Label_Main_Thermal_Scene_Mean, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_left(ui_Label_Main_Thermal_Scene_Mean, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_right(ui_Label_Main_Thermal_Scene_Mean, 5, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_top(ui_Label_Main_Thermal_Scene_Mean, 0, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_pad_bottom(ui_Label_Main_Thermal_Scene_Mean, 5, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Container_Gradient = lv_obj_create(ui_Container_Main_Thermal); lv_obj_remove_style_all(ui_Container_Gradient); diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c index dd0fd48..719b107 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c @@ -12,6 +12,8 @@ lv_obj_t * ui_Container_Menu = NULL; lv_obj_t * ui_Container_Menu_Buttons = NULL; lv_obj_t * ui_Button_Menu_Back = NULL; lv_obj_t * ui_Label_Menu_Back = NULL; +lv_obj_t * ui_Button_Menu_Save = NULL; +lv_obj_t * ui_Label_Menu_Button_Save = NULL; // event funtions void ui_event_Menu(lv_event_t * e) { @@ -21,9 +23,6 @@ void ui_event_Menu(lv_event_t * e) lv_indev_wait_release(lv_indev_active()); _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } - if(event_code == LV_EVENT_SCREEN_LOADED) { - ScreenMenuLoaded(e); - } } void ui_event_Button_Menu_Back(lv_event_t * e) @@ -35,6 +34,15 @@ void ui_event_Button_Menu_Back(lv_event_t * e) } } +void ui_event_Button_Menu_Save(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_CLICKED) { + ButtonMenuSaveClicked(e); + } +} + // build funtions void ui_Menu_screen_init(void) @@ -113,7 +121,32 @@ void ui_Menu_screen_init(void) lv_label_set_text(ui_Label_Menu_Back, "B"); lv_obj_set_style_text_font(ui_Label_Menu_Back, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + ui_Button_Menu_Save = lv_button_create(ui_Container_Menu_Buttons); + lv_obj_set_width(ui_Button_Menu_Save, 50); + lv_obj_set_height(ui_Button_Menu_Save, lv_pct(95)); + lv_obj_set_x(ui_Button_Menu_Save, 100); + lv_obj_set_y(ui_Button_Menu_Save, 0); + lv_obj_set_align(ui_Button_Menu_Save, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Button_Menu_Save, + LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | + LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags + lv_obj_set_style_bg_color(ui_Button_Menu_Save, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Button_Menu_Save, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Button_Menu_Save, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Button_Menu_Save, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Button_Menu_Save, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Menu_Button_Save = lv_label_create(ui_Button_Menu_Save); + lv_obj_set_width(ui_Label_Menu_Button_Save, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Menu_Button_Save, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Menu_Button_Save, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Menu_Button_Save, "S"); + lv_obj_set_style_text_color(ui_Label_Menu_Button_Save, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Menu_Button_Save, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Menu_Button_Save, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_add_event_cb(ui_Button_Menu_Back, ui_event_Button_Menu_Back, LV_EVENT_ALL, NULL); + lv_obj_add_event_cb(ui_Button_Menu_Save, ui_event_Button_Menu_Save, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(ui_Menu, ui_event_Menu, LV_EVENT_ALL, NULL); } @@ -130,5 +163,7 @@ void ui_Menu_screen_destroy(void) ui_Container_Menu_Buttons = NULL; ui_Button_Menu_Back = NULL; ui_Label_Menu_Back = NULL; + ui_Button_Menu_Save = NULL; + ui_Label_Menu_Button_Save = NULL; } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h index 401fac7..654db67 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h @@ -22,6 +22,9 @@ extern lv_obj_t * ui_Container_Menu_Buttons; extern void ui_event_Button_Menu_Back(lv_event_t * e); extern lv_obj_t * ui_Button_Menu_Back; extern lv_obj_t * ui_Label_Menu_Back; +extern void ui_event_Button_Menu_Save(lv_event_t * e); +extern lv_obj_t * ui_Button_Menu_Save; +extern lv_obj_t * ui_Label_Menu_Button_Save; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c index 50bc123..d230c77 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c @@ -13,6 +13,14 @@ lv_obj_t * ui_SplashScreen_LoadingBar = NULL; lv_obj_t * ui_SplashScreen_StatusText = NULL; lv_obj_t * ui_SplashScreen_FirmwareVersion = NULL; // event funtions +void ui_event_Splash(lv_event_t * e) +{ + lv_event_code_t event_code = lv_event_get_code(e); + + if(event_code == LV_EVENT_SCREEN_LOADED) { + ScreenSplahLoaded(e); + } +} // build funtions @@ -109,6 +117,8 @@ void ui_Splash_screen_init(void) lv_obj_set_style_text_align(ui_SplashScreen_FirmwareVersion, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_SplashScreen_FirmwareVersion, &lv_font_montserrat_10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_add_event_cb(ui_Splash, ui_event_Splash, LV_EVENT_ALL, NULL); + } void ui_Splash_screen_destroy(void) diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h index ee68e83..e14dc0c 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h @@ -13,6 +13,7 @@ extern "C" { // SCREEN: ui_Splash extern void ui_Splash_screen_init(void); extern void ui_Splash_screen_destroy(void); +extern void ui_event_Splash(lv_event_t * e); extern lv_obj_t * ui_Splash; extern lv_obj_t * ui_SplashScreen_Logo; extern lv_obj_t * ui_SplashScreen_LogoText; diff --git a/main/Application/Tasks/GUI/Export/ui_events.cpp b/main/Application/Tasks/GUI/Export/ui_events.cpp index 8b7a5bb..d387505 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.cpp +++ b/main/Application/Tasks/GUI/Export/ui_events.cpp @@ -3,12 +3,16 @@ // LVGL version: 9.1.0 // Project name: PyroVision +#include #include #include "ui.h" +#include "../UI/ui_Settings.h" #include "../../../application.h" +static const char *TAG = "ui_Settings"; + void ScreenMainLoaded(lv_event_t *e) { char Buf[128]; @@ -19,15 +23,15 @@ void ScreenMainLoaded(lv_event_t *e) snprintf(Buf, sizeof(Buf), "Firmware %s\n(c) 2026 PyroVision Project", Info.FirmwareVersion); lv_label_set_text(ui_SplashScreen_FirmwareVersion, Buf); + /* Set the symbols for the UI */ lv_label_set_text(ui_Image_Main_WiFi, LV_SYMBOL_WIFI); lv_label_set_text(ui_Image_Main_SDCard, LV_SYMBOL_SD_CARD); - + lv_label_set_text(ui_Label_Menu_Button_Save, LV_SYMBOL_SAVE); lv_label_set_text(ui_Label_Main_Button_Menu, "\uF0C9"); lv_label_set_text(ui_Label_Main_Button_Info, "\uF129"); lv_label_set_text(ui_Label_Main_Button_ROI, "\uE595"); lv_label_set_text(ui_Label_Main_Button_WiFi, "\uF1EB"); lv_label_set_text(ui_Label_Main_Thermal_Crosshair, "\uF05B"); - lv_label_set_text(ui_Label_Menu_Back, "\uF060"); lv_label_set_text(ui_Label_Info_Back, "\uF060"); } @@ -43,7 +47,12 @@ void ButtonMainWiFiClicked(lv_event_t *e) esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_OPEN_WIFI_REQUEST, NULL, 0, 0); } -void ScreenMenuLoaded(lv_event_t * e) +void ScreenSplahLoaded(lv_event_t * e) { - // Your code here + ui_settings_build(ui_Container_Menu); } + +void ButtonMenuSaveClicked(lv_event_t * e) +{ + SettingsManager_Save(); +} \ No newline at end of file diff --git a/main/Application/Tasks/GUI/Export/ui_events.h b/main/Application/Tasks/GUI/Export/ui_events.h index 7607b69..1e86838 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.h +++ b/main/Application/Tasks/GUI/Export/ui_events.h @@ -10,9 +10,10 @@ extern "C" { #endif +void ScreenSplahLoaded(lv_event_t * e); void ScreenMainLoaded(lv_event_t * e); void ButtonMainWiFiClicked(lv_event_t * e); -void ScreenMenuLoaded(lv_event_t * e); +void ButtonMenuSaveClicked(lv_event_t * e); void ScreenInfoLoaded(lv_event_t * e); #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Private/guiHelper.cpp b/main/Application/Tasks/GUI/Private/guiHelper.cpp index c3a27bd..b9d6ee9 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.cpp +++ b/main/Application/Tasks/GUI/Private/guiHelper.cpp @@ -21,7 +21,9 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ + #include +#include #include "guiHelper.h" #include "Application/application.h" @@ -179,8 +181,25 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t #endif ESP_LOGI(TAG, "Create I2C bus for touch controller..."); + i2c_new_master_bus(&_GUI_Touch_I2C_Config, &p_GUITask_State->Touch_Bus_Handle); + // --- I2C-Scanner --- + /* + ESP_LOGI(TAG, "Starte I2C-Scan auf Touch-Bus (driver_ng)..."); + for (uint8_t addr = 1; addr < 127; addr++) { + esp_err_t ret = i2c_master_probe(p_GUITask_State->Touch_Bus_Handle, addr, 10 / portTICK_PERIOD_MS); + if (ret == ESP_OK) { + ESP_LOGW(TAG, "I2C-Gerät gefunden bei Adresse 0x%02X", addr); + } + } + ESP_LOGI(TAG, "I2C-Scan abgeschlossen."); + + while(1) + { + vTaskDelay(1000 / portTICK_PERIOD_MS); + }*/ + ESP_LOGI(TAG, "Create panel IO..."); ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(static_cast(LCD_SPI_HOST), &_GUI_Panel_IO_Config, &p_GUITask_State->Panel_IO_Handle)); @@ -242,17 +261,25 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t GUI_DRAW_BUFFER_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL); - ESP_LOGD(TAG, "Initialize GT911 touch controller..."); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(p_GUITask_State->Touch_IO_Handle, &_GUI_Touch_Config, - &p_GUITask_State->TouchHandle)); - - /* Register touchpad input device */ - ESP_LOGD(TAG, "Register touch input device to LVGL"); - p_GUITask_State->Touch = lv_indev_create(); - lv_indev_set_type(p_GUITask_State->Touch, LV_INDEV_TYPE_POINTER); - lv_indev_set_display(p_GUITask_State->Touch, p_GUITask_State->Display); - lv_indev_set_read_cb(p_GUITask_State->Touch, Touch_Read_Callback); - lv_indev_set_user_data(p_GUITask_State->Touch, p_GUITask_State->TouchHandle); + ESP_LOGI(TAG, "Initialize GT911 touch controller..."); + esp_err_t TouchError = esp_lcd_touch_new_i2c_gt911(p_GUITask_State->Touch_IO_Handle, &_GUI_Touch_Config, + &p_GUITask_State->TouchHandle); + if (TouchError != ESP_OK) { + ESP_LOGW(TAG, "GT911 touch controller initialization failed (0x%x)", TouchError); + ESP_LOGW(TAG, "System will continue without touch functionality"); + p_GUITask_State->TouchHandle = NULL; + p_GUITask_State->Touch = NULL; + } else { + ESP_LOGI(TAG, "GT911 touch controller initialized successfully"); + + /* Register touchpad input device */ + ESP_LOGD(TAG, "Register touch input device to LVGL"); + p_GUITask_State->Touch = lv_indev_create(); + lv_indev_set_type(p_GUITask_State->Touch, LV_INDEV_TYPE_POINTER); + lv_indev_set_display(p_GUITask_State->Touch, p_GUITask_State->Display); + lv_indev_set_read_cb(p_GUITask_State->Touch, Touch_Read_Callback); + lv_indev_set_user_data(p_GUITask_State->Touch, p_GUITask_State->TouchHandle); + } /* Create LVGL tick timer */ const esp_timer_create_args_t LVGL_TickTimer_args = { diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp new file mode 100644 index 0000000..025257c --- /dev/null +++ b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp @@ -0,0 +1,135 @@ +/* + * ui_Settings_Events.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Settings UI implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include "../../../../Manager/Settings/settingsManager.h" + +#include "ui_Settings_Events.h" + +static const char *TAG = "ui_Settings_Events"; + +void on_Lepton_Emissivity_Slider_Callback(lv_event_t * e) { + int Value; + App_Settings_Lepton_t LeptonSettings; + lv_obj_t * slider = static_cast(lv_event_get_target(e)); + Slider_Widgets_t * widgets = static_cast(lv_obj_get_user_data(slider)); + + SettingsManager_GetLepton(&LeptonSettings); + + Value = static_cast(lv_slider_get_value(slider)); + lv_label_set_text_fmt(widgets->Label, "%d", Value); + + /* Save on release only */ + if(lv_event_get_code(e) == LV_EVENT_RELEASED) { + SettingsManager_Setting_t Setting; + + Setting.ID = SETTINGS_ID_LEPTON_EMISSIVITY; + Setting.Value = Value; + LeptonSettings.CurrentEmissivity = static_cast(Value); + SettingsManager_UpdateLepton(&LeptonSettings, &Setting); + } +} + +void on_Display_Brightness_Slider_Callback(lv_event_t * e) { + int Value; + App_Settings_Display_t DisplaySettings; + lv_obj_t * slider = static_cast(lv_event_get_target(e)); + Slider_Widgets_t * widgets = static_cast(lv_obj_get_user_data(slider)); + + SettingsManager_GetDisplay(&DisplaySettings); + + Value = static_cast(lv_slider_get_value(slider)); + lv_label_set_text_fmt(widgets->Label, "%d", Value); + + /* Save on release only */ + if(lv_event_get_code(e) == LV_EVENT_RELEASED) { + DisplaySettings.Brightness = static_cast(Value); + SettingsManager_UpdateDisplay(&DisplaySettings); + } +} + +void on_Lepton_Dropdown_Callback(lv_event_t * e) { + int Value; + App_Settings_Lepton_t LeptonSettings; + lv_obj_t * dropdown = static_cast(lv_event_get_target(e)); + Slider_Widgets_t * widgets = static_cast(lv_obj_get_user_data(dropdown)); + + SettingsManager_GetLepton(&LeptonSettings); + + Value = LeptonSettings.EmissivityPresets[lv_dropdown_get_selected(dropdown)].Value * 100; + lv_slider_set_value(widgets->Slider, Value, LV_ANIM_ON); + lv_label_set_text_fmt(widgets->Label, "%d", Value); + + /* Save settings directly without triggering additional events */ + SettingsManager_Setting_t Setting; + Setting.ID = SETTINGS_ID_LEPTON_EMISSIVITY; + Setting.Value = Value; + LeptonSettings.CurrentEmissivity = static_cast(Value); + SettingsManager_UpdateLepton(&LeptonSettings, &Setting); +} + +void on_WiFi_Autoconnect_Callback(lv_event_t * e) { + App_Settings_WiFi_t WiFiSettings; + lv_obj_t * switch_obj = static_cast(lv_event_get_target(e)); + + SettingsManager_GetWiFi(&WiFiSettings); + + if(lv_obj_has_state(switch_obj, LV_STATE_CHECKED)) { + WiFiSettings.AutoConnect = true; + ESP_LOGI(TAG, "WiFi autoconnect enabled"); + } else { + WiFiSettings.AutoConnect = false; + ESP_LOGI(TAG, "WiFi autoconnect disabled"); + } + + SettingsManager_UpdateWiFi(&WiFiSettings); +} + +void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "Devices event received: ID=%d", ID); + + switch (ID) { + case SETTINGS_EVENT_LEPTON_CHANGED: { + SettingsManager_Setting_t NewSetting; + + memcpy(&NewSetting, p_Data, sizeof(SettingsManager_Setting_t)); + + ESP_LOGD(TAG, "Lepton settings changed: ID=%d", NewSetting.ID); + ESP_LOGD(TAG, "Lepton settings changed: Value=%d", NewSetting.Value); + + if(NewSetting.ID == SETTINGS_ID_LEPTON_EMISSIVITY) { + lv_slider_set_value(emissivity_widgets.Slider, NewSetting.Value, LV_ANIM_ON); + lv_label_set_text_fmt(emissivity_widgets.Label, "%d", static_cast(NewSetting.Value)); + } + + break; + } + case SETTINGS_EVENT_WIFI_CHANGED: { + ESP_LOGI(TAG, "WiFi settings changed."); + + break; + } + } +} \ No newline at end of file diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h new file mode 100644 index 0000000..7e8484d --- /dev/null +++ b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h @@ -0,0 +1,78 @@ +/* + * ui_Settings_Events.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Settings UI implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef UI_SETTINGS_EVENTS_H_ +#define UI_SETTINGS_EVENTS_H_ + +#include + +#include + +/** @brief + */ +typedef struct { + lv_obj_t * Slider; + lv_obj_t * Label; +} Slider_Widgets_t; + +/** @brief + */ +typedef struct { + lv_obj_t * Container; + lv_obj_t * Page; +} Menu_Page_Result_t; + +extern Slider_Widgets_t brightness_widgets; +extern Slider_Widgets_t emissivity_widgets; + +/** @brief Display brightness slider event callback to update value label. + * @param e Pointer to the event object + */ +void on_Lepton_Emissivity_Slider_Callback(lv_event_t * e); + +/** @brief Display brightness slider event callback to update value label. + * @param e Pointer to the event object + */ +void on_Display_Brightness_Slider_Callback(lv_event_t * e); + +/** @brief Dropdown event callback to update slider and label with selected emissivity preset value. + * @param e Pointer to the event object + */ +void on_Lepton_Dropdown_Callback(lv_event_t * e); + +/** @brief Switch event callback to toggle WiFi autoconnect setting. + * @param e Pointer to the event object + */ +void on_WiFi_Autoconnect_Callback(lv_event_t * e); + +/** @brief Settings event handler which is used to update the UI elements when a + * settings change event is received from the Settings Manager. + * This ensures that the UI always reflects the current settings values. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data); + +#endif /* UI_SETTINGS_EVENTS_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/UI/ui_Settings.cpp b/main/Application/Tasks/GUI/UI/ui_Settings.cpp new file mode 100644 index 0000000..25c0b4f --- /dev/null +++ b/main/Application/Tasks/GUI/UI/ui_Settings.cpp @@ -0,0 +1,448 @@ +/* + * ui_Settings.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Settings UI implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include +#include + +#include "../Export/ui.h" + +#include "ui_Settings.h" +#include "Private/ui_Settings_Events.h" +#include "../../../Manager/Settings/settingsManager.h" + +Slider_Widgets_t brightness_widgets; +Slider_Widgets_t emissivity_widgets; + +lv_obj_t * root_page; +lv_obj_t * menu; +lv_obj_t * cont; +lv_obj_t * section; +lv_obj_t * about_Page; +lv_obj_t * wifi_Page; +lv_obj_t * display_Page; +lv_obj_t * lepton_Page; +lv_obj_t * flash_Page; +lv_obj_t * settings_Menu; +lv_obj_t * emissivity_Dropdown; +lv_obj_t * wifi_status_label; + +static lv_obj_t * create_menu_container(lv_obj_t * parent) { + lv_obj_t * container = lv_obj_create(parent); + lv_obj_clear_flag(container, LV_OBJ_FLAG_CLICKABLE); + lv_obj_set_size(container, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_set_style_pad_all(container, 8, 0); + lv_obj_set_style_bg_color(container, lv_color_hex(0x2A2A2A), 0); + lv_obj_set_style_bg_opa(container, 255, 0); + lv_obj_set_style_border_width(container, 0, 0); + lv_obj_set_flex_flow(container, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(container, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_set_scrollbar_mode(container, LV_SCROLLBAR_MODE_OFF); + + return container; +} + +static lv_obj_t * create_row(lv_obj_t * parent, lv_flex_align_t main_align) { + lv_obj_t * row = lv_obj_create(parent); + lv_obj_clear_flag(row, static_cast(LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_GESTURE_BUBBLE)); + lv_obj_set_size(row, LV_PCT(100), 28); + lv_obj_set_style_border_width(row, 0, 0); + lv_obj_set_style_bg_opa(row, 0, 0); + lv_obj_set_style_pad_all(row, 4, 0); + lv_obj_set_style_pad_row(row, 4, 0); + lv_obj_set_scrollbar_mode(row, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_scroll_dir(row, LV_DIR_NONE); + lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(row, main_align, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + + return row; +} + +static lv_obj_t* create_compact_slider(lv_obj_t * parent, const char * label_text, + int min_val, int max_val, int init_val, Slider_Widgets_t *widgets) { + char Buffer[8]; + + if(widgets == NULL) { + return NULL; + } + + lv_obj_t * label_row = create_row(parent, LV_FLEX_ALIGN_START); + lv_obj_t * label = lv_label_create(label_row); + lv_label_set_text(label, label_text); + lv_obj_set_width(label, LV_PCT(50)); + lv_obj_set_style_text_color(label, lv_color_white(), 0); + + snprintf(Buffer, sizeof(Buffer), "%i", init_val); + lv_obj_t * value_label = lv_label_create(label_row); + lv_label_set_text(value_label, Buffer); + lv_label_set_long_mode(value_label, LV_LABEL_LONG_CLIP); + lv_obj_set_width(value_label, 40); + lv_obj_set_height(value_label, 24); + lv_obj_set_style_text_align(value_label, LV_TEXT_ALIGN_CENTER, 0); + lv_obj_set_style_bg_color(value_label, lv_color_hex(0x7B3FF0), 0); + lv_obj_set_style_bg_opa(value_label, 255, 0); + lv_obj_set_style_text_color(value_label, lv_color_white(), 0); + lv_obj_set_style_radius(value_label, 6, 0); + lv_obj_set_style_pad_all(value_label, 5, 0); + lv_obj_clear_flag(value_label, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_style_margin_left(value_label, 10, 0); + + lv_obj_t * slider_row = create_row(parent, LV_FLEX_ALIGN_CENTER); + lv_obj_t * slider = lv_slider_create(slider_row); + lv_obj_clear_flag(slider, LV_OBJ_FLAG_GESTURE_BUBBLE); + + widgets->Slider = slider; + widgets->Label = value_label; + lv_obj_set_user_data(slider, widgets); + + lv_slider_set_range(slider, min_val, max_val); + lv_slider_set_value(slider, init_val, LV_ANIM_OFF); + lv_obj_set_width(slider, LV_PCT(90)); + lv_obj_set_style_bg_color(slider, lv_color_hex(0x7B3FF0), LV_PART_INDICATOR); + lv_obj_set_style_bg_color(slider, lv_color_hex(0x2E2E2E), LV_PART_MAIN); + lv_obj_set_style_bg_color(slider, lv_color_hex(0xFF9500), LV_PART_KNOB); + + return slider; +} + +static Menu_Page_Result_t create_menu_page_with_container(lv_obj_t * menu) { + lv_obj_t * page = lv_menu_page_create(menu, NULL); + lv_obj_t * section = lv_menu_section_create(page); + lv_obj_t * container = create_menu_container(section); + + lv_obj_set_scrollbar_mode(menu, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_scrollbar_mode(page, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_scrollbar_mode(section, LV_SCROLLBAR_MODE_OFF); + + lv_obj_remove_flag(page, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_remove_flag(section, LV_OBJ_FLAG_SCROLLABLE); + + lv_obj_set_style_pad_all(page, 0, 0); + lv_obj_set_style_pad_all(section, 0, 0); + lv_obj_set_style_border_width(page, 0, 0); + lv_obj_set_style_border_width(section, 0, 0); + + lv_obj_set_style_bg_opa(page, 0, 0); + lv_obj_set_style_bg_opa(section, 0, 0); + + return {container, page}; +} + +static lv_obj_t * create_text(lv_obj_t * parent, const char * txt) { + lv_obj_t * obj = lv_menu_cont_create(parent); + lv_obj_set_style_bg_color(obj, lv_color_hex(0x3A3A3A), LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_PRESSED); + lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUSED); + lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_CHECKED); + lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_EDITED); + lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUS_KEY); + lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_PRESSED | LV_STATE_CHECKED); + lv_obj_set_style_bg_opa(obj, 255, 0); + lv_obj_set_style_radius(obj, 6, 0); + lv_obj_set_style_pad_all(obj, 10, 0); + lv_obj_set_style_margin_bottom(obj, 4, 0); + lv_obj_set_style_border_width(obj, 15, LV_STATE_FOCUSED); + lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUSED); + lv_obj_set_style_border_width(obj, 15, LV_STATE_CHECKED); + lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_CHECKED); + lv_obj_set_style_border_width(obj, 15, LV_STATE_PRESSED); + lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_PRESSED); + lv_obj_set_style_border_width(obj, 15, LV_STATE_EDITED); + lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_EDITED); + lv_obj_set_style_border_width(obj, 15, LV_STATE_FOCUS_KEY); + lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUS_KEY); + lv_obj_set_style_shadow_width(obj, 15, LV_STATE_FOCUSED); + lv_obj_set_style_shadow_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUSED); + lv_obj_set_style_shadow_width(obj, 15, LV_STATE_CHECKED); + lv_obj_set_style_shadow_color(obj, lv_color_hex(0xFF9500), LV_STATE_CHECKED); + lv_obj_set_style_shadow_width(obj, 15, LV_STATE_PRESSED); + lv_obj_set_style_shadow_color(obj, lv_color_hex(0xFF9500), LV_STATE_PRESSED); + lv_obj_set_style_shadow_opa(obj, 180, LV_STATE_FOCUSED); + lv_obj_set_style_shadow_opa(obj, 180, LV_STATE_CHECKED); + lv_obj_set_style_shadow_opa(obj, 180, LV_STATE_PRESSED); + lv_obj_set_size(obj, LV_PCT(95), 36); + + lv_obj_t * label = NULL; + + if(txt) { + label = lv_label_create(obj); + lv_label_set_text(label, txt); + lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); + lv_obj_set_style_text_color(label, lv_color_white(), 0); + lv_obj_set_style_text_font(label, &lv_font_montserrat_14, 0); + lv_obj_set_flex_grow(label, 1); + } + + return obj; +} + +/** @brief Creates the About page. + * @param p_Menu Pointer to the menu object + */ +static lv_obj_t * ui_Settings_Create_About_Page(lv_obj_t *p_parent) +{ + lv_obj_t * cont; + lv_obj_t * section; + lv_obj_t * about_page; + lv_obj_t * about_container; + Menu_Page_Result_t about_result; + lv_obj_t * sub_software_info_page; + lv_obj_t * sub_legal_info_page; + char Buffer[64]; + + about_result = create_menu_page_with_container(p_parent); + about_container = about_result.Container; + about_page = about_result.Page; + + lv_menu_separator_create(about_page); + + sub_software_info_page = lv_menu_page_create(p_parent, NULL); + section = lv_menu_section_create(sub_software_info_page); + lv_obj_set_style_bg_color(section, lv_color_hex(0x1E1E1E), 0); + lv_obj_set_style_bg_opa(section, 255, 0); + lv_obj_set_style_pad_all(section, 8, 0); + create_text(section, "PyroVision Firmware"); + + memset(Buffer, 0, sizeof(Buffer)); + snprintf(Buffer, sizeof(Buffer), "Version %u.%u.%u", 1, 0, 0); + create_text(section, Buffer); + + memset(Buffer, 0, sizeof(Buffer)); + snprintf(Buffer, sizeof(Buffer), "Platform: %s", CONFIG_IDF_TARGET); + create_text(section, Buffer); + + memset(Buffer, 0, sizeof(Buffer)); + snprintf(Buffer, sizeof(Buffer), "LVGL Version: %d.%d.%d\n", LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, LVGL_VERSION_PATCH); + create_text(section, Buffer); + + sub_legal_info_page = lv_menu_page_create(p_parent, NULL); + section = lv_menu_section_create(sub_legal_info_page); + lv_obj_set_style_bg_color(section, lv_color_hex(0x1E1E1E), 0); + lv_obj_set_style_bg_opa(section, 255, 0); + lv_obj_set_style_pad_all(section, 8, 0); + + lv_obj_t * license_label = lv_label_create(section); + lv_label_set_text(license_label, + "(c) 2026 PyroVision Project\n" + "Licensed under GNU GPL v3\n" + "\n" + "This program is free software.\n" + "See LICENSE file for details."); + lv_obj_set_width(license_label, LV_PCT(95)); + lv_obj_set_style_text_color(license_label, lv_color_white(), 0); + lv_obj_set_style_text_align(license_label, LV_TEXT_ALIGN_LEFT, 0); + lv_label_set_long_mode(license_label, LV_LABEL_LONG_WRAP); + + cont = create_text(about_container, "Software information"); + lv_menu_set_load_page_event(p_parent, cont, sub_software_info_page); + cont = create_text(about_container, "Legal information"); + lv_menu_set_load_page_event(p_parent, cont, sub_legal_info_page); + + return about_page; +} + +/** @brief Creates the WiFi settings page and load it with the values from the settings. + * @param p_Menu Pointer to the menu object + */ +static lv_obj_t* ui_Settings_Create_WiFi_Page(lv_obj_t *p_Menu) +{ + Menu_Page_Result_t WiFiResult = create_menu_page_with_container(p_Menu); + lv_obj_t * WiFiContainer = WiFiResult.Container; + lv_obj_t * WiFiPage = WiFiResult.Page; + App_Settings_WiFi_t WiFiSettings; + + SettingsManager_GetWiFi(&WiFiSettings); + + lv_obj_t * wifi_row1 = create_row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t * wifi_label = lv_label_create(wifi_row1); + lv_label_set_text(wifi_label, "Autoconnect"); + lv_obj_set_style_text_color(wifi_label, lv_color_white(), 0); + + lv_obj_t * wifi_switch = lv_switch_create(wifi_row1); + lv_obj_set_style_bg_color(wifi_switch, lv_color_hex(0x7B3FF0), 0); + lv_obj_set_style_bg_color(wifi_switch, lv_color_hex(0xFF9500), LV_PART_KNOB); + lv_obj_add_event_cb(wifi_switch, on_WiFi_Autoconnect_Callback, LV_EVENT_VALUE_CHANGED, NULL); + + if(WiFiSettings.AutoConnect) { + lv_obj_add_state(wifi_switch, LV_STATE_CHECKED); + } else { + lv_obj_remove_state(wifi_switch, LV_STATE_CHECKED); + } + + lv_obj_t * wifi_row2 = create_row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t * ssid_label = lv_label_create(wifi_row2); + lv_label_set_text(ssid_label, "Status"); + lv_obj_set_style_text_color(ssid_label, lv_color_white(), 0); + wifi_status_label = lv_label_create(wifi_row2); + lv_label_set_text(wifi_status_label, "Offline"); + lv_obj_set_style_text_color(wifi_status_label, lv_color_hex(0xFF9500), 0); + + return WiFiPage; +} + +/** @brief Creates the display settings page and load it with the values from the settings. + * @param p_Menu Pointer to the menu object + */ +static lv_obj_t* ui_Settings_Create_Display_Page(lv_obj_t *p_Menu) +{ + Menu_Page_Result_t DisplayResult = create_menu_page_with_container(p_Menu); + lv_obj_t * DisplayContainer = DisplayResult.Container; + lv_obj_t * DisplayPage = DisplayResult.Page; + App_Settings_Display_t DisplaySettings; + + SettingsManager_GetDisplay(&DisplaySettings); + + lv_obj_t *brightness_slider = create_compact_slider(DisplayContainer, "Brightness", 0, 100, DisplaySettings.Brightness, &brightness_widgets); + + lv_obj_add_event_cb(brightness_slider, on_Display_Brightness_Slider_Callback, LV_EVENT_VALUE_CHANGED, NULL); + + return DisplayPage; +} + +/** @brief Creates the Lepton settings page and load it with the values from the settings. + * @param p_Menu Pointer to the menu object + */ +static lv_obj_t* ui_Settings_Create_Lepton_Page(lv_obj_t *p_Menu) +{ + std::string Buffer; + Menu_Page_Result_t LeptonResult = create_menu_page_with_container(p_Menu); + lv_obj_t * LeptonContainer = LeptonResult.Container; + lv_obj_t * LeptonPage = LeptonResult.Page; + App_Settings_Lepton_t LeptonSettings; + + SettingsManager_GetLepton(&LeptonSettings); + + for(size_t i = 0; i < LeptonSettings.EmissivityCount; i++) { + Buffer += LeptonSettings.EmissivityPresets[i].Description + std::string("\n"); + } + + lv_obj_t *emissivity_slider = create_compact_slider(LeptonContainer, "Emissivity", 0, 100, LeptonSettings.CurrentEmissivity, &emissivity_widgets); + + lv_obj_add_event_cb(emissivity_slider, on_Lepton_Emissivity_Slider_Callback, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb(emissivity_slider, on_Lepton_Emissivity_Slider_Callback, LV_EVENT_RELEASED, NULL); + + lv_obj_t * dropdown_row = create_row(LeptonContainer, LV_FLEX_ALIGN_CENTER); + emissivity_Dropdown = lv_dropdown_create(dropdown_row); + lv_obj_set_width(emissivity_Dropdown, LV_PCT(95)); + lv_obj_set_style_bg_color(emissivity_Dropdown, lv_color_hex(0x3A3A3A), LV_PART_MAIN); + lv_obj_set_style_border_color(emissivity_Dropdown, lv_color_hex(0xFF9500), LV_PART_MAIN); + lv_obj_set_style_border_width(emissivity_Dropdown, 2, LV_PART_MAIN); + lv_obj_set_style_radius(emissivity_Dropdown, 6, LV_PART_MAIN); + lv_obj_set_style_text_color(emissivity_Dropdown, lv_color_white(), LV_PART_MAIN); + lv_obj_set_style_pad_all(emissivity_Dropdown, 8, LV_PART_MAIN); + lv_obj_set_style_bg_color(emissivity_Dropdown, lv_color_hex(0xFF9500), LV_PART_SELECTED); + lv_obj_set_style_text_color(emissivity_Dropdown, lv_color_white(), LV_PART_SELECTED); + lv_obj_set_user_data(emissivity_Dropdown, &emissivity_widgets); + lv_obj_add_event_cb(emissivity_Dropdown, on_Lepton_Dropdown_Callback, LV_EVENT_VALUE_CHANGED, NULL); + lv_dropdown_set_options(emissivity_Dropdown, Buffer.c_str()); + lv_dropdown_set_selected(emissivity_Dropdown, 0); + + return LeptonPage; +} + +/** @brief Creates the Flash settings page and load it with the values from the settings. + * @param p_Menu Pointer to the menu object + */ +static lv_obj_t* ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) +{ + Menu_Page_Result_t FlashResult = create_menu_page_with_container(p_Menu); + lv_obj_t * FlashContainer = FlashResult.Container; + lv_obj_t * FlashPage = FlashResult.Page; + + lv_obj_t * flash_row1 = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t * flash_label1 = lv_label_create(flash_row1); + lv_label_set_text(flash_label1, "Used"); + lv_obj_set_style_text_color(flash_label1, lv_color_white(), 0); + lv_obj_t * flash_value1 = lv_label_create(flash_row1); + lv_label_set_text(flash_value1, "2.1 MB"); + lv_obj_set_style_text_color(flash_value1, lv_color_hex(0xB998FF), 0); + + lv_obj_t * flash_row2 = create_row(FlashContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_t * flash_btn = lv_btn_create(flash_row2); + lv_obj_set_width(flash_btn, 90); + lv_obj_set_style_bg_color(flash_btn, lv_color_hex(0xFF3B3B), LV_STATE_DEFAULT); + lv_obj_set_style_radius(flash_btn, 6, 0); + lv_obj_t * flash_btn_label = lv_label_create(flash_btn); + lv_label_set_text(flash_btn_label, "Clear"); + lv_obj_set_style_text_color(flash_btn_label, lv_color_white(), 0); + lv_obj_center(flash_btn_label); + + return FlashPage; +} + +void ui_settings_build(lv_obj_t *p_Parent) +{ + menu = lv_menu_create(p_Parent); + settings_Menu = menu; + lv_obj_set_size(menu, lv_pct(100), lv_pct(100)); + lv_obj_center(menu); + lv_obj_set_style_bg_color(menu, lv_color_hex(0x1E1E1E), 0); + lv_obj_set_style_bg_opa(menu, 255, 0); + + lv_menu_set_mode_header(menu, LV_MENU_HEADER_TOP_FIXED); + + wifi_Page = ui_Settings_Create_WiFi_Page(menu); + display_Page = ui_Settings_Create_Display_Page(menu); + lepton_Page = ui_Settings_Create_Lepton_Page(menu); + flash_Page = ui_Settings_Create_Flash_Page(menu); + about_Page = ui_Settings_Create_About_Page(menu); + + root_page = lv_menu_page_create(menu, NULL); + lv_obj_set_style_bg_color(root_page, lv_color_hex(0x1E1E1E), 0); + lv_obj_set_style_bg_opa(root_page, 255, 0); + + section = lv_menu_section_create(root_page); + lv_obj_set_style_bg_color(section, lv_color_hex(0x1E1E1E), 0); + lv_obj_set_style_bg_opa(section, 255, 0); + lv_obj_set_style_pad_all(section, 8, 0); + + cont = create_text(section, "WiFi"); + lv_menu_set_load_page_event(menu, cont, wifi_Page); + + cont = create_text(section, "Display"); + lv_menu_set_load_page_event(menu, cont, display_Page); + + cont = create_text(section, "Lepton"); + lv_menu_set_load_page_event(menu, cont, lepton_Page); + + cont = create_text(section, "Flash"); + lv_menu_set_load_page_event(menu, cont, flash_Page); + + cont = create_text(section, "About"); + lv_menu_set_load_page_event(menu, cont, about_Page); + + lv_menu_set_sidebar_page(menu, root_page); + + esp_event_handler_register(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler, NULL); +} + +void ui_settings_deinit(lv_obj_t *p_Parent) +{ + if(ui_Splash) { + lv_obj_del(settings_Menu); + lv_obj_delete(settings_Menu); + + esp_event_handler_unregister(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler); + } +} \ No newline at end of file diff --git a/main/Application/Tasks/GUI/UI/ui_Settings.h b/main/Application/Tasks/GUI/UI/ui_Settings.h new file mode 100644 index 0000000..2f74b5e --- /dev/null +++ b/main/Application/Tasks/GUI/UI/ui_Settings.h @@ -0,0 +1,38 @@ +/* + * ui_Settings.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Settings UI implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef UI_SETTINGS_H_ +#define UI_SETTINGS_H_ + +#include + +#include + +extern lv_obj_t * wifi_status_label; + +/** @brief Builds the settings UI. + * @param p_Parent Pointer to the parent object where the settings UI will be attached + */ +void ui_settings_build(lv_obj_t * p_Parent); + +#endif /* UI_SETTINGS_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp index 2cd4035..0dce948 100644 --- a/main/Application/Tasks/GUI/guiTask.cpp +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -304,6 +304,8 @@ static void GUI_Update_Info(void) lv_label_set_text(ui_Label_Info_Lepton_Serial, _GUITask_State.LeptonDeviceInfo.SerialNumber); lv_label_set_text(ui_Label_Info_Lepton_Part, _GUITask_State.LeptonDeviceInfo.PartNumber); + lv_label_set_text(ui_Label_Info_Lepton_GPP_Revision, _GUITask_State.LeptonDeviceInfo.SoftwareRevision.GPP_Revision); + lv_label_set_text(ui_Label_Info_Lepton_DSP_Revision, _GUITask_State.LeptonDeviceInfo.SoftwareRevision.DSP_Revision); lv_label_set_text(ui_Label_Info_MAC, mac_str); } @@ -393,10 +395,10 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) SettingsManager_GetLepton(&SettingsLepton); /* Check if an update is required */ - if (SettingsLepton.ROI[ROI.Type].x == ROI.x && - SettingsLepton.ROI[ROI.Type].y == ROI.y && - SettingsLepton.ROI[ROI.Type].w == ROI.w && - SettingsLepton.ROI[ROI.Type].h == ROI.h) { + if ((SettingsLepton.ROI[ROI.Type].x == ROI.x) && + (SettingsLepton.ROI[ROI.Type].y == ROI.y) && + (SettingsLepton.ROI[ROI.Type].w == ROI.w) && + (SettingsLepton.ROI[ROI.Type].h == ROI.h)) { ESP_LOGW(TAG, "ROI unchanged, not updating NVS"); return; } @@ -466,9 +468,14 @@ static void Touch_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data esp_lcd_touch_handle_t Touch; Touch = (esp_lcd_touch_handle_t)lv_indev_get_user_data(p_Indev); - esp_lcd_touch_read_data(Touch); + + /* Check if touch controller is available */ + if (Touch == NULL) { + p_Data->state = LV_INDEV_STATE_RELEASED; + return; + } - if ((esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])) == ESP_OK) && (Count > 0)) { + if ((esp_lcd_touch_read_data(Touch) == ESP_OK) && (esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])) == ESP_OK) && (Count > 0)) { p_Data->point.x = CONFIG_GUI_WIDTH - Data[0].x; p_Data->point.y = Data[0].y; @@ -573,16 +580,43 @@ void Task_GUI(void *p_Parameters) /* Check for new thermal frame */ if (xQueueReceive(App_Context->Lepton_FrameEventQueue, &LeptonFrame, 0) == pdTRUE) { - uint8_t *dst; + uint8_t *Dst; uint32_t Image_Width; uint32_t Image_Height; - char temp_buf[16]; + char Buffer[16]; + + /* Variables for Illuminance values for the scene label. + * Fetch all these values at the beginning to not waste CPU performance because these + * functions aren´t simple get functions + * 0 = Max label + * 1 = Min label + * 2 = Mean label + */ + int32_t SceneLabel_x0[3] = { lv_obj_get_x(ui_Label_Main_Thermal_Scene_Max), + lv_obj_get_x(ui_Label_Main_Thermal_Scene_Min), + lv_obj_get_x(ui_Label_Main_Thermal_Scene_Mean) + }; + int32_t SceneLabel_y0[3] = { lv_obj_get_y(ui_Label_Main_Thermal_Scene_Max), + lv_obj_get_y(ui_Label_Main_Thermal_Scene_Min), + lv_obj_get_y(ui_Label_Main_Thermal_Scene_Mean) + }; + int32_t SceneLabel_w[3] = { lv_obj_get_width(ui_Label_Main_Thermal_Scene_Max), + lv_obj_get_width(ui_Label_Main_Thermal_Scene_Min), + lv_obj_get_width(ui_Label_Main_Thermal_Scene_Mean) + }; + int32_t SceneLabel_h[3] = { lv_obj_get_height(ui_Label_Main_Thermal_Scene_Max), + lv_obj_get_height(ui_Label_Main_Thermal_Scene_Min), + lv_obj_get_height(ui_Label_Main_Thermal_Scene_Mean) + }; + uint32_t SceneLabelIlluminance[3] = {0, 0, 0}; + uint32_t SceneLabelCount[3] = {0, 0, 0}; + uint8_t SceneLabelAverageLuminance[3] = {0, 0, 0}; /* Reset watchdog before image processing */ esp_task_wdt_reset(); /* Scale from source (160x120) to destination (240x180) using bilinear interpolation */ - dst = _GUITask_State.ThermalCanvasBuffer; + Dst = _GUITask_State.ThermalCanvasBuffer; Image_Width = lv_obj_get_width(ui_Image_Thermal); Image_Height = lv_obj_get_height(ui_Image_Thermal); @@ -592,32 +626,28 @@ void Task_GUI(void *p_Parameters) continue; } - /* Pre-calculate scaling factors (fixed-point 16.16) */ - uint32_t x_ratio = ((LeptonFrame.Width - 1) << 16) / Image_Width; - uint32_t y_ratio = ((LeptonFrame.Height - 1) << 16) / Image_Height; - - for (uint32_t dst_y = 0; dst_y < Image_Height; dst_y++) { - uint32_t src_y_fixed = dst_y * y_ratio; + for (uint32_t y = 0; y < Image_Height; y++) { + uint32_t src_y_fixed = y * ((LeptonFrame.Height - 1) << 16) / Image_Height; uint32_t y0 = src_y_fixed >> 16; - uint32_t y1 = (y0 + 1 < LeptonFrame.Height) ? y0 + 1 : y0; + uint32_t y1 = ((y0 + 1) < LeptonFrame.Height) ? (y0 + 1) : y0; uint32_t y_frac = (src_y_fixed >> 8) & 0xFF; /* 8-bit fractional part */ uint32_t y_inv = 256 - y_frac; - for (uint32_t dst_x = 0; dst_x < Image_Width; dst_x++) { - uint32_t src_x_fixed = dst_x * x_ratio; + for (uint32_t x = 0; x < Image_Width; x++) { + uint32_t src_x_fixed = x * ((LeptonFrame.Width - 1) << 16) / Image_Width; uint32_t x0 = src_x_fixed >> 16; - uint32_t x1 = (x0 + 1 < LeptonFrame.Width) ? x0 + 1 : x0; + uint32_t x1 = ((x0 + 1) < LeptonFrame.Width) ? (x0 + 1) : x0; uint32_t x_frac = (src_x_fixed >> 8) & 0xFF; /* 8-bit fractional part */ uint32_t x_inv = 256 - x_frac; /* Get the four surrounding pixels */ - uint32_t idx00 = (y0 * LeptonFrame.Width + x0) * 3; - uint32_t idx10 = (y0 * LeptonFrame.Width + x1) * 3; - uint32_t idx01 = (y1 * LeptonFrame.Width + x0) * 3; - uint32_t idx11 = (y1 * LeptonFrame.Width + x1) * 3; + uint32_t idx00 = ((y0 * LeptonFrame.Width) + x0) * 3; + uint32_t idx10 = ((y0 * LeptonFrame.Width) + x1) * 3; + uint32_t idx01 = ((y1 * LeptonFrame.Width) + x0) * 3; + uint32_t idx11 = ((y1 * LeptonFrame.Width) + x1) * 3; /* Bilinear interpolation using fixed-point arithmetic (8.8 format) */ - /* Weight: (256-x_frac)*(256-y_frac), x_frac*(256-y_frac), etc. */ + /* Weight: (256 - x_frac) * (256 - y_frac), x_frac*(256 - y_frac), etc. */ uint32_t w00 = (x_inv * y_inv) >> 8; uint32_t w10 = (x_frac * y_inv) >> 8; uint32_t w01 = (x_inv * y_frac) >> 8; @@ -633,39 +663,83 @@ void Task_GUI(void *p_Parameters) LeptonFrame.Buffer[idx01 + 1] * w01 + LeptonFrame.Buffer[idx11 + 1] * w11) >> 8; - uint32_t b_val = (LeptonFrame.Buffer[idx00 + 2] * w00 + - LeptonFrame.Buffer[idx10 + 2] * w10 + - LeptonFrame.Buffer[idx01 + 2] * w01 + - LeptonFrame.Buffer[idx11 + 2] * w11) >> 8; + uint32_t b = (LeptonFrame.Buffer[idx00 + 2] * w00 + + LeptonFrame.Buffer[idx10 + 2] * w10 + + LeptonFrame.Buffer[idx01 + 2] * w01 + + LeptonFrame.Buffer[idx11 + 2] * w11) >> 8; + + /* Inside the image area under the label: Add the Luminance + * Note: The image widget has 180° rotation applied via lv_image_set_rotation. + * - x_rot = Image_Width - 1 - x (X axis is inverted due to rotation) + * - y is used directly (Y axis matches label position directly) + */ + uint32_t x_rot = Image_Width - 1 - x; + + /* Max Label */ + if ((x_rot >= SceneLabel_x0[0]) && + (x_rot < (SceneLabel_x0[0] + SceneLabel_w[0])) && + (y >= SceneLabel_y0[0]) && + (y < (SceneLabel_y0[0] + SceneLabel_h[0]))) { + SceneLabelIlluminance[0] += static_cast((0.299f * r) + (0.587f * g) + (0.114f * b)); + SceneLabelCount[0]++; + } - /* Destination pixel index (rotated 180 degrees) */ - uint32_t rot_y = Image_Height - 1 - dst_y; - uint32_t rot_x = Image_Width - 1 - dst_x; - uint32_t dst_idx = rot_y * Image_Width + rot_x; + /* Min Label */ + if ((x_rot >= SceneLabel_x0[1]) && + (x_rot < (SceneLabel_x0[1] + SceneLabel_w[1])) && + (y >= SceneLabel_y0[1]) && + (y < (SceneLabel_y0[1] + SceneLabel_h[1]))) { + SceneLabelIlluminance[1] += static_cast((0.299f * r) + (0.587f * g) + (0.114f * b)); + SceneLabelCount[1]++; + } + + /* Mean Label */ + if ((x_rot >= SceneLabel_x0[2]) && + (x_rot < (SceneLabel_x0[2] + SceneLabel_w[2])) && + (y >= SceneLabel_y0[2]) && + (y < (SceneLabel_y0[2] + SceneLabel_h[2]))) { + SceneLabelIlluminance[2] += static_cast((0.299f * r) + (0.587f * g) + (0.114f * b)); + SceneLabelCount[2]++; + } + + uint32_t dst_idx = (y * Image_Width) + x; /* Convert to RGB565 - LVGL handles swapping with RGB565_SWAPPED */ - uint16_t rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b_val >> 3); + uint16_t rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); /* Low byte first */ - dst[dst_idx * 2 + 0] = rgb565 & 0xFF; + Dst[(dst_idx * 2) + 0] = rgb565 & 0xFF; /* High byte second */ - dst[dst_idx * 2 + 1] = (rgb565 >> 8) & 0xFF; + Dst[(dst_idx * 2) + 1] = (rgb565 >> 8) & 0xFF; } } + /* Set the average Luminance and the text color */ + for (uint8_t i = 0; i < (sizeof(SceneLabelAverageLuminance) / sizeof(SceneLabelAverageLuminance[0])); i++) { + if (SceneLabelCount[i] > 0) { + SceneLabelAverageLuminance[i] = SceneLabelIlluminance[i] / SceneLabelCount[i]; + } else { + SceneLabelAverageLuminance[i] = 0; + } + } + + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Max, (SceneLabelAverageLuminance[0] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Min, (SceneLabelAverageLuminance[1] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Mean, (SceneLabelAverageLuminance[2] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); + /* Reset watchdog after image processing */ esp_task_wdt_reset(); /* Max temperature (top of gradient) */ float temp_max_celsius = (LeptonFrame.Max / 100.0f) - 273.15f; - snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_max_celsius); - lv_label_set_text(ui_Label_TempScaleMax, temp_buf); + snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_max_celsius); + lv_label_set_text(ui_Label_TempScaleMax, Buffer); /* Min temperature (bottom of gradient) */ float temp_min_celsius = (LeptonFrame.Min / 100.0f) - 273.15f; - snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_min_celsius); - lv_label_set_text(ui_Label_TempScaleMin, temp_buf); + snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_min_celsius); + lv_label_set_text(ui_Label_TempScaleMin, Buffer); /* Trigger LVGL to redraw the image */ lv_obj_invalidate(ui_Image_Thermal); @@ -674,36 +748,33 @@ void Task_GUI(void *p_Parameters) /* Update network frame for server streaming if server is running */ if (Server_isRunning()) { - if (xSemaphoreTake(_GUITask_State.NetworkFrame.mutex, 0) == pdTRUE) { + if (xSemaphoreTake(_GUITask_State.NetworkFrame.Mutex, 0) == pdTRUE) { /* Convert scaled RGB565 buffer to RGB888 for network transmission */ uint8_t *rgb888_dst = _GUITask_State.NetworkRGBBuffer; - for (uint32_t i = 0; i < Image_Width * Image_Height; i++) { + for (uint32_t i = 0; i < (Image_Width * Image_Height); i++) { /* Read RGB565 value (little endian) */ - uint16_t rgb565 = dst[i * 2 + 0] | (dst[i * 2 + 1] << 8); + uint16_t rgb565 = Dst[(i * 2) + 0] | (Dst[(i * 2) + 1] << 8); /* Convert RGB565 to RGB888 */ - uint8_t r = ((rgb565 >> 11) & 0x1F) * 255 / 31; - uint8_t g = ((rgb565 >> 5) & 0x3F) * 255 / 63; - uint8_t b = (rgb565 & 0x1F) * 255 / 31; + uint8_t r = (rgb565 >> 8) & 0xF8; + uint8_t g = (rgb565 >> 3) & 0xFC; + uint8_t b = (rgb565 << 3) & 0xF8; /* Store as RGB888 */ - rgb888_dst[i * 3 + 0] = r; - rgb888_dst[i * 3 + 1] = g; - rgb888_dst[i * 3 + 2] = b; + rgb888_dst[(i * 3) + 0] = r; + rgb888_dst[(i * 3) + 1] = g; + rgb888_dst[(i * 3) + 2] = b; } - _GUITask_State.NetworkFrame.buffer = _GUITask_State.NetworkRGBBuffer; - _GUITask_State.NetworkFrame.width = Image_Width; - _GUITask_State.NetworkFrame.height = Image_Height; - _GUITask_State.NetworkFrame.timestamp = esp_timer_get_time() / 1000; + _GUITask_State.NetworkFrame.Buffer = _GUITask_State.NetworkRGBBuffer; + _GUITask_State.NetworkFrame.Width = Image_Width; + _GUITask_State.NetworkFrame.Height = Image_Height; + _GUITask_State.NetworkFrame.Timestamp = esp_timer_get_time() / 1000; - xSemaphoreGive(_GUITask_State.NetworkFrame.mutex); + xSemaphoreGive(_GUITask_State.NetworkFrame.Mutex); } - /* Notify Websocket handler that a new frame is ready (non-blocking) */ - if (WebSocket_Handler_HasClients()) { - WebSocket_Handler_NotifyFrameReady(); - } + Server_NotifyClients(); } } @@ -781,58 +852,47 @@ void Task_GUI(void *p_Parameters) xEventGroupClearBits(_GUITask_State.EventGroup, SD_CARD_MOUNT_ERROR); } else if (EventBits & LEPTON_SPOTMETER_READY) { - // TODO: Can we move this to the network task? - if (Server_isRunning()) { - if (xSemaphoreTake(_GUITask_State.NetworkFrame.mutex, 0) == pdTRUE) { - _GUITask_State.NetworkFrame.temp_min = _GUITask_State.ROIResult.Min; - _GUITask_State.NetworkFrame.temp_max = _GUITask_State.ROIResult.Max; - _GUITask_State.NetworkFrame.temp_avg = _GUITask_State.ROIResult.Average; - - xSemaphoreGive(_GUITask_State.NetworkFrame.mutex); - } - } - xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_SPOTMETER_READY); } else if (EventBits & LEPTON_UPTIME_READY) { - char buf[32]; - uint32_t uptime_sec; + char Buffer[32]; + uint32_t Uptime; - uptime_sec = _GUITask_State.LeptonUptime / 1000; + Uptime = _GUITask_State.LeptonUptime / 1000; - snprintf(buf, sizeof(buf), "%02lu:%02lu:%02lu", uptime_sec / 3600, (uptime_sec % 3600) / 60, uptime_sec % 60); - lv_label_set_text(ui_Label_Info_Lepton_Uptime, buf); + snprintf(Buffer, sizeof(Buffer), "%02lu:%02lu:%02lu", Uptime / 3600, (Uptime % 3600) / 60, Uptime % 60); + lv_label_set_text(ui_Label_Info_Lepton_Uptime, Buffer); xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_UPTIME_READY); } else if (EventBits & LEPTON_TEMP_READY) { - char buf[32]; + char Buffer[32]; - snprintf(buf, sizeof(buf), "%.2f °C", _GUITask_State.LeptonTemperatures.FPA); - lv_label_set_text(ui_Label_Info_Lepton_FPA, buf); - snprintf(buf, sizeof(buf), "%.2f °C", _GUITask_State.LeptonTemperatures.AUX); - lv_label_set_text(ui_Label_Info_Lepton_AUX, buf); + snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUITask_State.LeptonTemperatures.FPA); + lv_label_set_text(ui_Label_Info_Lepton_FPA, Buffer); + snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUITask_State.LeptonTemperatures.AUX); + lv_label_set_text(ui_Label_Info_Lepton_AUX, Buffer); xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_TEMP_READY); } else if (EventBits & LEPTON_PIXEL_TEMPERATURE_READY) { - char buf[16]; + char Buffer[16]; - snprintf(buf, sizeof(buf), "%.2f °C", _GUITask_State.SpotTemperature); - lv_label_set_text(ui_Label_Main_Thermal_PixelTemperature, buf); + snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUITask_State.SpotTemperature); + lv_label_set_text(ui_Label_Main_Thermal_PixelTemperature, Buffer); xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); } else if (EventBits & LEPTON_SCENE_STATISTICS_READY) { - char temp_buf[16]; + char Buffer[16]; float temp_max_celsius = _GUITask_State.ROIResult.Max; - snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_max_celsius); - lv_label_set_text(ui_Label_Main_Thermal_Scene_Max, temp_buf); + snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_max_celsius); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Max, Buffer); float temp_min_celsius = _GUITask_State.ROIResult.Min; - snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_min_celsius); - lv_label_set_text(ui_Label_Main_Thermal_Scene_Min, temp_buf); + snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_min_celsius); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Min, Buffer); float temp_mean_celsius = _GUITask_State.ROIResult.Mean ; - snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", temp_mean_celsius); - lv_label_set_text(ui_Label_Main_Thermal_Scene_Mean, temp_buf); + snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_mean_celsius); + lv_label_set_text(ui_Label_Main_Thermal_Scene_Mean, Buffer); xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_SCENE_STATISTICS_READY); } @@ -861,16 +921,8 @@ esp_err_t GUI_Task_Init(void) ESP_ERROR_CHECK(GUI_Helper_Init(&_GUITask_State, Touch_LVGL_ReadCallback)); - /* Initialize the UI elements and trigger a redraw to make all elements accessibile */ ui_init(); - /* Use the event loop to receive control signals from other tasks */ - esp_event_handler_register(DEVICE_EVENTS, ESP_EVENT_ANY_ID, on_Devices_Event_Handler, NULL); - esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL); - esp_event_handler_register(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler, NULL); - esp_event_handler_register(TIME_EVENTS, ESP_EVENT_ANY_ID, on_Time_Event_Handler, NULL); - esp_event_handler_register(SD_EVENTS, ESP_EVENT_ANY_ID, on_SD_Event_Handler, NULL); - _GUITask_State.ThermalCanvasBuffer = (uint8_t *)heap_caps_malloc(240 * 180 * 2, MALLOC_CAP_SPIRAM); _GUITask_State.GradientCanvasBuffer = (uint8_t *)heap_caps_malloc(20 * 180 * 2, MALLOC_CAP_SPIRAM); _GUITask_State.NetworkRGBBuffer = (uint8_t *)heap_caps_malloc(240 * 180 * 3, MALLOC_CAP_SPIRAM); @@ -955,8 +1007,8 @@ esp_err_t GUI_Task_Init(void) #endif /* Initialize network frame for server streaming */ - _GUITask_State.NetworkFrame.mutex = xSemaphoreCreateMutex(); - if (_GUITask_State.NetworkFrame.mutex == NULL) { + _GUITask_State.NetworkFrame.Mutex = xSemaphoreCreateMutex(); + if (_GUITask_State.NetworkFrame.Mutex == NULL) { ESP_LOGE(TAG, "Failed to create NetworkFrame mutex!"); heap_caps_free(_GUITask_State.ThermalCanvasBuffer); heap_caps_free(_GUITask_State.GradientCanvasBuffer); @@ -964,6 +1016,13 @@ esp_err_t GUI_Task_Init(void) return ESP_ERR_NO_MEM; } + /* Use the event loop to receive control signals from other tasks */ + esp_event_handler_register(DEVICE_EVENTS, ESP_EVENT_ANY_ID, on_Devices_Event_Handler, NULL); + esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL); + esp_event_handler_register(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler, NULL); + esp_event_handler_register(TIME_EVENTS, ESP_EVENT_ANY_ID, on_Time_Event_Handler, NULL); + esp_event_handler_register(SD_EVENTS, ESP_EVENT_ANY_ID, on_SD_Event_Handler, NULL); + _GUITask_State.isInitialized = true; return ESP_OK; @@ -985,9 +1044,9 @@ void GUI_Task_Deinit(void) GUI_Helper_Deinit(&_GUITask_State); - if (_GUITask_State.NetworkFrame.mutex != NULL) { - vSemaphoreDelete(_GUITask_State.NetworkFrame.mutex); - _GUITask_State.NetworkFrame.mutex = NULL; + if (_GUITask_State.NetworkFrame.Mutex != NULL) { + vSemaphoreDelete(_GUITask_State.NetworkFrame.Mutex); + _GUITask_State.NetworkFrame.Mutex = NULL; } _GUITask_State.Display = NULL; diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp index 3c0d99d..6afaf2e 100644 --- a/main/Application/Tasks/Lepton/leptonTask.cpp +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -56,7 +56,6 @@ typedef struct { EventGroupHandle_t EventGroup; uint8_t *RGB_Buffer[2]; uint8_t CurrentReadBuffer; - uint16_t Emissivity; SemaphoreHandle_t BufferMutex; QueueHandle_t RawFrameQueue; Lepton_FrameBuffer_t RawFrame; @@ -64,12 +63,45 @@ typedef struct { Lepton_t Lepton; App_Settings_ROI_t ROI; App_GUI_Screenposition_t ScreenPosition; + SettingsManager_Setting_t NewSetting; } Lepton_Task_State_t; static Lepton_Task_State_t _LeptonTask_State; static const char *TAG = "lepton_task"; +/** @brief + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "Settings event received: ID=%d", ID); + + switch (ID) { + case SETTINGS_EVENT_LEPTON_CHANGED: { + memcpy(&_LeptonTask_State.NewSetting, p_Data, sizeof(SettingsManager_Setting_t)); + + ESP_LOGD(TAG, "Lepton settings changed: ID=%d", _LeptonTask_State.NewSetting.ID); + ESP_LOGD(TAG, "Lepton settings changed: Value=%d", _LeptonTask_State.NewSetting.Value); + + if(_LeptonTask_State.NewSetting.ID == SETTINGS_ID_LEPTON_EMISSIVITY) { + xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); + } + + break; + } + } +} + +/** @brief + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) { ESP_LOGD(TAG, "GUI event received: ID=%d", ID); @@ -115,13 +147,6 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int break; } - case GUI_EVENT_REQUEST_EMISSIVITY: { - _LeptonTask_State.Emissivity = *(uint16_t *)p_Data; - - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); - - break; - } default: { ESP_LOGW(TAG, "Unhandled GUI event ID: %d", ID); break; @@ -129,6 +154,20 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int } } +/** @brief Loads the Lepton settings from the Settings Manager and applies them to the Lepton. + */ +static void Lepton_LoadSettings(void) +{ + App_Settings_Lepton_t LeptonSettings; + + SettingsManager_GetLepton(&LeptonSettings); + + ESP_LOGI(TAG, "Loading Lepton settings..."); + ESP_LOGI(TAG, "Emissivity: %d", LeptonSettings.CurrentEmissivity); + + Lepton_SetEmissivity(&_LeptonTask_State.Lepton, static_cast(LeptonSettings.CurrentEmissivity)); +} + /** @brief Lepton camera task main loop. * @param p_Parameters Task parameters */ @@ -162,8 +201,22 @@ static void Task_Lepton(void *p_Parameters) _LeptonTask_State.Lepton.SerialNumber[6], _LeptonTask_State.Lepton.SerialNumber[7]); memcpy(DeviceInfo.PartNumber, _LeptonTask_State.Lepton.PartNumber, sizeof(DeviceInfo.PartNumber)); + snprintf(DeviceInfo.SoftwareRevision.GPP_Revision, sizeof(DeviceInfo.SoftwareRevision.GPP_Revision), + "%u.%u.%u", + _LeptonTask_State.Lepton.SoftwareVersion.gpp_major, + _LeptonTask_State.Lepton.SoftwareVersion.gpp_minor, + _LeptonTask_State.Lepton.SoftwareVersion.gpp_build); + + snprintf(DeviceInfo.SoftwareRevision.DSP_Revision, sizeof(DeviceInfo.SoftwareRevision.DSP_Revision), + "%u.%u.%u", + _LeptonTask_State.Lepton.SoftwareVersion.dsp_major, + _LeptonTask_State.Lepton.SoftwareVersion.dsp_minor, + _LeptonTask_State.Lepton.SoftwareVersion.dsp_build); + ESP_LOGD(TAG, " Part number: %s", DeviceInfo.PartNumber); ESP_LOGD(TAG, " Serial number: %s", DeviceInfo.SerialNumber); + ESP_LOGI(TAG, " GPP revision: %s", DeviceInfo.SoftwareRevision.GPP_Revision); + ESP_LOGI(TAG, " DSP revision: %s", DeviceInfo.SoftwareRevision.DSP_Revision); esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_READY, &DeviceInfo, sizeof(App_Lepton_Device_t), portMAX_DELAY); @@ -187,6 +240,8 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGD(TAG, "Start image capturing..."); + Lepton_LoadSettings(); + if (Lepton_StartCapture(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrameQueue) != LEPTON_ERR_OK) { ESP_LOGE(TAG, "Can not start image capturing!"); esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); @@ -436,11 +491,11 @@ static void Task_Lepton(void *p_Parameters) } else if (EventBits & LEPTON_TASK_UPDATE_EMISSIVITY) { Lepton_Error_t Error; - Error = Lepton_SetEmissivity(&_LeptonTask_State.Lepton, static_cast(_LeptonTask_State.Emissivity)); + Error = Lepton_SetEmissivity(&_LeptonTask_State.Lepton, static_cast(_LeptonTask_State.NewSetting.Value)); if (Error == LEPTON_ERR_OK) { - ESP_LOGD(TAG, "Updated emissivity to %u", _LeptonTask_State.Emissivity); + ESP_LOGD(TAG, "Updated emissivity to %u", _LeptonTask_State.NewSetting.Value); } else { - ESP_LOGE(TAG, "Failed to update emissivity to %u!", _LeptonTask_State.Emissivity); + ESP_LOGE(TAG, "Failed to update emissivity to %u!", _LeptonTask_State.NewSetting.Value); } xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); @@ -531,6 +586,7 @@ esp_err_t Lepton_Task_Init(void) /* Use the event loop to receive control signals from other tasks */ esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL); + esp_event_handler_register(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler, NULL); ESP_LOGD(TAG, "Lepton Task initialized"); @@ -556,6 +612,7 @@ void Lepton_Task_Deinit(void) _LeptonTask_State.EventGroup = NULL; } + esp_event_handler_unregister(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler); esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); Lepton_Deinit(&_LeptonTask_State.Lepton); diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index 3bb1ceb..09bf081 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -46,6 +46,7 @@ #define NETWORK_TASK_SNTP_TIMEZONE_SET BIT7 #define NETWORK_TASK_SNTP_TIME_SYNCED BIT8 #define NETWORK_TASK_WIFI_CREDENTIALS_UPDATED BIT10 +#define LEPTON_SPOTMETER_READY BIT11 typedef struct { bool isInitialized; @@ -61,12 +62,34 @@ typedef struct { App_Context_t *AppContext; char SSID[33]; char Password[65]; + App_Lepton_ROI_Result_t ROIResult; } Network_Task_State_t; static Network_Task_State_t _NetworkTask_State; static const char *TAG = "network_task"; +/** @brief + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_Lepton_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "Lepton event received: ID=%d", ID); + + switch (ID) { + case LEPTON_EVENT_RESPONSE_SPOTMETER: { + memcpy(&_NetworkTask_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); + + xEventGroupSetBits(_NetworkTask_State.EventGroup, LEPTON_SPOTMETER_READY); + + break; + } + } +} + /** @brief SNTP event handler for task coordination. * @param p_HandlerArgs Handler argument * @param Base Event base @@ -361,6 +384,11 @@ static void Task_Network(void *p_Parameters) SettingsManager_Save(); xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); + } else if (EventBits & LEPTON_SPOTMETER_READY) { + if (Server_isRunning()) { + + } + xEventGroupClearBits(_NetworkTask_State.EventGroup, LEPTON_SPOTMETER_READY); } vTaskDelay(10 / portTICK_PERIOD_MS); @@ -416,7 +444,8 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) if ((esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL) != ESP_OK) || (esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL) != ESP_OK) || - (esp_event_handler_register(SNTP_EVENTS, ESP_EVENT_ANY_ID, on_SNTP_Event_Handler, NULL) != ESP_OK)) { + (esp_event_handler_register(SNTP_EVENTS, ESP_EVENT_ANY_ID, on_SNTP_Event_Handler, NULL) != ESP_OK) || + (esp_event_handler_register(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler, NULL) != ESP_OK)) { ESP_LOGE(TAG, "Failed to register event handler: %d!", Error); vEventGroupDelete(_NetworkTask_State.EventGroup); @@ -483,6 +512,7 @@ void Network_Task_Deinit(void) Provisioning_Deinit(); NetworkManager_Deinit(); + esp_event_handler_unregister(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler); esp_event_handler_unregister(SNTP_EVENTS, ESP_EVENT_ANY_ID, on_SNTP_Event_Handler); esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); diff --git a/main/Application/application.h b/main/Application/application.h index d0b8145..acfb64a 100644 --- a/main/Application/application.h +++ b/main/Application/application.h @@ -38,7 +38,8 @@ ESP_EVENT_DECLARE_BASE(SD_EVENTS); /** @brief Lepton camera event identifiers. */ enum { - LEPTON_EVENT_CAMERA_READY, /**< Lepton camera is ready. */ + LEPTON_EVENT_CAMERA_READY, /**< Lepton camera is ready. + Data is transmitted in a App_Lepton_Device_t structure. */ LEPTON_EVENT_CAMERA_ERROR, /**< Lepton camera error occurred. */ LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP, /**< FPA and AUX temperatures are ready. Data is transmitted in a App_Lepton_Temperatures_t structure. */ @@ -72,13 +73,10 @@ enum { Data is transmitted in a App_Settings_ROI_t structure. */ GUI_EVENT_REQUEST_FPA_AUX_TEMP, /**< Request update of the FPA and AUX temperature. */ GUI_EVENT_REQUEST_UPTIME, /**< Request update of the uptime. */ - GUI_EVENT_UPDATE_INFO, /**< Update the information screen. */ GUI_EVENT_REQUEST_PIXEL_TEMPERATURE, /**< Request update of pixel temperature. Data is transmitted in a App_GUI_Screenposition_t structure. */ GUI_EVENT_REQUEST_SPOTMETER, /**< Request update of spotmeter data. */ GUI_EVENT_REQUEST_SCENE_STATISTICS, /**< Request update of scene statistics data. */ - GUI_EVENT_REQUEST_EMISSIVITY, /**< Request update of the emissivity setting. - Data is transmitted as a uint16_t (Emissivity multiplied by 100). */ }; /** @brief Structure representing a screen position. @@ -119,7 +117,11 @@ typedef struct { */ typedef struct { char PartNumber[33]; /**< Lepton device part number. */ - char SerialNumber[24]; /**< Lepton device serial number formatted as "XXXX-XXXX-XXXX-XXXX". */ + char SerialNumber[24]; /**< Lepton device serial number. */ + struct { + char GPP_Revision[24]; /**< Lepton GPP software revision. */ + char DSP_Revision[24]; /**< Lepton DSP software revision. */ + } SoftwareRevision; } App_Lepton_Device_t; /** @brief Structure representing the ROI results from the Lepton camera. diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 09b18cd..df89aa8 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -85,7 +85,7 @@ menu "PyroVision" menu "Task" config LEPTON_TASK_STACKSIZE int "Stack size" - default 4096 + default 8192 config LEPTON_TASK_PRIO int "Task prio" @@ -280,7 +280,7 @@ menu "PyroVision" menu "Task" config GUI_TASK_STACKSIZE int "Stack size" - default 32768 + default 16384 config GUI_TASK_PRIO int "Task prio" diff --git a/sdkconfig.debug b/sdkconfig.debug index bc7a47d..822a53b 100644 --- a/sdkconfig.debug +++ b/sdkconfig.debug @@ -647,7 +647,7 @@ CONFIG_NETWORK_TASK_CORE=1 # # Task # -CONFIG_LEPTON_TASK_STACKSIZE=4096 +CONFIG_LEPTON_TASK_STACKSIZE=8192 CONFIG_LEPTON_TASK_PRIO=16 CONFIG_LEPTON_TASK_CORE=1 # end of Task @@ -701,7 +701,7 @@ CONFIG_SD_CARD_PIN_CD=-1 # # CONFIG_LCD_SPI2_HOST is not set CONFIG_LCD_SPI3_HOST=y -CONFIG_LCD_CLOCK=80000000 +CONFIG_LCD_CLOCK=8000000 CONFIG_LCD_CS=18 CONFIG_LCD_DC=3 CONFIG_LCD_RST=8 @@ -729,7 +729,7 @@ CONFIG_GUI_LVGL_TICK_PERIOD_MS=2 # # Task # -CONFIG_GUI_TASK_STACKSIZE=32768 +CONFIG_GUI_TASK_STACKSIZE=16384 CONFIG_GUI_TASK_PRIO=2 CONFIG_GUI_TASK_CORE=0 # end of Task @@ -1441,7 +1441,7 @@ CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 -CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y # CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set # CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set @@ -3046,7 +3046,7 @@ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 -CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_MAIN_TASK_STACK_SIZE=8192 CONFIG_CONSOLE_UART_DEFAULT=y # CONFIG_CONSOLE_UART_CUSTOM is not set # CONFIG_CONSOLE_UART_NONE is not set diff --git a/ui/PyroVision.sll b/ui/PyroVision.sll index 60a203f..19c0abb 100644 --- a/ui/PyroVision.sll +++ b/ui/PyroVision.sll @@ -12,7 +12,7 @@ "board": "ESP WROVER KIT", "board_version": "2.0.0", "editor_version": "1.6.0", - "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQBLa273V3Dbx/flkVF+pOK7q8Phvw9J/Z76SupXMQxNIz7FDegOCTXJ+Hf+Rn0n/r8h/9DFXtf/5GPU/+vuX/ANDNbQfLDmtrcpaK5q/274d/6FGD/wACT/8AE1d1GbS9J+yfbvBUEX2u2S6g/wBMDb4nztbgHGcHg81xte1XGh2L/wDCP+Kdej36Fo/hyyaWIxM/2mVt4SMdAcMVJyccqCMMSF7aXZfcv8gucPp02l6t9r+w+CoJfsls91P/AKYF2RJjc3IGcZHA5ql/bvh3/oUYP/Ak/wDxNei2+h2Kf8JB4p0GPZoWseHL1oohEyfZpV2B4z1AywYjBxwwAwoJ8Vo9tLsvuX+QXOusz4b8Qyf2emkrptzKMQyK+9S3oTgEVwt1bva3c1vJ9+KRkb6g4rc0D/kY9M/6+4v/AEMVR8Rf8jPq3/X5N/6Gac3zQ5ra3B6q5reF9KsGsLrWdVBa0t3ESxqATI5GcDP1FaB1rw4DgeE4COxNwef/AB2qdn/yTc/9hf8A9o1kVTlyJKKW3ZP8x7HTQ6poVxPHBB4OjlmkYIkaTszMxOAAAvJJrQ+z2n/CQ/2D/wAIGv8AanmeV9m+0HOeuc7cbcc7s4xznHNRfDqGK31q71+6jR7XRLSS8KyqNkkuNsUe48KxY5U4JyvA9O98+P7d/wALO+yw+V/YO/z8v5f9pZ8nZs3btv8AB/dxznPNT7aXZfcv8guebzapoVvPJBP4OjimjYo8bzsrKwOCCCvBBpg1rw4Tg+E4AO5FweP/AB2tH4lwWs3iGDXtOH/Ev1q2S7jKxhQr/dkQlSQXBGW7gtz6ni6PbS7L7l/kFzT8UaVYLYWus6UCtpcOYmjYAGNwM4OPoa5u1t3uruG3j+/LIqL9ScV1F5/yTcf9hf8A9o1i+Hf+Rn0n/r8h/wDQxROKc1bS9hNanWXh8N+HpP7PfSV1K5iGJpGfYob0BwSarf274d/6FGD/AMCT/wDE1la//wAjHqf/AF9y/wDoZrPpzqtSaSVvRDbPRtB0M+JrF73SPAEFzbpIYmf+0ETDAAkYbB6MPzo17Qz4ZsUvdX8AQW1u8giV/wC0EfLEEgYXJ6Kfyrk/B3/I76B/2Erf/wBGLR4x/wCR31//ALCVx/6Map9tLsvuX+Qrlv8At3w7/wBCjB/4En/4mrNmfDfiGT+z00ldNuZRiGRX3qW9CcAiuRrQ0D/kY9M/6+4v/QxVQqtySaVvRDTMO6t3tbua3k+/FIyN9QcV0nhfSrBrC61nVQWtLdxEsagEyORnAz9RWT4i/wCRn1b/AK/Jv/QzW1Z/8k3P/YX/APaNKEUpu+triS1Lh1rw4DgeE4COxNwef/Hams7/AES/vreztvB8ElxcSLFEn2rG5mOAMlcDk965atrwf/yO2g/9hG3/APRi0e2l2X3L/IdzZiXT59eOhw+B45NSEzQGBLrJDqSGGQMYGDk5wACc4qreX+iWF9cWdz4PgjuLeRopU+1Z2spwRkLg8jtXf2t74Lg8ea1ZWx1e31/Ubm4s47+dEaO1ndnUtFsIYZY4BPOMcqCxryHUrGXS9Uu9PnZGmtZngdkJKllYqcZxxkUe2l2X3L/ILmyNa8OE4PhOADuRcHj/AMdrP8UaVYLYWus6UCtpcOYmjYAGNwM4OPoazK17z/km4/7C/wD7RqlLnTUktuyX5BuclRRRXOQFFFFABRRRQAUUUUAFFFFAFiwumsdQtrxFDNBKsoB7lSD/AErs7/w/Lr95LqmgtHdwXLGVo/NVZImPJDAkd64SitITSXLJXQ0zsv8AhB/Ef/QO/wDI8f8A8VXSeJIPF/iHStG0s6Y9vY6baRwCAXcbLJIq7TKeRyRgAHOOcHk15TRTvS/lf3r/ACHdHq3huDxf4e0rWdLGmPcWOpWkkBgN3GqxyMu0Sjk8gZBAxnjJ4Fc3/wAIP4j/AOgd/wCR4/8A4quNoovS7P7/APgBdHd2Hh+XQLyLVNeaO0gtmEqx+arSSsOQFAJ71xl/dNfahc3jqFaeVpSB2LEn+tV6KU5prlirITZ1fhy4tr/Q7nQJ7iO3macXNrJKcIz7dpUntkdKt/8ACE+Ie1gGHYiaPB/8eriaKpVItJTW3nb9GO/c9Tt9N8SWvgq88PQaIiNeXaz3F0J4t0kagbYiOuAw3A59Rjk5meHxbJ4Aj8KNpriGO789ZVuo1Bj5PlFQfmG8l8knnHHAryaijmpfyv7/APgBdHqdxpviS68FWfh6fREdrO7ae3ujPFujjYHdEB1wWO4nPoMcDGF/whPiHvYBR3JmjwP/AB6uJoo5qX8r+/8A4AXR1fiO4trDQ7bQILiO4mWc3N1JEcor7doUHvgda5ywumsdQtrxFDNBKsoB7lSD/Sq9FRKblK60E2d3f+H5dfvJdU0Fo7uC5YytH5qrJEx5IYEjvVb/AIQfxH/0Dv8AyPH/APFVxtFW505O7i7+v/AHdHrXhXSZ9A8qe+8Ef2lqEFyJ4Lr+1RD5e3aVGwEg4YE5PrijxVpM+v8Amz2Pgj+zdQnuTPPdf2qJvM3biw2EgDLEHI9MV5LRS5qX8r+9f5BdHZf8IP4j/wCgd/5Hj/8Aiqs2Hh+XQLyLVNeaO0gtmEqx+arSSsOQFAJ71wlFNTpxd1F39f8AgBdFi/umvtQubx1CtPK0pA7FiT/Wuj8OXFtf6Hc6BPcR28zTi5tZJThGfbtKk9sjpXKUVEZuMrvUSZ23/CE+Ie1gGHYiaPB/8eq7o/hjxFpOt2Gpf2V5v2S5jn8v7RGu/YwbGcnGcdcV55RV81L+V/f/AMAd0e7G4Eery61bfDeFdWaR50uJtX81FmbJ3mM4BwTnAx7EHBHC3nhTxRf31xeXNl5lxcSNLK/mxDczHJOAcDk9q4Oijmpfyv7/APgBdHbf8IT4h72AUdyZo8D/AMeqp4juLaw0O20CC4juJlnNzdSRHKK+3aFB74HWuUoodSKTUFv53/RBfsFFFFYkhRRRQAUUUUAek3XgrR4vF+oaUhf7Tb3E8/2Pedi2oLbFDZ3FwoRzycq3qprAt9L0i60hRHLaJfNpAlXzbsRj7R9sKkfMwAbyR909ucZ5rnTf3hvXvTdzm7dmZp/MO9iepLdSTk5+tRyTyzLEssrusS7IwzEhFyTgegyScepNAy9r0Nlbap5NiY2ijggV2jk3qZREnmkNk5Hmb+nHpxis2iigR2HhvRtKs9DufE2vMz2sR2xQqN24k4ACngsSG68ADNX4dV065uGih8CLxCk5eS+gRVjcAoWYxbRkEcE57Vm6lEZ/hLp8SlFZ9UiUF2CqCRcDkngD3NRal9nv7KXR4tQsEukisH3tcp5Unl25jdRJnblWb155rScpKbinZK22m8U366sxhCNRc0tdX+Da/Q2YNS0+e8uLQeAwk1t/rvNvIY1j7DLNCAM9uee1Nl1fSoGkSXwMUkjmWBozcxbt7AkADycnODyOPzFZV5NaarZXOk21/aCeH7JieWURx3PlQmNsM2BwTxnqKi/tSztfGemXJlWa3shbRSzoCQ5jRVZxxzgjj1wKXPP+Z/eyvYU+x0N/e6XpkayXfglERmKblvIXAYdVJWI4b2PNVB4i8Nk/8imv/gRH/wDGay7iGPStAu7SS9tLqa6uYnjW3lEgCoHy5I6Z3AAHB68VkJ1o55/zP72HsKfY68a74bP/ADKi/wDf+P8A+M1KuseG2P8AyKy/9/4//jNcmnUfWrMfWjnn/M/vYewp9jp11Pw2xH/FLr/3+j/+NVIt74bb/mWV/wC/0f8A8arnY+oqzH1/Cjnn/M/vY/YU+xvLceG2/wCZbX/v7H/8aqRX8Nt/zLi/9/I//jVYsfX8Ksx9KOef8z+9i9hT7Gqq+Gz/AMy8v/fyP/41Uq2/htv+ZfX/AL7j/wDjVZqd60YLuWO3MKeWF3bt3lruB46NjI6etHPP+Z/ew9hT7FpNK0B4JJh4dHlxkKx3x8E5x/yz9jVp/DejRQiWTw4qqcZ+eLK56ZHl5GferVxrdzPaCQXTsszKJ4WlPBHXaM/dYHkYxnj0qadokbUbr7TFKl0CIlVssdzhuR2wB370c8/5n97H7Cn2KcPhbRZ2dU8PplH2NmSEDd6AlOT9Ki/sDw4GKtogVh1B8vI/8h1oW6Ld6bBCs8UTxSuzCR9uQwX5h69OnXpS3kyXF/PNH9x3JB9RnrRzz/mf3sPYU+xRHh3w2f8AmDr/AOQ//jdSjwx4bP8AzCV/KP8A+N1ZToPpVlaOef8AM/vYewp9iiPCXhsnH9lL+Uf/AMRUo8G+Gyf+QYv/AHzH/wDEVpJ94fWrCdR9aOef8z+9h7Cn2MlfBHhtj/yDl/74j/8AiKkXwH4bb/mHr/3xH/8AEVtx9asp1FHPP+Z/ew9hT7GAvw98Nt/y4r/37j/+IqRfhx4bb/lyX/v3H/8AEV0cdWY+v4Uc8/5n97D2FPscuvwz8Nt/y6L/AN+o/wD4mpV+F3htv+XVf+/Mf/xNdjAB5Y+6CWwSwzmp1AUEherHr/Kjnn/M/vYewp9ji1+FHhth/wAe6/8AfmP/AOJqO6+GGkWEBu7GytJpIxny7i1jdX9sba79AAxHYE06Xm1l/wB0/wAqipVqQg5KTul6/gxqhT6I+QfGcVlD4svU063Fva/u2WEdEJjUsB7bice1YNbfi7/kaLz/AIB/6AtYlbYiKjVlFdG/zJpSc6cZPqkFFFFYmgVreFbaG98X6La3MYkgmv4I5EboymRQQfwNZNbXg448b6Af+olb/wDoxaAPsSMxxRrHGoRFGFVQAAPQCneaKo+b7mjzfc1RZ89fHS0tbXx9C9tCkRuLFJpdoxvfe67j74UflXmVen/HVt3jeyOf+Yan/oyWvMKklnVax/yR+z/7CUf8rmuCT7orvdY/5I/Z/wDYSj/lc1wSfdFXU/iy/wC3f/SImVD4PnL/ANKZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hVmPpVaPr+FWY+lAFhO9Wo+n41VTvVqPp+NAFiPp+NWU+6KrR9Pxqyn3RQBYT7oqynQfSqyfdFWU6D6UAWU6D6VZWqydB9KsrQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FIC3C7KMA8delTxswzz71Wj6GrEfegCzGT196klObWX/dP8qjj6fjUkn/AB6y/wC6f5VnX/hS9H+Q1ufH3i7/AJGi8/4B/wCgLWJW34u/5Gi8/wCAf+gLWJXViv48/V/mcuH/AIMPRfkFFFFYGwVs+EjjxnoR9NQt/wD0YtY1a/hU48YaIf8Ap/g/9GLQB9Xed9KPO+lUfOo86qLPEvjc27xnZn/qHp/6MkrzWvRPjM27xhaH/pwT/wBGSV53Uks6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETKh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8Ksx9KALCd6tR9PxqqnerUfT8aALEfT8asp90VWj6fjVlPuigCwn3RVlOg+lVk+6Ksp0H0oAsp0H0qytVk6D6VZWgCyn3h9asJ1H1qun3h9asJ1H1oAsx9asp1FVo+tWU6imMsR1Zj6/hVaOrMfX8KQFmPoasR96rx9DViPvQBZj6fjUkn/AB6y/wC6f5VHH0/GpJP+PWX/AHT/ACrOv/Cl6P8AIa3Pj7xd/wAjRef8A/8AQFrErb8Xf8jRef8AAP8A0BaxK6sV/Hn6v8zlw/8ABh6L8gooorA2CtXwwceLNGPpfQf+jFrKrY8JRef4z0OHdt8zULdc4zjMiigD6R84+9HnH3rZ/wCEVb/n+/8AIP8A9ej/AIRVv+f7/wAg/wD16ZR8+fF5t3iy1P8A04p/6MkrgK9J+NmnnTfGdnCZfN3aejZ27f8AlpIPX2rzakI6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETKh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8K1NJ0271e9js7KEyzv0A7D1J7CgBid6tR9PxrvbX4S3BhBudXjjkPVY4C4H4lh/Kra/CnaP+Q1/wCSv/2dAHn8fT8asp90V3a/C3aP+Qz/AOSv/wBnUi/DPaP+Qv8A+S3/ANnQBxCfdFWU6D6V2S/DjaP+Qr/5L/8A2VSj4e4H/IU/8l//ALKgDkU6D6VZWtPVPC15pURmDLPAv3nUYK/UVmLQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf8AhS9H+Q1ufH3i7/kaLz/gH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBWt4VNyPF+imzEZuhfweSJc7C/mLt3Y5xnGaya3fBX/I+eHf8AsJ23/o1aAPpfzviL/wA+3hz/AL6m/wAaPO+Iv/Pt4c/76m/xrsaKZR8u/GRtabxfaHXUskuvsCbRZltmzzJMZ3c5zn9K88r0/wCPF5b3fj6BbeZZDb2CQy7Tna4kkJX64YV5hSEdVrH/ACR+z/7CUf8AK5rgk+6K73WP+SP2f/YSj/lc1wSfdFXU/iy/7d/9IiZUPg+cv/SmWU6D6VYToPpVdOg+lWE6D6VBqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4V7H8IbGJdIvtQ2gzPP5O7uFVQ382/QV45H1/CvbfhH/wAipc/9fr/+gR0AXvFPi2907V7TQ9DskvdWuBvKyE7I09Tgj0PcYA96YJviKRn7L4dHsWl/xrOtefjle57WAx/3yleh0Acd53xF/wCfbw5/31N/jR53xF/59vDn/fU3+NdjRQBx3nfEX/n28Of99S/41y2qfEfxXo+sNpk9hpNxcINzpaiR8DGSPvcEAZ6cV1HjXxbNpzR6Hoi/aNdvPljRBnyQf4j2zjpnp1PHWbwx4OtvDekzPPtudTuI2N1ctyWJ5KgnnH8+p9AAbOhavB4j0C21KOIpFcocxvzgglWHuMg/WvPruEW9/cwL92OVkH0BIrqPhp/yT3SvpL/6Neub1T/kMX3/AF8Sf+hGgBqfeH1qwnUfWq6feH1qwnUfWgCzH1qynUVWj61ZTqKYyxHVmPr+FVo6sx9fwpAWY+hqxH3qvH0NWI+9AFmPp+NSSf8AHrL/ALp/lUcfT8akk/49Zf8AdP8AKs6/8KXo/wAhrc+PvF3/ACNF5/wD/wBAWsStvxd/yNF5/wAA/wDQFrErqxX8efq/zOXD/wAGHovyCiiisDYK3fBX/I+eHf8AsJ23/o1awq2/BjKnjnw+zMFVdStiSTgAeatAH2VXFeMvFVzb3Mfh3w+vn63dfKdvP2dSPvH0OOfYcntl/i7xsmmKmmaLsvdaujsijjIcR5/ib39B+J4qz4N8Ir4etpLu8k+06xd/Pc3DHJBPJUH0z1Pc/hhlHz58U/DieGPEOn2XnNPPJp6TXEpOd0hkkBI9uBXDV6t+0B/yPlj/ANgyP/0bLXlNIR1Wsf8AJH7P/sJR/wArmuCT7orvdY/5I/Z/9hKP+VzXBJ90VdT+LL/t3/0iJlQ+D5y/9KZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hXtvwj/5FS5/6/X/APQI68Sj6/hXtvwj/wCRUuf+v1//AECOgDA1jX4PDnxmlvLoH7M8KQysOSisi/N+BA/DNen3+rafpmky6reXcUVjFH5jTlsrtPTGOucjAHJJAGc15pqugWXiT4wX1hf+Z5P2MP8Au2wQQigH8M5rA8XSat4c8J6t4Kvle6t5lSTTbkcZVZVYr+QPHUHjkEUAdxZ+OPFmq2qX2l/D+aawny1vLPqkULyR5+VijDIyOe454JGDWdcfFt55tR02z0C+ttURoorSC8QrK7OpJLx4+XHGBk7tw6c1pal8W/DcHhmLU7C9hnurhf3Vm7hZEbv5i5yoB/PsSDmuA8DaVr/ivxfret2/iH+ztQRLeQzSaesxdZUJG0SY2gKoAIHIPBx1AO00Czbwl4m0W31OD7brfiH7S0940v8Ax7+WgfaBj5s5wTkdO4r0W4/49pf9w/yry+bS9d034peC/wC2/Ef9seZ9u8r/AEJLfysQfN90/NnI69Me9eoXH/HtL/uH+VAHL/DP/knul/SX/wBGvXN6p/yGL7/r4k/9CNdJ8M/+Se6X9Jf/AEa9c3qn/IYvv+viT/0I0ANT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf+FL0f5DW58feLv+RovP8AgH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBWr4XtItQ8W6NZT58m4voIn2nB2tIoOPwNZVbngshfHfh4kgAanbEk/8AXVaAPqrQPBmieG3aWwtf37DBmlbc+PQHt+Fb9Rfabf8A57xf99ij7Tb/APPeL/vsUyj5m+N2qR6l8QWSJGUWdslsSf4mDOxP/j2PwrzivT/jvFbJ4+gktwmZrCOSVkOdzb5FyffCr+VeYUhHVax/yR+z/wCwlH/K5rgk+6K73WP+SP2f/YSj/lc1wSfdFXU/iy/7d/8ASImVD4PnL/0pllOg+lWE6D6VXToPpVhOg+lQalkVZTrVYVZTrTAsJ1H1qzH1qsnUfWrMfWgZZj6irMfX8KrR9RVmPr+FAFiPr+Fe2/CP/kVLn/r9f/0COvEo+v4V7b8I/wDkVLn/AK/X/wDQI6AIbT/kuV9/14D/ANBSu01fRdP12yNpqVsk8RORngqfUEcg1wt1cw6L8aPtN+4ggvbMJFK5wucAcntyuPxFeiC6tyMieLH++KAOV034YeEdNleUaRDdSP3u1EoH4EY/HGa6G10ewstVv9Tt4Nl5qHl/aZN7HzPLXanBOBgHsB71Z+02/wDz3i/77FH2m3/57xf99igDz7xlqF3deNtNstEsbebWdOgkuIZ53Ybd67WRRkKSVA5b8MVt+DPFEnirwzPc3EKxXUDNFKE+6x25BHp16e1WNc8OaNrszXE04iuWt2tzNFIMlD2OfTtTLeLQfBPhaaGG4jjto1Z2Z5AXlcj9ScAce1AEPwz/AOSe6X9Jf/Rr1zeqf8hi+/6+JP8A0I10nw0GPh7pWfSX/wBGvXN6p/yGL7/r4k/9CNADU+8PrVhOo+tV0+8PrVhOo+tAFmPrVlOoqtH1qynUUxliOrMfX8KrR1Zj6/hSAsx9DViPvVePoasR96ALMfT8akk/49Zf90/yqOPp+NSSf8esv+6f5VnX/hS9H+Q1ufH3i7/kaLz/AIB/6AtYlbfi7/kaLz/gH/oC1iV1Yr+PP1f5nLh/4MPRfkFFFFYGwVq+GbOLUfFej2UxYRXF9BC5U4O1nAOPfmsqrel3U1jq9leW77J4J0ljbAO1lYEHB4PIoA+nP+FQeGv+el//AN/l/wDiaP8AhUHhr/npf/8Af5f/AImvMP8AhaXjD/oLj/wGi/8AiKP+FpeMP+guP/AaL/4imUYvxd8N2PhfxXa2Vg0zRPYpMTKwY7i8g7AcfKK4Guh8Y6/qXiLV4rzVLn7ROkAiVvLVMKGY4woA6k1z1IR1Wsf8kfs/+wlH/K5rgk+6K73WP+SP2f8A2Eo/5XNcEn3RV1P4sv8At3/0iJlQ+D5y/wDSmWU6D6VYToPpVdOg+lWE6D6VBqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4V6p8J9dgt/tOjTuEeZxNASfvNgBl+uAMfjXlcfX8KtREqQykgjBBHagD6M1zw9pniOzFtqdsJVU5RgcMh9iOlcqfhD4aJ4e/H0mH/AMTXC2njjxLbQiKPVZCo6eYiSH82BNXU8e+JiOdS7/8APCP/AOJoA63/AIVB4a/56X//AH+X/wCJo/4VB4a/56X/AP3+X/4muYTx14kI51Hv/wA8I/8A4mp08beISBnUP/IMf/xNAHQf8Kg8Nf8APXUP+/y//E1NbfCjwvbzLI8VzOFOdks3yn64Arn08Za+QM3/AP5Bj/8AiamXxdrpHN92/wCeSf8AxNAHpE01ppGnbiEht4U2qigAADooFeZTTNcXMszcNI5c/UnNR3Wo3moOHu7h5SOgJ4H0HQULQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/3T/Ko4+n41JJ/x6y/7p/lWdf+FL0f5DW58feLv+RovP8AgH/oC1iVt+Lv+RovP+Af+gLWJXViv48/V/mcuH/gw9F+QUUUVgbBUkBxPGf9ofzqOnIcSKfcUAbXmj1o80etUvOHqaPOHqaBkeoNunU/7P8AU1UqW4bdID7VFQI6rWP+SP2f/YSj/lc1wSfdFd7rH/JH7P8A7CUf8rmuCT7oq6n8WX/bv/pETOh8Hzl/6UyynQfSrCdB9Krp0H0qwnQfSoNSyKsp1qsKsp1pgWE6j61Zj61WTqPrVmPrQMsx9RVmPr+FVo+oqzH1/CgCxH1/CrMfSq0fX8Ksx9KALCd6tR9PxqqnerUfT8aALEfT8asp90VWj6fjVlPuigCwn3RVlOg+lVk+6Ksp0H0oAsp0H0qytVk6D6VZWgCyn3h9asJ1H1qun3h9asJ1H1oAsx9asp1FVo+tWU6imMsR1Zj6/hVaOrMfX8KQFmPoasR96rx9DViPvQBZj6fjUkn/AB6y/wC6f5VHH0/GpJP+PWX/AHT/ACrOv/Cl6P8AIa3Pj7xd/wAjRef8A/8AQFrErb8Xf8jRef8AAP8A0BaxK6sV/Hn6v8zlw/8ABh6L8gooorA2CjOOfSimucIx9jQA/wA76Ued9Ko+b7Ueb7Uxl3du5oqKBtyE+9S0hHVax/yR+z/7CUf8rmuCT7orvdY/5I/Z/wDYSj/lc1wSfdFXU/iy/wC3f/SImdD4PnL/ANKZZToPpVhOg+lV06D6VYToPpUGpZFWU61WFWU60wLCdR9asx9arJ1H1qzH1oGWY+oqzH1/Cq0fUVZj6/hQBYj6/hVmPpVaPr+FWY+lAFhO9Wo+n41VTvVqPp+NAFiPp+NWU+6KrR9Pxqyn3RQBYT7oqynQfSqyfdFWU6D6UAWU6D6VZWqydB9KsrQBZT7w+tWE6j61XT7w+tWE6j60AWY+tWU6iq0fWrKdRTGWI6sx9fwqtHVmPr+FICzH0NWI+9V4+hqxH3oAsx9PxqST/j1l/wB0/wAqjj6fjUkn/HrL/un+VZ1/4UvR/kNbnx94u/5Gi8/4B/6AtYlbfi7/AJGi8/4B/wCgLWJXViv48/V/mcuH/gw9F+QUUUVgbBTXUsjKOpBFOq9ounf2xr2naZ5vk/bLqK38zbu2b2C5xkZxnpmgDn/s1x/d/wDHhR9muP7v/jwrsl8JXi6aL6aWNIzavcbV+ZkIAZVccbSysGHXIPscWn8J2I06K8TWfNRri3t38qFZMGVHbIVZC/BQjBVSew4xQM4+2jeOLD9Sc1NWnr2jtoOpHT5phJcxopm2rhFY8gKf4hgjnA5JxkYJzKBHVax/yR+z/wCwlH/K5rgk+6K9A1SKSX4OwMilhFqEbvj+Ff365P4so/EV5+n3RVVP4sv+3f8A0iJnR+D5y/8ASmWU6D6VYToPpVdOg+lWE6D6VJqWRVlOtVhVlOtMCwnUfWrMfWqydR9asx9aBlmPqKsx9fwqtH1FWY+v4UAWI+v4VZj6VWj6/hVmPpQBYTvVqPp+NVU71aj6fjQBYj6fjVlPuiq0fT8asp90UAWE+6Ksp0H0qsn3RVlOg+lAFlOg+lWVqsnQfSrK0AWU+8PrVhOo+tV0+8PrVhOo+tAFmPrVlOoqtH1qynUUxliOrMfX8KrR1Zj6/hSAsx9DViPvVePoasR96ALMfT8akk/49Zf90/yqOPp+NPmYLaSliANp5P0rOv8Awpej/Ia3Pj/xd/yNF5/wD/0BaxK2/F3/ACNF5/wD/wBAWsSurFfx5+r/ADObD/wYei/IKKKKwNQq3peoS6Tq1lqUCo01pOk8ayAlSyMGAOCDjI9aqUUAbEXibU431ZjKsn9qoUuQ68HJzuAHQjkD0BI6Gqp1rVWS2RtTvStrzADO2IuMfLz8vHHFUaKAJJJ5ZljWWV3WJdkYZidi5JwPQZJOPc1HRRQB0XhnxVLoiz2d1Al3ps4IeFwGwD1G08EHAOOMHmrp1PwIWLf8IsQSc8STAfl51chRV8yfxJN/12sZumm7ptHYDVfAo6eF2/7+zf8Ax6nDWfBA6eGG/wC/s3/x6uNopXj/AC/i/wDMXsv7zO1/tzwV/wBCy3/fyX/49Th4g8GDp4bb/v5L/wDHq4iii8f5fxf+Yez/ALzO5HiTweOnhxv++5f/AI9Th4o8Ijp4db/vuT/49XCUUXj/AC/i/wDMPZv+ZnejxX4THTw83/fUn/x6njxf4VHTw+3/AH1J/wDHq8/oovH+X8X/AJh7N/zM9CHjPwwOmgN+cn/x2nDxv4aHTQW/N/8A47XndFF4/wAv4v8AzD2b/mZ6MPHXhwdNCb83/wDjtOHj7w+OmiN/4/8A/Ha83oovH+X8X/mHs3/Mz0ofELQR00Vv/H//AI7Tx8RdDHTRm/Jv/jteZUUXj/L+L/zD2b/mZ6ePiToo6aO35N/8dpw+JukDppDf98t/8dry6ii8f5fxf+Y/Zv8AmZ6mPihpQ6aS3/fLf/Had/wtTTB/zCm/75P/AMcryqii8f5fxf8AmHs3/Mz1gfFjTx00tv8Avg//ABynD4uWI6aY3/fB/wDjleS0UXj/AC/i/wDMPZv+Znrg+MFmOmnN/wB+/wD7ZTh8Y7YdNPb/AL9//bK8hoovH+X8X/mHs3/Mz2AfGeAdLBv+/X/2ynD41xDpYt/36/8AtleO0UXj/L+L/wAw9m/5meyj43KOlk3/AH5H/wAcpw+OWOlm3/fkf/F14xRReP8AL+L/AMw9m/5me0j47MOlo3/fkf8AxdRz/GmHUU+z3q3kNs3EhtoE3EenL141RT5o78q/F/m7B7Lu395reJtXh13xDd6jb232aCQqscWclVVQgye5IUE+5NZNFFS227s0CiiikAqKXdUXqxwKtfYc3ZhEo2gZEmOD6fqcVDbyCGUSEElQduPXHFP+0j7GIgCJAcbv9kc4/M1lPnv7v9f8MehhVhVC9bV79enT/t5vfdW8yuQQcHrU6wRiNXml2b+VAXJx6mmTuskzOoIDHJHv3/WpBJDJGizeYGQYBQA5HWnJysmZ0oUlUlF2dtr3Sevlbp5kDABiAcgHqO9JStjcduQM8ZpK0OR7hRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigArrdH8IWN+umC71mS2l1G0kuLeNLUSF3WV4/KBMijcdmRkjJOOuM8lXW3mo+FryDS7F5tZFvYWjRLcrbxK+8zPIcx7yCMPj74PFAzNfTdEF4YRrdxEiyqjNc2BRlXaxYlVduQQqgZ53dsGr58Gf2hHaTeH9QW+guWmQG6VbRkaJVd8hnK42sDkN65xiodZ1zTtb1u4eWCSCznliZ7ryhJdYSPYT95VJc/Owz178c3PEvimC7vNFvtJ1HVHvdPiCNJcxLEoKEbGRFdwCR94cAkZxyaAK2p+Dxo+m2N7e6tZ7buCVwttNHORIpcKo2OcqxQAuOFLYPIpq+GtPvdPupNJ1pr29tIFnlgNo0aMpZVOxy2WILjgquecVW1TWrW41E3Fpa5t3t3QWlyC0dq8gO/wAoBuFDMWXpgnkHGTr6j4psZfD8Ftpt3eWcyW9sklpFp0EcUskYXczzK29gWUv8ynnHTqACpq3hK306DU44dVNxqGkhft0BtiiLl1jOx9x34dlByq9cjIrl67TxT4xi8Q2M7Jd30c11KJZ7RreLy85Jx5wId1BPyhhxxzxXF0AFFFFAgrVbRl/sOx1RLsGKa5a2uN0ZAt3GCucZLAqSRgfwsO1ZVdlJqfhGDSdYtLJ9X2XsUbQ20trHshnQ5Vt/mkkcuv3ejmgDNv8AQNPXRrjUtI1d7+O1mjhuFktTARvDbWX5juX5COcHpxU0PhITMzC9YwStGtnKsORN5iuVLfN8gHlsG+9ggjnBNa+teL9Kur+GaxnvUs1vPPGnjTYLeKEEMAwMb/vHTI27h+I75WpeKftdrd2kdzfbWjQRzk7XmO1VkEoDEFXxu6tyo/vMaBnL0UUUCP/Z", + "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQBLa273V3Dbx/flkVF+pOK7q8Phvw9J/Z76SupXMQxNIz7FDegOCTXJ+Hf+Rn0n/r8h/9DFXtf/5GPU/+vuX/ANDNbQfLDmtrcpaK5q/274d/6FGD/wACT/8AE10Og6GfE1i97pHgCC5t0kMTP/aCJhgASMNg9GH515zXpOg2Olah8Hni1fWf7Ktxr5ZZ/srT7m+zgBdq8jgk59vel7aXZfcv8guUtftLfwvPDDrPgOO1aZS0ZN2HVgDg4ZQRkcZGcjI9RWR/bvh3/oUYP/Ak/wDxNdJ40jtdD+HGg6HYX02q2V3cvfxagzBYxgFTEkeSy435YHGGJ7khfNqPbS7L7l/kFzrrM+G/EMn9nppK6bcyjEMivvUt6E4BFcLdW72t3NbyffikZG+oOK3NA/5GPTP+vuL/ANDFUfEX/Iz6t/1+Tf8AoZpzfNDmtrcHqrmZRRRWJIUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV1PhfSrBrC61nVQWtLdxEsagEyORnAz9RXLV1tn/yTc/8AYX/9o1rSSu2+iKiXDrXhwHA8JwEdibg8/wDjtJ/bXh3/AKFKD/wJP/xNc7U1naT399b2dsnmXFxIsUSZA3MxwBk8Dk96ftpdl9y/yHc9Nm8DalBBJM/w3jKxqWITUI3YgDPCjJJ9gMmuO/trw7/0KUH/AIEn/wCJrqNO0bwx4J8RwXeoeM3k1HTW3zWVhZvlpAvMQlztIJ+U5xkZB2844LWNQ/tbW7/UvK8r7XcyT+Xu3bN7FsZwM4z1xR7aXZfcv8guaw1rw4Tg+E4AO5FweP8Ax2s/xRpVgtha6zpQK2lw5iaNgAY3Azg4+hrMrXvP+Sbj/sL/APtGqUudNSS27JfkG5yVFFFc5AUUUUAFFFFABRRRQAUUUUAWLC6ax1C2vEUM0EqygHuVIP8ASuzv/D8uv3kuqaC0d3BcsZWj81VkiY8kMCR3rhKK0hNJcsldDTOy/wCEH8R/9A7/AMjx/wDxVddoNrfaf4VfQNX8Gf2rbm9N6p/tRYNrbAg+7yeAe/fpxXj9FO9L+V/ev8h3R6n4p0/xH4h+w2tr4eh03StPjMdpZxXEbbN2C7M5ILMxGST/ADyTz3/CD+I/+gd/5Hj/APiq42ii9L+V/ev8guju7Dw/LoF5FqmvNHaQWzCVY/NVpJWHICgE964y/umvtQubx1CtPK0pA7FiT/Wq9FKc01yxVkJsKKKKzEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFdX4cuLa/0O50Ce4jt5mnFzaySnCM+3aVJ7ZHSuUoq4T5Xcadjtv8AhCfEPawDDsRNHg/+PVNZ+FPFFhfW95bWXl3FvIssT+bEdrKcg4JweR3rg6Kvmpfyv7/+AO6PcLtINUunvdT+GkM19NhriWHWTCkj4+ZggOBk89zzySea4X/hCfEX/QP/API0f/xVcTRRzUv5X9//AAAujtv+EJ8Q97AKO5M0eB/49VTxHcW1hodtoEFxHcTLObm6kiOUV9u0KD3wOtcpRQ6kUmoLfzv+iC/YKKKKxJCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKK3P+EWvv8Anrb/APfTf4Uf8Itff89bf/vpv8K7v7Nxf/Ptl+zl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2Ouooor7w7QooooAKKKKACiiigAooooAKKKKACiiigAooooAK6bR9Ji1Lw4xZUjCXwM1ztBMcIjYtz+HTucVzNX4tXuoNFn0qMqtvcSrLIQDubHQfTofqBWNeE5RSg7O6E79Ddm0yxGh6tqVlDmymgia3MgDPA4lVXTPYjP4qwq5r6z2U0y2sGgJbJBGwR0tvO5jUn5T82ckn1rlrbWLu10i90tCptbsozqwJ2lSCCvoeADVy78Ri+LPc6PprzMgQzYlDcKFB+/jOAO1cnsKqnd6q7+60bdVro/6ZNnc05tFtZItMvblFt9Oh06OW6eNQGlcu+FHq7YAz2AyelWNRt7G01nXNQj0+2KWkFuYLZkzErSKgyV74yTz1Jrmr/W73UbCysZnUW1mmyONAQD/ALR9T2/yakutfurv7d5kcI+2pEkm1TwIwNuOf9kZ601h6105Put+nMn+Kv8AkFmWtSaHUfDsGqfZLe2uUumt5Ps8exJF2hgSo4BHI4rAq19vl/sr+ztqeT5/n7sHdu27cdemKq110oOCa89PQpKwUUUVqMKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/9k=", "export_temp_image": false, "force_export_images": false, "flat_export": false, @@ -25,7 +25,7 @@ "custom_variable_prefix": "uic", "separate_screen_save": false, "hierarchy_state_save": false, - "backup_cnt": 73, + "backup_cnt": 91, "autosave_cnt": 0, "group_color_cnt": 0, "imagebytearrayprefix": "", @@ -36,5 +36,5 @@ "naming": "Screen_Name", "naming_force_lowercase": false, "naming_add_subcomponent": false, - "nidcnt": 1001699 + "nidcnt": 1001743 } \ No newline at end of file diff --git a/ui/PyroVision.spj b/ui/PyroVision.spj index 8b03b22..ee57874 100644 --- a/ui/PyroVision.spj +++ b/ui/PyroVision.spj @@ -1210,7 +1210,6 @@ "isPage": true, "editor_posx": 400, "editor_posy": -400, - "locked": true, "properties": [ { "nid": 10, @@ -1353,6 +1352,71 @@ "strtype": "SCREEN/Style_scrollbar", "strval": "lv.PART.SCROLLBAR, Rectangle, Pad", "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1001723, + "strtype": "_event/EventHandler", + "strval": "SCREEN_LOADED", + "childs": [ + { + "nid": 1001724, + "strtype": "_event/name", + "strval": "ScreenSplahLoaded", + "InheritedType": 10 + }, + { + "nid": 1001725, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1001726, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1001727, + "strtype": "_event/action", + "strval": "CALL FUNCTION", + "childs": [ + { + "nid": 1001728, + "strtype": "CALL FUNCTION/Name", + "strval": "CALL FUNCTION", + "InheritedType": 10 + }, + { + "nid": 1001729, + "strtype": "CALL FUNCTION/Call", + "strval": "<{Function_name}>( event_struct )", + "InheritedType": 10 + }, + { + "nid": 1001730, + "strtype": "CALL FUNCTION/CallC", + "strval": "<{Function_name}>( e );", + "InheritedType": 10 + }, + { + "nid": 1001731, + "strtype": "CALL FUNCTION/Function_name", + "strval": "ScreenSplahLoaded", + "InheritedType": 10 + }, + { + "nid": 1001732, + "strtype": "CALL FUNCTION/Dont_export_function", + "strval": "False", + "InheritedType": 2 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 } ], "saved_objtypeKey": "SCREEN" @@ -1431,6 +1495,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -1619,6 +1689,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -1807,6 +1883,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -1996,6 +2078,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -2159,6 +2247,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -2350,6 +2444,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -2502,8 +2602,8 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 119, - 89 + -1, + -1 ], "InheritedType": 7 }, @@ -2512,8 +2612,8 @@ "flags": 17, "strtype": "OBJECT/Size", "intarray": [ - 1, - 1 + 2, + 2 ], "InheritedType": 7 }, @@ -2533,6 +2633,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -2716,6 +2822,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -2899,6 +3011,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -3083,6 +3201,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -3237,6 +3361,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -3373,7 +3503,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 0, + 10, 0 ], "InheritedType": 7 @@ -3405,6 +3535,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -3587,6 +3723,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -3726,7 +3868,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 0, + -10, 0 ], "InheritedType": 7 @@ -3758,6 +3900,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -3847,17 +3995,6 @@ "strtype": "_style/Bg_Image_opa", "integer": 255, "InheritedType": 6 - }, - { - "nid": 11110, - "strtype": "_style/Padding", - "intarray": [ - 0, - 5, - 0, - 5 - ], - "InheritedType": 7 } ], "InheritedType": 1 @@ -3908,7 +4045,7 @@ "strtype": "OBJECT/Position", "intarray": [ 0, - 0 + -5 ], "InheritedType": 7 }, @@ -3939,6 +4076,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -4074,6 +4217,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "IMAGE/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -4169,6 +4318,7 @@ { "nid": 1040, "strtype": "IMAGE/Rotation", + "integer": 1800, "InheritedType": 6 }, { @@ -4208,16 +4358,6 @@ ], "InheritedType": 7 }, - { - "nid": 10530, - "strtype": "_style/Bg_gradiens_Color", - "intarray": [ - 255, - 255, - 255 - ], - "InheritedType": 7 - }, { "nid": 10550, "strtype": "_style/Gradient direction", @@ -4308,6 +4448,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -4485,6 +4631,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "IMAGE/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "flags": 1048576, @@ -4686,6 +4838,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -4856,6 +5014,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -4991,6 +5155,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -5133,6 +5303,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -5296,6 +5472,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "BUTTON/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -5540,6 +5722,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -5704,6 +5892,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "BUTTON/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -5883,6 +6077,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -6036,6 +6236,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "BUTTON/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -6290,6 +6496,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -6443,6 +6655,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "BUTTON/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -6693,6 +6911,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -6799,6 +7023,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "SCREEN/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -7043,8 +7273,14 @@ "InheritedType": 1 }, { - "nid": 110, - "strtype": "OBJECT/Clickable", + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", "strval": "False", "InheritedType": 2 }, @@ -7229,6 +7465,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "PANEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -7425,6 +7667,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -7567,6 +7815,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -7720,6 +7974,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "BUTTON/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 225, "strtype": "OBJECT/Scrolling", @@ -7901,6 +8161,426 @@ } ], "saved_objtypeKey": "BUTTON" + }, + { + "guid": "GUID65690463-138553S6282537", + "children": [ + { + "guid": "GUID35373283-138552S6282537", + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Menu Button Save", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "S", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "fa", + "InheritedType": 3 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + } + ], + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Button Menu Save", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 100, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 33, + "strtype": "OBJECT/Size", + "intarray": [ + 50, + 95 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, + { + "nid": 90, + "flags": 1048576, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 100, + "strtype": "BUTTON/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 230, + "strtype": "OBJECT/Scrollable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 240, + "strtype": "OBJECT/Scroll_elastic", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 250, + "strtype": "OBJECT/Scroll_momentum", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 270, + "strtype": "OBJECT/Scroll_chain", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10520, + "strtype": "_style/Bg_Color", + "intarray": [ + 50, + 50, + 50, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10710, + "strtype": "_style/Border_Color", + "intarray": [ + 185, + 152, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10720, + "strtype": "_style/Border width", + "integer": 2, + "InheritedType": 6 + } + ], + "InheritedType": 1 + } + ], + "nid": 1010, + "strtype": "BUTTON/Style_main", + "strval": "lv.PART.MAIN, Rectangle, Pad, Text, Transform", + "InheritedType": 11 + }, + { + "disabled": false, + "nid": 1001733, + "strtype": "_event/EventHandler", + "strval": "CLICKED", + "childs": [ + { + "nid": 1001734, + "strtype": "_event/name", + "strval": "ButtonMenuSaveClicked", + "InheritedType": 10 + }, + { + "nid": 1001735, + "strtype": "_event/condition_C", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1001736, + "strtype": "_event/condition_P", + "strval": "", + "InheritedType": 10 + }, + { + "nid": 1001737, + "strtype": "_event/action", + "strval": "CALL FUNCTION", + "childs": [ + { + "nid": 1001738, + "strtype": "CALL FUNCTION/Name", + "strval": "CALL FUNCTION", + "InheritedType": 10 + }, + { + "nid": 1001739, + "strtype": "CALL FUNCTION/Call", + "strval": "<{Function_name}>( event_struct )", + "InheritedType": 10 + }, + { + "nid": 1001740, + "strtype": "CALL FUNCTION/CallC", + "strval": "<{Function_name}>( e );", + "InheritedType": 10 + }, + { + "nid": 1001741, + "strtype": "CALL FUNCTION/Function_name", + "strval": "ButtonMenuSaveClicked", + "InheritedType": 10 + }, + { + "nid": 1001742, + "strtype": "CALL FUNCTION/Dont_export_function", + "strval": "False", + "InheritedType": 2 + } + ], + "InheritedType": 10 + } + ], + "InheritedType": 4 + } + ], + "saved_objtypeKey": "BUTTON" } ], "properties": [ @@ -7970,6 +8650,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "CONTAINER/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -8076,6 +8762,12 @@ "strtype": "OBJECT/Flags", "InheritedType": 1 }, + { + "nid": 100, + "strtype": "SCREEN/Hidden", + "strval": "False", + "InheritedType": 2 + }, { "nid": 110, "strtype": "OBJECT/Clickable", @@ -8203,6 +8895,7 @@ }, { "nid": 1000320, + "flags": 1048576, "strtype": "_event/action", "strval": "CHANGE SCREEN", "childs": [ @@ -8251,71 +8944,6 @@ } ], "InheritedType": 4 - }, - { - "disabled": false, - "nid": 1000377, - "strtype": "_event/EventHandler", - "strval": "SCREEN_LOADED", - "childs": [ - { - "nid": 1000378, - "strtype": "_event/name", - "strval": "ScreenMenuLoaded", - "InheritedType": 10 - }, - { - "nid": 1000379, - "strtype": "_event/condition_C", - "strval": "", - "InheritedType": 10 - }, - { - "nid": 1000380, - "strtype": "_event/condition_P", - "strval": "", - "InheritedType": 10 - }, - { - "nid": 1000388, - "strtype": "_event/action", - "strval": "CALL FUNCTION", - "childs": [ - { - "nid": 1000389, - "strtype": "CALL FUNCTION/Name", - "strval": "CALL FUNCTION", - "InheritedType": 10 - }, - { - "nid": 1000390, - "strtype": "CALL FUNCTION/Call", - "strval": "<{Function_name}>( event_struct )", - "InheritedType": 10 - }, - { - "nid": 1000391, - "strtype": "CALL FUNCTION/CallC", - "strval": "<{Function_name}>( e );", - "InheritedType": 10 - }, - { - "nid": 1000392, - "strtype": "CALL FUNCTION/Function_name", - "strval": "ScreenMenuLoaded", - "InheritedType": 10 - }, - { - "nid": 1000393, - "strtype": "CALL FUNCTION/Dont_export_function", - "strval": "False", - "InheritedType": 2 - } - ], - "InheritedType": 10 - } - ], - "InheritedType": 4 } ], "saved_objtypeKey": "SCREEN" @@ -8770,11 +9398,11 @@ }, { "nid": 60, - "flags": 35, + "flags": 51, "strtype": "OBJECT/Size", "intarray": [ 1, - 15 + 1 ], "InheritedType": 7 }, @@ -9095,9 +9723,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -9105,7 +9733,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -9300,9 +9928,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -9310,7 +9938,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -9490,7 +10118,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "Serial:\\n", + "strval": "Serial:", "InheritedType": 10 }, { @@ -9505,9 +10133,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -9515,7 +10143,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -9584,11 +10212,11 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 50, - 100 + 1 ], "InheritedType": 7 }, @@ -9893,7 +10521,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -10104,7 +10732,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -10315,7 +10943,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -10384,11 +11012,11 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 50, - 100 + 1 ], "InheritedType": 7 }, @@ -10548,11 +11176,11 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 100, - 50 + 1 ], "InheritedType": 7 }, @@ -10709,11 +11337,11 @@ }, { "nid": 60, - "flags": 17, + "flags": 49, "strtype": "OBJECT/Size", "intarray": [ 300, - 100 + 1 ], "InheritedType": 7 }, @@ -10933,11 +11561,11 @@ }, { "nid": 60, - "flags": 35, + "flags": 51, "strtype": "OBJECT/Size", "intarray": [ 1, - 15 + 1 ], "InheritedType": 7 }, @@ -11258,9 +11886,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -11268,7 +11896,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -11463,9 +12091,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -11668,9 +12296,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -11678,7 +12306,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -11747,11 +12375,11 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 50, - 100 + 1 ], "InheritedType": 7 }, @@ -11926,7 +12554,7 @@ { "nid": 70, "strtype": "OBJECT/Align", - "strval": "CENTER", + "strval": "TOP_RIGHT", "InheritedType": 3 }, { @@ -12056,7 +12684,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -12267,7 +12895,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -12478,7 +13106,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -12547,18 +13175,18 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 50, - 100 + 1 ], "InheritedType": 7 }, { "nid": 70, "strtype": "OBJECT/Align", - "strval": "RIGHT_MID", + "strval": "BOTTOM_RIGHT", "InheritedType": 3 }, { @@ -12711,11 +13339,11 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 100, - 50 + 1 ], "InheritedType": 7 }, @@ -13107,11 +13735,11 @@ }, { "nid": 60, - "flags": 17, + "flags": 49, "strtype": "OBJECT/Size", "intarray": [ 300, - 100 + 1 ], "InheritedType": 7 }, @@ -13331,11 +13959,11 @@ }, { "nid": 60, - "flags": 35, + "flags": 51, "strtype": "OBJECT/Size", "intarray": [ 1, - 15 + 1 ], "InheritedType": 7 }, @@ -13441,7 +14069,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "LEPTON\\n", + "strval": "LEPTON", "InheritedType": 10 }, { @@ -13656,9 +14284,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -13666,7 +14294,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -13846,7 +14474,212 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "Part Number:", + "strval": "Part Number:", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID44302939-208082S5004365", + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton GPP Revision Name", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 51, + "strtype": "OBJECT/Size", + "intarray": [ + 1, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "GPP Revision:", "InheritedType": 10 }, { @@ -13861,9 +14694,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -13871,7 +14704,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -13898,12 +14731,12 @@ "saved_objtypeKey": "LABEL" }, { - "guid": "GUID44302939-208082S5004365", + "guid": "GUID75705018-725311S45003531", "properties": [ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label Info Lepton Revision Name", + "strval": "Label Info Lepton DSP Revision Main", "InheritedType": 10 }, { @@ -14051,7 +14884,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "Software Revision:", + "strval": "DSP Revision:", "InheritedType": 10 }, { @@ -14066,9 +14899,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -14076,7 +14909,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -14271,9 +15104,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -14281,7 +15114,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -14476,9 +15309,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -14486,7 +15319,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -14681,9 +15514,9 @@ "nid": 10410, "strtype": "_style/Text_Color", "intarray": [ - 136, - 136, - 136, + 255, + 255, + 255, 255 ], "InheritedType": 7 @@ -14691,7 +15524,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -14760,11 +15593,11 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 50, - 100 + 1 ], "InheritedType": 7 }, @@ -15046,7 +15879,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -15257,7 +16090,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -15289,7 +16122,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label Info Lepton Revision", + "strval": "Label Info Lepton GPP Revision", "InheritedType": 10 }, { @@ -15468,7 +16301,218 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", + "InheritedType": 3 + }, + { + "nid": 11110, + "strtype": "_style/Padding", + "intarray": [ + 0, + 0, + 0, + 5 + ], + "InheritedType": 7 + } + ], + "InheritedType": 1 + } + ], + "nid": 1040, + "strtype": "LABEL/Style_main", + "strval": "lv.PART.MAIN, Text, Rectangle, Pad, Transform", + "InheritedType": 11 + } + ], + "saved_objtypeKey": "LABEL" + }, + { + "guid": "GUID50265110-725310S34524531", + "properties": [ + { + "nid": 10, + "strtype": "OBJECT/Name", + "strval": "Label Info Lepton DSP Revision", + "InheritedType": 10 + }, + { + "nid": 20, + "strtype": "OBJECT/Layout", + "InheritedType": 1 + }, + { + "Flow": 0, + "Wrap": false, + "Reversed": false, + "MainAlignment": 0, + "CrossAlignment": 0, + "TrackAlignment": 0, + "LayoutType": 0, + "nid": 30, + "strtype": "OBJECT/Layout_type", + "strval": "No_layout", + "InheritedType": 13 + }, + { + "nid": 40, + "strtype": "OBJECT/Transform", + "InheritedType": 1 + }, + { + "nid": 50, + "flags": 17, + "strtype": "OBJECT/Position", + "intarray": [ + 0, + 0 + ], + "InheritedType": 7 + }, + { + "nid": 60, + "flags": 50, + "strtype": "OBJECT/Size", + "intarray": [ + 100, + 1 + ], + "InheritedType": 7 + }, + { + "nid": 70, + "strtype": "OBJECT/Align", + "strval": "CENTER", + "InheritedType": 3 + }, + { + "nid": 75, + "strtype": "OBJECT/Extend_click_area", + "InheritedType": 6 + }, + { + "nid": 90, + "strtype": "OBJECT/Flags", + "InheritedType": 1 + }, + { + "nid": 100, + "strtype": "LABEL/Hidden", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 110, + "strtype": "OBJECT/Clickable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 130, + "strtype": "OBJECT/Press_lock", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 140, + "strtype": "OBJECT/Click_focusable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 210, + "strtype": "OBJECT/Gesture_bubble", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 220, + "strtype": "OBJECT/Snappable", + "strval": "False", + "InheritedType": 2 + }, + { + "nid": 225, + "flags": 1048576, + "strtype": "OBJECT/Scrolling", + "InheritedType": 1 + }, + { + "nid": 300, + "strtype": "OBJECT/Scrollbar_mode", + "strval": "AUTO", + "InheritedType": 3 + }, + { + "nid": 310, + "strtype": "OBJECT/Scroll_direction", + "strval": "ALL", + "InheritedType": 3 + }, + { + "nid": 314, + "strtype": "OBJECT/Scroll_snap_x", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 315, + "strtype": "OBJECT/Scroll_snap_y", + "strval": "NONE", + "InheritedType": 3 + }, + { + "nid": 320, + "flags": 1048576, + "strtype": "OBJECT/States", + "InheritedType": 1 + }, + { + "nid": 1010, + "strtype": "LABEL/Label", + "InheritedType": 1 + }, + { + "nid": 1020, + "strtype": "LABEL/Long_mode", + "strval": "WRAP", + "InheritedType": 3 + }, + { + "nid": 1030, + "strtype": "LABEL/Text", + "strval": "Nothing", + "InheritedType": 10 + }, + { + "part": "lv.PART.MAIN", + "childs": [ + { + "nid": 10000, + "strtype": "_style/StyleState", + "strval": "DEFAULT", + "childs": [ + { + "nid": 10410, + "strtype": "_style/Text_Color", + "intarray": [ + 255, + 255, + 255, + 255 + ], + "InheritedType": 7 + }, + { + "nid": 10430, + "strtype": "_style/Text_Align", + "strval": "RIGHT", + "InheritedType": 3 + }, + { + "nid": 10450, + "strtype": "_style/Text_Font", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -15679,7 +16723,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -15890,7 +16934,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -16070,7 +17114,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "0\\n", + "strval": "0", "InheritedType": 10 }, { @@ -16101,7 +17145,7 @@ { "nid": 10450, "strtype": "_style/Text_Font", - "strval": "montserrat_10", + "strval": "montserrat_12", "InheritedType": 3 }, { @@ -16170,11 +17214,11 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 50, - 100 + 1 ], "InheritedType": 7 }, @@ -16311,11 +17355,11 @@ }, { "nid": 60, - "flags": 34, + "flags": 50, "strtype": "OBJECT/Size", "intarray": [ 100, - 100 + 1 ], "InheritedType": 7 }, @@ -16452,11 +17496,11 @@ }, { "nid": 60, - "flags": 17, + "flags": 49, "strtype": "OBJECT/Size", "intarray": [ 300, - 140 + 1 ], "InheritedType": 7 }, @@ -16761,24 +17805,18 @@ "InheritedType": 7 }, { - "nid": 10710, - "strtype": "_style/Border_Color", - "intarray": [ - 30, - 30, - 30, - 255 - ], - "InheritedType": 7 + "nid": 10720, + "strtype": "_style/Border width", + "InheritedType": 6 }, { "nid": 11110, "strtype": "_style/Padding", "intarray": [ + 5, 0, 0, - 10, - 10 + 0 ], "InheritedType": 7 } @@ -17699,7 +18737,7 @@ }, "animations": [], "selected_theme": "Default", - "selected_screen": "GUID63572141-853113S4094354", + "selected_screen": "GUID40629891-934771S164356", "info": { "name": "SquareLine_Project.spj", "depth": 1, @@ -17727,7 +18765,7 @@ "custom_variable_prefix": "uic", "separate_screen_save": false, "hierarchy_state_save": false, - "backup_cnt": 73, + "backup_cnt": 91, "autosave_cnt": 0, "group_color_cnt": 0, "imagebytearrayprefix": null, @@ -17738,7 +18776,7 @@ "naming": "Screen_Name", "naming_force_lowercase": false, "naming_add_subcomponent": false, - "nidcnt": 1001699, + "nidcnt": 1001743, "BitDepth": 16, "Name": "SquareLine_Project" } diff --git a/ui/PyroVision_events.py b/ui/PyroVision_events.py index f687e30..95586c5 100644 --- a/ui/PyroVision_events.py +++ b/ui/PyroVision_events.py @@ -46,3 +46,15 @@ def ScreenMenuLoaded(event_struct): def Menu(event_struct): return + +def ContainerMenuLoaded(event_struct): + return + + +def ScreenSplahLoaded(event_struct): + return + + +def ButtonMenuSaveClicked(event_struct): + return + diff --git a/ui/project.info b/ui/project.info index 97571ee..d9c766e 100644 --- a/ui/project.info +++ b/ui/project.info @@ -1,7 +1,7 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-01-29T19:31:57.7621353+01:00", + "datetime": "2026-02-06T07:11:20.7294523+01:00", "editor_version": "1.6.0", - "project_version": 95, + "project_version": 105, "user": "Kampert Daniel" } \ No newline at end of file From 995782d02462e75bd71336876b60488c96d753f5 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Sat, 7 Feb 2026 12:56:46 +0100 Subject: [PATCH 10/26] Add message box when saving the settings --- .../Application/Tasks/Devices/devicesTask.cpp | 32 ++++--------- .../Application/Tasks/GUI/Export/project.info | 2 +- .../Tasks/GUI/Export/screens/ui_Splash.c | 2 +- .../Tasks/GUI/Export/ui_events.cpp | 22 +++++++-- main/Application/Tasks/GUI/Export/ui_events.h | 2 +- .../Application/Tasks/GUI/Private/guiHelper.h | 8 ++-- .../GUI/UI/Private/ui_Settings_Events.cpp | 20 +++++++- .../Tasks/GUI/UI/Private/ui_Settings_Events.h | 9 ++++ main/Application/Tasks/GUI/UI/ui_Settings.cpp | 3 ++ main/Application/Tasks/GUI/guiTask.cpp | 46 ++++++++----------- main/Application/Tasks/Lepton/leptonTask.cpp | 33 +++++-------- .../Application/Tasks/Network/networkTask.cpp | 29 ++++-------- main/CMakeLists.txt | 1 + ui/PyroVision.sll | 4 +- ui/PyroVision.spj | 6 +-- ui/PyroVision_events.py | 2 +- ui/project.info | 4 +- 17 files changed, 115 insertions(+), 110 deletions(-) diff --git a/main/Application/Tasks/Devices/devicesTask.cpp b/main/Application/Tasks/Devices/devicesTask.cpp index 7d327a8..5c0a71e 100644 --- a/main/Application/Tasks/Devices/devicesTask.cpp +++ b/main/Application/Tasks/Devices/devicesTask.cpp @@ -44,8 +44,7 @@ ESP_EVENT_DEFINE_BASE(DEVICE_EVENTS); typedef struct { bool isInitialized; - bool Running; - bool RunTask; + bool isRunning; TaskHandle_t TaskHandle; EventGroupHandle_t EventGroup; uint32_t LastBatteryUpdate; @@ -79,8 +78,7 @@ static void Task_Devices(void *p_Parameters) ESP_LOGD(TAG, "Devices task started on core %d", xPortGetCoreID()); - _DevicesTask_State.RunTask = true; - while (_DevicesTask_State.RunTask) { + while (_DevicesTask_State.isRunning) { EventBits_t EventBits; esp_task_wdt_reset(); @@ -89,6 +87,8 @@ static void Task_Devices(void *p_Parameters) if (EventBits & DEVICES_TASK_STOP_REQUEST) { ESP_LOGD(TAG, "Stop request received"); + _DevicesTask_State.isRunning = false; + xEventGroupClearBits(_DevicesTask_State.EventGroup, DEVICES_TASK_STOP_REQUEST); break; @@ -116,7 +116,6 @@ static void Task_Devices(void *p_Parameters) ESP_LOGD(TAG, "Devices task shutting down"); DevicesManager_Deinit(); - _DevicesTask_State.Running = false; _DevicesTask_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); @@ -184,11 +183,13 @@ esp_err_t DevicesTask_Start(App_Context_t *p_AppContext) return ESP_ERR_INVALID_ARG; } else if (_DevicesTask_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_DevicesTask_State.Running) { + } else if (_DevicesTask_State.isRunning) { ESP_LOGW(TAG, "Task already running"); return ESP_OK; } + _DevicesTask_State.isRunning = true; + ESP_LOGD(TAG, "Starting Devices Task"); ret = xTaskCreatePinnedToCore( @@ -206,36 +207,23 @@ esp_err_t DevicesTask_Start(App_Context_t *p_AppContext) return ESP_ERR_NO_MEM; } - _DevicesTask_State.Running = true; - return ESP_OK; } esp_err_t DevicesTask_Task_Stop(void) { - if (_DevicesTask_State.Running == false) { + if (_DevicesTask_State.isRunning == false) { return ESP_OK; } ESP_LOGD(TAG, "Stopping Devices Task"); - xEventGroupSetBits(_DevicesTask_State.EventGroup, DEVICES_TASK_STOP_REQUEST); - /* Wait for task to exit (with timeout) */ - for (uint8_t i = 0; i < 100 && _DevicesTask_State.Running; i++) { - vTaskDelay(10 / portTICK_PERIOD_MS); - } - - if (_DevicesTask_State.Running) { - ESP_LOGE(TAG, "Task did not stop in time"); - return ESP_ERR_TIMEOUT; - } - - _DevicesTask_State.TaskHandle = NULL; + xEventGroupSetBits(_DevicesTask_State.EventGroup, DEVICES_TASK_STOP_REQUEST); return ESP_OK; } bool DevicesTask_Task_isRunning(void) { - return _DevicesTask_State.Running; + return _DevicesTask_State.isRunning; } \ No newline at end of file diff --git a/main/Application/Tasks/GUI/Export/project.info b/main/Application/Tasks/GUI/Export/project.info index 91a5839..8f390c5 100644 --- a/main/Application/Tasks/GUI/Export/project.info +++ b/main/Application/Tasks/GUI/Export/project.info @@ -4,6 +4,6 @@ "editor_version": "1.6.0", "project_version": 105, "user": "Kampert Daniel", - "export_datetime": "2026-02-06T10:10:56.7827177+01:00", + "export_datetime": "2026-02-07T12:26:53.4688234+01:00", "export_user": "Kampert Daniel" } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c index d230c77..e0ab155 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c @@ -18,7 +18,7 @@ void ui_event_Splash(lv_event_t * e) lv_event_code_t event_code = lv_event_get_code(e); if(event_code == LV_EVENT_SCREEN_LOADED) { - ScreenSplahLoaded(e); + ScreenSplashLoaded(e); } } diff --git a/main/Application/Tasks/GUI/Export/ui_events.cpp b/main/Application/Tasks/GUI/Export/ui_events.cpp index d387505..3e122b7 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.cpp +++ b/main/Application/Tasks/GUI/Export/ui_events.cpp @@ -11,7 +11,14 @@ #include "../UI/ui_Settings.h" #include "../../../application.h" -static const char *TAG = "ui_Settings"; +/** @brief Callback for the message box timer to close the box after a delay. + * @param p_Timer Timer handle (user data is the message box to close) + */ +static void MessageBox_on_Close(lv_timer_t * p_Timer) +{ + lv_obj_t * Box = (lv_obj_t *)lv_timer_get_user_data(p_Timer); + lv_msgbox_close(Box); +} void ScreenMainLoaded(lv_event_t *e) { @@ -47,12 +54,19 @@ void ButtonMainWiFiClicked(lv_event_t *e) esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_OPEN_WIFI_REQUEST, NULL, 0, 0); } -void ScreenSplahLoaded(lv_event_t * e) +void ScreenSplashLoaded(lv_event_t * e) { ui_settings_build(ui_Container_Menu); } void ButtonMenuSaveClicked(lv_event_t * e) { - SettingsManager_Save(); -} \ No newline at end of file + lv_obj_t * Box = lv_msgbox_create(NULL); + + SettingsManager_Save(); + + lv_msgbox_add_title(Box, "Settings Saved"); + + lv_timer_t * Timer = lv_timer_create(MessageBox_on_Close, 1000, Box); + lv_timer_set_repeat_count(Timer, 1); +} diff --git a/main/Application/Tasks/GUI/Export/ui_events.h b/main/Application/Tasks/GUI/Export/ui_events.h index 1e86838..9458d2b 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.h +++ b/main/Application/Tasks/GUI/Export/ui_events.h @@ -10,7 +10,7 @@ extern "C" { #endif -void ScreenSplahLoaded(lv_event_t * e); +void ScreenSplashLoaded(lv_event_t * e); void ScreenMainLoaded(lv_event_t * e); void ButtonMainWiFiClicked(lv_event_t * e); void ButtonMenuSaveClicked(lv_event_t * e); diff --git a/main/Application/Tasks/GUI/Private/guiHelper.h b/main/Application/Tasks/GUI/Private/guiHelper.h index f1d45ce..a0357e1 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.h +++ b/main/Application/Tasks/GUI/Private/guiHelper.h @@ -39,7 +39,7 @@ #include "Application/application.h" #include "Application/Manager/Network/networkTypes.h" -#define STOP_REQUEST BIT0 +#define GUI_TASK_STOP_REQUEST BIT0 #define BATTERY_VOLTAGE_READY BIT1 #define BATTERY_CHARGING_STATUS_READY BIT2 #define WIFI_CONNECTION_STATE_CHANGED BIT3 @@ -57,13 +57,11 @@ typedef struct { bool isInitialized; - bool Running; - bool ChargeStatus; + bool isRunning; bool WiFiConnected; bool ProvisioningActive; - bool RunTask; bool CardPresent; - TaskHandle_t GUI_Handle; + TaskHandle_t TaskHandle; void *DisplayBuffer1; void *DisplayBuffer2; i2c_master_bus_handle_t Touch_Bus_Handle; diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp index 025257c..e6d42a4 100644 --- a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp +++ b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp @@ -23,7 +23,7 @@ #include -#include "../../../../Manager/Settings/settingsManager.h" +#include "managers.h" #include "ui_Settings_Events.h" @@ -106,9 +106,25 @@ void on_WiFi_Autoconnect_Callback(lv_event_t * e) { SettingsManager_UpdateWiFi(&WiFiSettings); } +void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "Network event received: ID=%d", ID); + + switch (ID) { + case NETWORK_EVENT_WIFI_GOT_IP: { + + break; + } + case NETWORK_EVENT_WIFI_DISCONNECTED: { + + break; + } + } +} + void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) { - ESP_LOGD(TAG, "Devices event received: ID=%d", ID); + ESP_LOGD(TAG, "Settings event received: ID=%d", ID); switch (ID) { case SETTINGS_EVENT_LEPTON_CHANGED: { diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h index 7e8484d..39065f5 100644 --- a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h +++ b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h @@ -65,6 +65,15 @@ void on_Lepton_Dropdown_Callback(lv_event_t * e); */ void on_WiFi_Autoconnect_Callback(lv_event_t * e); +/** @brief Network event handler which is used to handle network-related events such as WiFi connection changes. + * This can be used to update the UI or internal state based on network events. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data); + /** @brief Settings event handler which is used to update the UI elements when a * settings change event is received from the Settings Manager. * This ensures that the UI always reflects the current settings values. diff --git a/main/Application/Tasks/GUI/UI/ui_Settings.cpp b/main/Application/Tasks/GUI/UI/ui_Settings.cpp index 25c0b4f..690f6ff 100644 --- a/main/Application/Tasks/GUI/UI/ui_Settings.cpp +++ b/main/Application/Tasks/GUI/UI/ui_Settings.cpp @@ -31,6 +31,7 @@ #include "ui_Settings.h" #include "Private/ui_Settings_Events.h" #include "../../../Manager/Settings/settingsManager.h" +#include "../../../Manager/Network/Server/server.h" Slider_Widgets_t brightness_widgets; Slider_Widgets_t emissivity_widgets; @@ -435,6 +436,7 @@ void ui_settings_build(lv_obj_t *p_Parent) lv_menu_set_sidebar_page(menu, root_page); esp_event_handler_register(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler, NULL); + esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL); } void ui_settings_deinit(lv_obj_t *p_Parent) @@ -444,5 +446,6 @@ void ui_settings_deinit(lv_obj_t *p_Parent) lv_obj_delete(settings_Menu); esp_event_handler_unregister(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler); + esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); } } \ No newline at end of file diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp index 0dce948..bfe1167 100644 --- a/main/Application/Tasks/GUI/guiTask.cpp +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -45,14 +45,6 @@ ESP_EVENT_DEFINE_BASE(GUI_EVENTS); -/* Touch calibration ranges (based on measurements) - * Adjusted: RAW_X increased to shift touch point up - */ -const int16_t TOUCH_RAW_X_MIN = 47; -const int16_t TOUCH_RAW_X_MAX = 281; -const int16_t TOUCH_RAW_Y_MIN = 30; -const int16_t TOUCH_RAW_Y_MAX = 234; - static GUI_Task_State_t _GUITask_State; static const char *TAG = "gui_task"; @@ -76,8 +68,6 @@ static void on_Devices_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, break; } case DEVICE_EVENT_RESPONSE_CHARGING: { - memcpy(&_GUITask_State.ChargeStatus, p_Data, sizeof(bool)); - xEventGroupSetBits(_GUITask_State.EventGroup, BATTERY_CHARGING_STATUS_READY); break; @@ -571,8 +561,7 @@ void Task_GUI(void *p_Parameters) esp_event_post(GUI_EVENTS, GUI_EVENT_APP_STARTED, NULL, 0, portMAX_DELAY); - _GUITask_State.RunTask = true; - while (_GUITask_State.RunTask) { + while (_GUITask_State.isRunning) { EventBits_t EventBits; App_Lepton_FrameReady_t LeptonFrame; @@ -780,8 +769,12 @@ void Task_GUI(void *p_Parameters) /* Process the recieved system events */ EventBits = xEventGroupGetBits(_GUITask_State.EventGroup); - if (EventBits & STOP_REQUEST) { - xEventGroupClearBits(_GUITask_State.EventGroup, STOP_REQUEST); + if (EventBits & GUI_TASK_STOP_REQUEST) { + ESP_LOGD(TAG, "Stop request received"); + + _GUITask_State.isRunning = false; + + xEventGroupClearBits(_GUITask_State.EventGroup, GUI_TASK_STOP_REQUEST); break; } else if (EventBits & BATTERY_VOLTAGE_READY) { @@ -902,12 +895,13 @@ void Task_GUI(void *p_Parameters) _lock_release(&_GUITask_State.LVGL_API_Lock); uint32_t delay_ms = (time_till_next > 0) ? time_till_next : 10; - /* Reset watchdog at end of loop to prevent timeout during long operations */ esp_task_wdt_reset(); vTaskDelay(delay_ms / portTICK_PERIOD_MS); } + _GUITask_State.TaskHandle = NULL; + esp_task_wdt_delete(NULL); vTaskDelete(NULL); } @@ -929,12 +923,14 @@ esp_err_t GUI_Task_Init(void) if (_GUITask_State.ThermalCanvasBuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate thermal canvas buffer!"); + return ESP_ERR_NO_MEM; } if (_GUITask_State.GradientCanvasBuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate gradient canvas buffer!"); heap_caps_free(_GUITask_State.ThermalCanvasBuffer); + return ESP_ERR_NO_MEM; } @@ -942,6 +938,7 @@ esp_err_t GUI_Task_Init(void) ESP_LOGE(TAG, "Failed to allocate network RGB buffer!"); heap_caps_free(_GUITask_State.ThermalCanvasBuffer); heap_caps_free(_GUITask_State.GradientCanvasBuffer); + return ESP_ERR_NO_MEM; } @@ -1013,6 +1010,7 @@ esp_err_t GUI_Task_Init(void) heap_caps_free(_GUITask_State.ThermalCanvasBuffer); heap_caps_free(_GUITask_State.GradientCanvasBuffer); heap_caps_free(_GUITask_State.NetworkRGBBuffer); + return ESP_ERR_NO_MEM; } @@ -1061,11 +1059,13 @@ esp_err_t GUI_Task_Start(App_Context_t *p_AppContext) return ESP_ERR_INVALID_ARG; } else if (_GUITask_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_GUITask_State.Running) { + } else if (_GUITask_State.isRunning) { ESP_LOGW(TAG, "Task already running"); return ESP_OK; } + _GUITask_State.isRunning = true; + ESP_LOGD(TAG, "Starting GUI Task"); ret = xTaskCreatePinnedToCore( @@ -1074,7 +1074,7 @@ esp_err_t GUI_Task_Start(App_Context_t *p_AppContext) CONFIG_GUI_TASK_STACKSIZE, p_AppContext, CONFIG_GUI_TASK_PRIO, - &_GUITask_State.GUI_Handle, + &_GUITask_State.TaskHandle, CONFIG_GUI_TASK_CORE ); @@ -1083,27 +1083,21 @@ esp_err_t GUI_Task_Start(App_Context_t *p_AppContext) return ESP_ERR_NO_MEM; } - _GUITask_State.Running = true; - return ESP_OK; } esp_err_t GUI_Task_Stop(void) { - if (_GUITask_State.Running == false) { + if (_GUITask_State.isRunning == false) { return ESP_OK; } - esp_task_wdt_delete(_GUITask_State.GUI_Handle); - vTaskDelete(_GUITask_State.GUI_Handle); - - _GUITask_State.GUI_Handle = NULL; - _GUITask_State.Running = false; + xEventGroupSetBits(_GUITask_State.EventGroup, GUI_TASK_STOP_REQUEST); return ESP_OK; } bool GUI_Task_isRunning(void) { - return _GUITask_State.Running; + return _GUITask_State.isRunning; } \ No newline at end of file diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp index 6afaf2e..b94614d 100644 --- a/main/Application/Tasks/Lepton/leptonTask.cpp +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -49,8 +49,7 @@ ESP_EVENT_DEFINE_BASE(LEPTON_EVENTS); typedef struct { bool isInitialized; - bool Running; - bool RunTask; + bool isRunning; bool ApplicationStarted; TaskHandle_t TaskHandle; EventGroupHandle_t EventGroup; @@ -247,7 +246,7 @@ static void Task_Lepton(void *p_Parameters) esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); /* Critical error - cannot continue without capture task */ - _LeptonTask_State.Running = false; + _LeptonTask_State.isRunning = false; _LeptonTask_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); @@ -256,8 +255,7 @@ static void Task_Lepton(void *p_Parameters) return; } - _LeptonTask_State.RunTask = true; - while (_LeptonTask_State.RunTask) { + while (_LeptonTask_State.isRunning) { EventBits_t EventBits; esp_task_wdt_reset(); @@ -405,6 +403,8 @@ static void Task_Lepton(void *p_Parameters) } else if (EventBits & LEPTON_TASK_STOP_REQUEST) { ESP_LOGI(TAG, "Stop request received"); + _LeptonTask_State.isRunning = false; + xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_STOP_REQUEST); break; @@ -505,7 +505,6 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGD(TAG, "Lepton task shutting down"); Lepton_Deinit(&_LeptonTask_State.Lepton); - _LeptonTask_State.Running = false; _LeptonTask_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); @@ -601,7 +600,7 @@ void Lepton_Task_Deinit(void) return; } - if (_LeptonTask_State.Running) { + if (_LeptonTask_State.isRunning) { Lepton_Task_Stop(); } @@ -648,12 +647,15 @@ esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext) return ESP_ERR_INVALID_ARG; } else if (_LeptonTask_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_LeptonTask_State.Running) { + } else if (_LeptonTask_State.isRunning) { ESP_LOGW(TAG, "Task already Running"); return ESP_OK; } + _LeptonTask_State.isRunning = true; + ESP_LOGD(TAG, "Starting Lepton Task"); + Ret = xTaskCreatePinnedToCore( Task_Lepton, "Task_Lepton", @@ -669,34 +671,23 @@ esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext) return ESP_ERR_NO_MEM; } - _LeptonTask_State.Running = true; - return ESP_OK; } esp_err_t Lepton_Task_Stop(void) { - if (_LeptonTask_State.Running == false) { + if (_LeptonTask_State.isRunning == false) { return ESP_OK; } ESP_LOGI(TAG, "Stopping Lepton Task"); - /* Signal task to stop */ xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_STOP_REQUEST); - /* Wait for task to set Running = false before deleting itself */ - for (int i = 0; i < 20 && _LeptonTask_State.Running; i++) { - vTaskDelay(50 / portTICK_PERIOD_MS); - } - - _LeptonTask_State.TaskHandle = NULL; - _LeptonTask_State.Running = false; - return ESP_OK; } bool Lepton_Task_isRunning(void) { - return _LeptonTask_State.Running; + return _LeptonTask_State.isRunning; } \ No newline at end of file diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index 09bf081..cc8fd7c 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -32,8 +32,8 @@ #include +#include "managers.h" #include "networkTask.h" -#include "Application/Manager/managers.h" #include "Application/Tasks/GUI/guiTask.h" #define NETWORK_TASK_STOP_REQUEST BIT0 @@ -51,8 +51,7 @@ typedef struct { bool isInitialized; bool isConnected; - bool Running; - bool RunTask; + bool isRunning; bool ApplicationStarted; TaskHandle_t TaskHandle; EventGroupHandle_t EventGroup; @@ -263,8 +262,7 @@ static void Task_Network(void *p_Parameters) _NetworkTask_State.State = NETWORK_STATE_IDLE; } - _NetworkTask_State.RunTask = true; - while (_NetworkTask_State.RunTask) { + while (_NetworkTask_State.isRunning) { EventBits_t EventBits; esp_task_wdt_reset(); @@ -273,7 +271,7 @@ static void Task_Network(void *p_Parameters) if (EventBits & NETWORK_TASK_STOP_REQUEST) { ESP_LOGD(TAG, "Stop request received"); - _NetworkTask_State.RunTask = false; + _NetworkTask_State.isRunning = false; xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_STOP_REQUEST); @@ -398,7 +396,6 @@ static void Task_Network(void *p_Parameters) Provisioning_Stop(); NetworkManager_Stop(); - _NetworkTask_State.Running = false; _NetworkTask_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); @@ -531,12 +528,15 @@ esp_err_t Network_Task_Start(void) if (_NetworkTask_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_NetworkTask_State.Running) { + } else if (_NetworkTask_State.isRunning) { ESP_LOGW(TAG, "Task already Running"); return ESP_OK; } + _NetworkTask_State.isRunning = true; + ESP_LOGD(TAG, "Starting Network Task"); + Ret = xTaskCreatePinnedToCore( Task_Network, "Task_Network", @@ -552,7 +552,6 @@ esp_err_t Network_Task_Start(void) return ESP_ERR_NO_MEM; } - _NetworkTask_State.Running = true; _NetworkTask_State.StartTime = xTaskGetTickCount() * portTICK_PERIOD_MS / 1000; return ESP_OK; @@ -560,7 +559,7 @@ esp_err_t Network_Task_Start(void) esp_err_t Network_Task_Stop(void) { - if (_NetworkTask_State.Running == false) { + if (_NetworkTask_State.isRunning == false) { return ESP_OK; } @@ -568,18 +567,10 @@ esp_err_t Network_Task_Stop(void) xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_STOP_REQUEST); - /* Wait for task to set Running = false before deleting itself */ - for (uint8_t i = 0; (i < 20) && _NetworkTask_State.Running; i++) { - vTaskDelay(50 / portTICK_PERIOD_MS); - } - - _NetworkTask_State.TaskHandle = NULL; - _NetworkTask_State.Running = false; - return ESP_OK; } bool Network_Task_isRunning(void) { - return _NetworkTask_State.Running; + return _NetworkTask_State.isRunning; } \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index dbf45a7..0f0962e 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,6 +1,7 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/main/*.*) idf_component_register(SRCS ${app_sources} + INCLUDE_DIRS "Application/Manager" REQUIRES esp_http_server esp_timer esp_wifi json nvs_flash driver EMBED_TXTFILES "../webserver/provision.html" EMBED_TXTFILES "../LICENSE" diff --git a/ui/PyroVision.sll b/ui/PyroVision.sll index 19c0abb..107daa2 100644 --- a/ui/PyroVision.sll +++ b/ui/PyroVision.sll @@ -12,7 +12,7 @@ "board": "ESP WROVER KIT", "board_version": "2.0.0", "editor_version": "1.6.0", - "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQBLa273V3Dbx/flkVF+pOK7q8Phvw9J/Z76SupXMQxNIz7FDegOCTXJ+Hf+Rn0n/r8h/9DFXtf/5GPU/+vuX/ANDNbQfLDmtrcpaK5q/274d/6FGD/wACT/8AE10Og6GfE1i97pHgCC5t0kMTP/aCJhgASMNg9GH515zXpOg2Olah8Hni1fWf7Ktxr5ZZ/srT7m+zgBdq8jgk59vel7aXZfcv8guUtftLfwvPDDrPgOO1aZS0ZN2HVgDg4ZQRkcZGcjI9RWR/bvh3/oUYP/Ak/wDxNdJ40jtdD+HGg6HYX02q2V3cvfxagzBYxgFTEkeSy435YHGGJ7khfNqPbS7L7l/kFzrrM+G/EMn9nppK6bcyjEMivvUt6E4BFcLdW72t3NbyffikZG+oOK3NA/5GPTP+vuL/ANDFUfEX/Iz6t/1+Tf8AoZpzfNDmtrcHqrmZRRRWJIUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV1PhfSrBrC61nVQWtLdxEsagEyORnAz9RXLV1tn/yTc/8AYX/9o1rSSu2+iKiXDrXhwHA8JwEdibg8/wDjtJ/bXh3/AKFKD/wJP/xNc7U1naT399b2dsnmXFxIsUSZA3MxwBk8Dk96ftpdl9y/yHc9Nm8DalBBJM/w3jKxqWITUI3YgDPCjJJ9gMmuO/trw7/0KUH/AIEn/wCJrqNO0bwx4J8RwXeoeM3k1HTW3zWVhZvlpAvMQlztIJ+U5xkZB2844LWNQ/tbW7/UvK8r7XcyT+Xu3bN7FsZwM4z1xR7aXZfcv8guaw1rw4Tg+E4AO5FweP8Ax2s/xRpVgtha6zpQK2lw5iaNgAY3Azg4+hrMrXvP+Sbj/sL/APtGqUudNSS27JfkG5yVFFFc5AUUUUAFFFFABRRRQAUUUUAWLC6ax1C2vEUM0EqygHuVIP8ASuzv/D8uv3kuqaC0d3BcsZWj81VkiY8kMCR3rhKK0hNJcsldDTOy/wCEH8R/9A7/AMjx/wDxVddoNrfaf4VfQNX8Gf2rbm9N6p/tRYNrbAg+7yeAe/fpxXj9FO9L+V/ev8h3R6n4p0/xH4h+w2tr4eh03StPjMdpZxXEbbN2C7M5ILMxGST/ADyTz3/CD+I/+gd/5Hj/APiq42ii9L+V/ev8guju7Dw/LoF5FqmvNHaQWzCVY/NVpJWHICgE964y/umvtQubx1CtPK0pA7FiT/Wq9FKc01yxVkJsKKKKzEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFdX4cuLa/0O50Ce4jt5mnFzaySnCM+3aVJ7ZHSuUoq4T5Xcadjtv8AhCfEPawDDsRNHg/+PVNZ+FPFFhfW95bWXl3FvIssT+bEdrKcg4JweR3rg6Kvmpfyv7/+AO6PcLtINUunvdT+GkM19NhriWHWTCkj4+ZggOBk89zzySea4X/hCfEX/QP/API0f/xVcTRRzUv5X9//AAAujtv+EJ8Q97AKO5M0eB/49VTxHcW1hodtoEFxHcTLObm6kiOUV9u0KD3wOtcpRQ6kUmoLfzv+iC/YKKKKxJCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKK3P+EWvv8Anrb/APfTf4Uf8Itff89bf/vpv8K7v7Nxf/Ptl+zl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2MOitz/hFr7/AJ62/wD303+FH/CLX3/PW3/76b/Cj+zcX/z7Yezl2Ouooor7w7QooooAKKKKACiiigAooooAKKKKACiiigAooooAK6bR9Ji1Lw4xZUjCXwM1ztBMcIjYtz+HTucVzNX4tXuoNFn0qMqtvcSrLIQDubHQfTofqBWNeE5RSg7O6E79Ddm0yxGh6tqVlDmymgia3MgDPA4lVXTPYjP4qwq5r6z2U0y2sGgJbJBGwR0tvO5jUn5T82ckn1rlrbWLu10i90tCptbsozqwJ2lSCCvoeADVy78Ri+LPc6PprzMgQzYlDcKFB+/jOAO1cnsKqnd6q7+60bdVro/6ZNnc05tFtZItMvblFt9Oh06OW6eNQGlcu+FHq7YAz2AyelWNRt7G01nXNQj0+2KWkFuYLZkzErSKgyV74yTz1Jrmr/W73UbCysZnUW1mmyONAQD/ALR9T2/yakutfurv7d5kcI+2pEkm1TwIwNuOf9kZ601h6105Put+nMn+Kv8AkFmWtSaHUfDsGqfZLe2uUumt5Ps8exJF2hgSo4BHI4rAq19vl/sr+ztqeT5/n7sHdu27cdemKq110oOCa89PQpKwUUUVqMKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/9k=", + "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDxmiiikSFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFTW0SzThWJChWZsdcAEn+VQ1JBL5EwfbuGCpGcZBBB/Q0AWEsh5nlySp5hUnYpOVO0kZ4x+R71Hb2v2iOR/OjTZyQ27OPXAB4pUvpQRv2thSAdoB6EAk4ycZpLW4jtpFlMTM6nK4fA+hGOR+VACiycxhhJHuKl1TJ3FRnJ6Y7H3px09/3ISaKRpsbFTdz+JGOO9C3irGv7omZYzGH3cYOR0x1wT3pUvVgRBDEQRIJDvfcMgEYHAwDn+VAyCaAxKjh1dHyAy56jr1A9alexmt7oRTwSMN5Qbfl3npwSKjuZhO4Yeb0x+8k3/lwKsy6iDJPJBE0bzPvYs4bHU8DAx160CIp7Mxy3AR1aOJQ4b+8pIAx+Y/Wkks3jjZt6FkALoCcqD68Y7joe9MS7mjXarDbt2YKg/LnOOR61JHfyqyF8OqkHGAC2OmTjJA44NAwksJopvKYpu8tpODxgAkj68EfWlOny7FYOhBVmGQw4C7j1HPTtTUvGWIqwLNl8Nnn5lwRyD7fr60gvJS25yCdjLkKoJyuOTjmgCRNNlkcRrJGZMqGTJym4gAnjHcdM1WMTCBJsjazMoHfIAP8A7MKmW/uV2lZACpBB2jJx0ycZOPeopZ5JgocjC5wFUKBnrwKBD5rOeFVZo22MqsHCnbyARz+NP+wuskqySxRiOQx7mJwW9sCnNexlSywsJWiWIsXyuAAM4x7etMN/cmRnLKWY5OY1OT64x196AJ301jIBGGQBCzh8ttIYrj5RzyPSoHs2jQtJIickKGyC2PTj+eKQ3kvy4YkhSrbwGB+Yt0I9T3zSG8nZWVmDBiSdyg4z1xxx+FADZoTDsDMpZlDbRnIBGRn8DUVTXFw9y6s4QFVCjaoHAAH9KhoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKuaf5ZFykmMNFgAyBMnep6njtVOigDSWaG3VI2DBQZgdrq5AZAByDzTFubULFkzZSFouEHOS3PX0bpVCigZoi9t1VItrtGVEbkgAlOTwM9cnP/ARQNQRpTIwaMsuw7FzwDlejA8Dj8BWdRQBpNfwPKJXjfcLh5dmAQQ2PfqMVBdzrdSR7CxbGC0jEZ592OPzqCC3nuplht4ZJpW+6kalmP0Apjo0bsjqVZTgqRgg+lPzA0jMF1GRRMo+T5G3jaH2YBz0/GkM6reWvnShjtAnbO4E7iRk98DH5Vm0UgLl47NBEs0qyzhmJYOH+XjAyPfNU6KKBBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVoaVbQ3KagZU3GK0aROSMMCoB/U1n1YtbyS0W4EaqfPiMLbh0BIPHvxVRaT1GbZ0eBdRgDWri2bSjdE5bBb7OW3Z/38e2eKWewsbSzuLn7IspW0tSqO7AB5EyzcEHORwM456VitqV81sbZr24NuQAYjK204AA4zjgAflVo69fR2klpbXNxDbyxokieezZ2rtOPQEdvTA7Vsp09dB3Rqrp2mJtQ26ea8Fqw87zinzx5bBjyQxbGMjHXip5NF00X1xGkH7tb2+iUB2+7HDuQdex59+9c7/at1FKJLO5urY+UkTFbhsttXHXjj0HbpUlvq3k2MVs0Uh2Syyl0mKE74wmOB2xk+ucU1Up7NBdGvbWenaoNNWCwt4IJ5UguZVeUyRSZ6csVw4Bx8vqOoqnrdjbx2Ud1bRWsSCZoSIXmyxxnkSqOR3I9RwKzptX1K4txbzajdyQDGI3mYrx04JxxUVze3V6ytdXM07KNqmWQsQPQZqZVIuNrBdHRTaVbNHBZxwRW+pStEqeQ8rFQ45MrN8vQ5+WpLq3ttV1lNQtreKW1lSQOLiRgqmIYLMV+Y5XY3HJLGud/tTUBDHD9uuvKjBCJ5zbV4xwM8cEj8aihu7m32+RcSxbW3rscrhsYyMd8d6ftY7WC6N24t9Kji1C6gtRMsSQqqMZFRXfO5lyQxHHG71qxe6LZRWEkVuLVpYrRLkzs8wkOVDE/d8vBzgDPpzmsZdf1Zbe5g/tC5K3JBlLSsS2BjrnuOD6gCqjXt21oto11MbZTkQmQ7AfXb0odSHb8AujoL3QUiu/EaRWUgSzQNBjcdgMi8+/yFuueOaz9RhtbBbZPsmZJbOKRsuwKuTknHuvGPfNVTrGpsULajeHYxdczt8rHqRzweetVZppbiZpZ5XlkY5Z3YsT9Samc4P4UDaJbma3lH7i1EH7x24kLfKcbV59Oee+ar0UVk3ckKKKKQBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFb/h3XLTSLLVoLi1aV7y38qORQCUOCO/bkH8BVQSbs3YaMCir32yP+635UfbI/wC635VIFGir32yP+635UfbI/wC635UAUaKvfbI/7rflR9sj/ut+VAFGir32yP8Aut+VH2yP+635UAUaKvfbI/7rflR9sj/ut+VAFGir32yP+635UfbI/wC635UAUaKvfbI/7rflR9sj/ut+VAFGir32yP8Aut+VH2yP+635UAUaKvfbI/7rflR9sj/ut+VAFGir32yP+635UfbI/wC635UAUaKvfbI/7rflR9sj/ut+VAFGir32yP8Aut+VH2yP+635UAUaKmuJllK7QRj1qGgQUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBJbmJbmJp1LwhwXVTglc8gfhXdahfys+sPe6vaXOhSxTCxtI7lGAY58ny4Ad0JU7ScqvAYZ554GigZ6pcto4+IX9rTtpFsB4gimtrm01AS+fGbjLPKPMcINvzZwgB4xzxmw3Lz+JLWPVNYkjtpLG+iE17rcWoLEXtpFzmP7uSVGMZY9M157RQB1niHUtOvPCelWmnKkUNpf3SRxkjzmjKQYkkA7swc+gxtHC1tpqtnaQ6dDeXa6lpryWzSzXV8kyxYAPyWo+aMKflbOcqCMfNXnFFAHoml3LPeW8Pi3WLO/tpb61ECvex3AjHnL5j5BIij8veCDtzlePl4r+HNea/utLutb1NZJ7XX7F45LqYZihJcy4JPCArHnsOOma4OigD0S3urC0srSC4Gk6feI9x9lSzuhcQiRosJLKd8mGDAKpJ4znAxkpol9qkF1qf9qa6s15JphS3eLXIUlH+kwsVFwSyg4VjtyTgNwM155RQBr6nFd6l4jlikuRLO5H7y61KKbgLxunyEPAx1Hp1rq9Sewtta8U3F7Pb3VpeWCLCtnqMJeUi4tjgEb8H5ScFckKfqPPaKBHpul6pp62kC6bdSWjDw+0Mcf8Aa8UEyyf2jvK+cVVVYrlsbQSp981QtbhprXXY7kadqF2b+ylWLVtYSTeixzgnzVkQSY3KDg4G7GPTgaKBno+q6xodvYyXpkt9UuE1a6MVnK29SskduHc4x8g2Oinjkgj7tVpr7SRrUGlwz2t5pV3p0UaG6kKJHKAzRGQqy7SCdrHIADMelcDRQB3d94mNro+rQaJfmwSC8s7e2WzuHQvEiXJdl+bcVMjbuScb1z2rG8OXjeZqjreJBq88INrdzyhCH8xS+JGOEcrn5iR3GRmudooA7nT7v7Zdz6T4lvdOvXYJcR3N1dtIkbDAcGSNxuYx5/iOSiL16TTeI9Kk0CLUp7e2uJ49SuUtdLlO5UgaK2RS3fCxxlAeu45H3TXAUUAemWl7p9tqt6ul6ofLOgwxW8iahHZyk/aIm2ea3yq4UHI74YCqNrcNNa67HcjTtQuzf2UqxatrCSb0WOcE+asiCTG5QcHA3Yx6cDRQB6NLqmh3+o6j/aAsr6Kwna4ha6mcGSJgS8MRVlDYkwFGDw7HGAa4C8u5r+9nvLh9888jSyN6sxyT+ZqCigAooooEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFKFZuik/QUEEHBBB96B2YlFFSQOEuI3b7qsCeO2aT0Q4pNpMjortLXUtKvphbKAGbhQ6YB9qoa9oSQQNd2y7Qv30HTHqK4YY5OoqdSLi2e5XyPloOvh6qqKO9v+HZzVFFLsb+6fyrvPCSbEooooEFFSpa3Eq7o4JXX1VCRTHRo2KupVh2IwaSkm7IpwkldrQbRRTljdhlUYj1ApkjaKcyOv3lI+optABRTzFIoyY3AHcrSIjyOERWZjwAoyTQA2irr6PqcUZkk068RB/E0DAfniqVABRTxFIRkRtj1xTKACirNtp97eAm1s7icDqYoy38hUU9vNbSeXPDJE/wDdkUqfyNAEdFKFLHCgk+gpWjkQZZGUepGKAG0UoBY4UEn0FK0boMsjKPUjFADaKKKACiiigAooooAKKKKACiiigAooooA7nwXb+bpE7Yz+/I/8dWuf8VJ5fiC4X0Cf+giuz+HUPmaDcnH/AC8kf+OrWnqOgaFc3jy3wg+0MBu3zFT044z6V8z9ejh8fUc02ttPkfWSpyxWWUqMWlbXX5nkFFeqS+B9Eu4c28ZTPSSGUn+ZIrgNf0KfQb/7PK2+NxujkAxuH+NethczoYmXJDR9meHistrYaPPKzXdGl4L0z7Xfy3TrlIFwuR/Ef/rZrtZbOK6hmhOGU5jcDtkf/Xp/hXSl0vw1C0w2M6meUntkZ/QYrI8Dan/aep6rFIeZZPtMansM4I/LbXhYurLEVKtaD0hb8/6Z9HgK0MHRp0JLWd2/u/4ZHndxA9tcywSDDxsVP1Br0b7IRowbH/Lvn/x2sDx/pn2HX/PVcR3SB/8AgQ4P9D+Nd2tqX8PqAuSbUYH/AACuvMMUqlGjVXX/AIBzZOvq1avT/rqeM11nhLQo7uNr+4jDqrbY1I4yOprk69Y8DwCTwrbMOu58/wDfRruzevKjhrx6ux5mS06c8Veor2V/mY+peIbHS7s2pikkdMbtmML7VcNlY+IdLWZV3xyA7WI+ZD/jXDeIlZfEeoq2ci4fr6Z4rvvAFuz+GyxBwZ3x9MD/AOvXnYvDww2GhXg3zafiezhc1q4nEzoVknDXS3Y80u7Z7O8mtpPvxOVP4V738PtBXTPBVpJKoWS4U3MhPHDdP/HQK8svdHbW/iYNJh/5eLmONiOw2jcfwGT+Fe4fEW7j8P8Aw/1CSLCM8QtYQOMFvl4+i5P4V9LhKvNTjUfVI+RxdNKrKEdk2c58SdB+3eDLieNMyWhFwpHoOG/Qk/hXhdlzf2w/6ar/ADFfT3gqeDxP8PrCSceYJbY2049SuUbP1xn8a+b5tOl0nxU2nTf6y2vPJb32vjP41rUd3cyhHlVj3zx1Z7PA+sPjpAT+orgPB3i3wroHhYSy2xj1JW2SrGm6SbuGBPQe2RivWPiJBs+H2uHHS2P8xXlXwz+Flv4n03+2tXkk+xs5SGCM7TJjgknsM5HHPBqpTfNdExgrWZq6P8U7DVdZttO/sq4j+0SiJJA4Ygk4GRjp+NN+KvhKzTQX1yCFIbmCRRIyjHmKxxz6nJHNdoZPh54Ed183TLK5j4YJ+8nHscZf868u+JHxKtvFFouk6TBLHYiQPJLKAGlI6ADsO/r06UnO8bMahZ3R6L4ftN3gfTX29dOjP/kMV5V8M/CEPiTU57q9TfZ2e3MZ6SOc4B9hgk/hXufhi2B+HmkMR10uI/8AkIVxXwLiSTwxqRA+cXnzfTYuP603JNq4lFpOxZ8S+MdG8GSQWD28kkxTcsFuoAjToM9MdDxVrS59C+IWhyOLbzYQxjkimUB42x6jp7EGvLPi9HJH8Rr8PnHlxFPp5a/1zXZfAOGSWHXiQfKDQY9M/Pn+lHtXez2D2atpucvofh5/D3xjtNKZi6JIzRsf4kMbEf4fUV1/xlthF4RtHA/5flH/AI49WNeiRf2g/D6KOfsnzfXbN/TFWvjpDs8E2ZAOP7QTP/fuSp5rRaQ+W7TPJfhunmfEDSkxnLSf+i3r0P4yWvk+FbNuxvlH/jj1wnwpTf8AEzRl/wBqX/0U9eofHaHy/Blgcf8AMQX/ANFyUoytBobjeSZ8+0UUVmWFFFFABRRRQAUUUUAFFFFABRRRQB658K4w/hu6OP8Al8b/ANASuM+Ia7PGl4v+zH/6AK634Y6xpen+HbmK+1G1tpDdswSaUKSNiDOD24NdHdzeBtQuWubu50aaZsBnkkQk44HevjvrM8JmdWq6cpJ6aL0PaaVbCQp8yVjgfhabh9cuol3G2+zlnH8IbcMfj1rq/GWjRanqGhWz7RuuGLknH7sDLfyA/GtMeJ/Bug2rJbXlkidfLs1DFj/wEfzrynxj4pfxRqiypGYrSEFYI2POD1Y+54/KrowxGOx/1iMHTjbdryt5XFKtChh/Yt83/D3PRvHV/Dp3hW5EUqeZcYgQKwPXr+gNeZeENRGmeKLKZmxG7+VJnptbjn6ZB/CsOivbwmWQw+HlQbvzXu/VWOOvjZ1asau1j1/4jWEN74bNzHJG0tpIHwGBJU8EfyP4VuRXNrYeHIruaVCkNqrsqsCeFzgD1rwSiuJ5FejCjKppFt7d7abnQszcakqkY6td+x7dD4W8La4BqNvawTrJ8xaKRgM+6g4B/CuV8Ha/a6FqF9oeoSiKFbhhFM33VIOCCewOBzXnisy52sRn0NJW0MofJOlVquUXa1+lvn+hm8w96M4RSa38z3HUfA+ieILkX7797gFpLeQYk+vUflTtQ1DQ/BmkLbh418tT5VsjZdz/APr7mvD0mljBCSOoPXaxFMJycmsFkU5WhWrOUF0/pl/2kk3KEEpPqew/BLTJdb8Zan4iukB+zocHHHmSE9PooYfiKuftAauBJpOhxt0DXco/8dT/ANnrf+E+seF/DXgW3iute0yG9una4nR7lAyk8AEZ4woHHrmvG/iJry+I/HWp38UgktxJ5UDA5BjT5QR7HBP419Ckox5Uea3fVnpnwA1fzLfVdEkYfu2W6iU+h+V/5J+dYXxg0P8Asz4kWOoom2HUfLcntvQhW/TafxrmPhh4gj8N+PLC7uZlitJd0Fw7HChWHUn0DbT+Feq/FvUPC/ijw1ai017Tpru2u4yqxXKM5RjtfAz7g/8AAafQR1fxHuLd/h3rqpPEzG2OAHBJ5Fcj8FvG2lf8I3D4cvLmK2vbaR/JErBRMrMW4J/iBYjH0qj4y+EfhXQ/B2oanY3l4bq2i3p5k6sGORwRtHr2rwui4bH0lqHwM8Pajq9xqD6jqCJcSNK8auhGWOThiucc1538V/Dfg/QItPh8P3kX22PMdxbJIZWYdd7HkBs8Y4zkccV5v9rufJ8n7RL5X9zecflUNAH1t4XurUfDnSA1xCGGlRAguM58oV4X8J/HFv4R1ueDUWK6bfBVkcDPlOM7Wx6ckH8PSu30b4OeFb/wbZ6lLf3guZ7JZ3dZ0CqxTceNvQGvBqGwPqzxB4F8K/ERbfUXuC7qm1LqxmX5k64PBB6n3qe1g8JfCzw5JH9pS2gyZG82QNNO+Ow6k8DgDFfKEU80DFoZXjJ7oxH8qa7tI5Z2LMepY5JouFz0zw14mbxR8dLLWpwIY5ZnEaM33EETBQT646+5Ne3eK7vwtc2cGk+IZ7Y2uoP5ab5MAOBkHcD8p9D/AI18h0UXA+sPC/w08MeFr86ppySSTlSElmm3iNT129unfrXmvxz8XafqRstA0+4juDbSme5eNsqr4KquR1OC2fTivHhcziExCaQRn+AMcflUVFwCiiikIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAqe1tJryQpCmdoyzHgKPUmoK9M020tvDmhG9niWSSFljjRhkS3JG4k+qoDge4PfFXFLdlxjdNvZGHZ+CJPJSe9mgtoX+693L5Qb/dHLGtIeA7SfatlqOlzytwsRuWjZz6Lu4NcxfaxcX9/JLNM0srfekbk/QdsfpW7oTx3MqRTXMUcTEB2ljBUD6oN38/oa3p88tIJfcn+dyXTUldu3zM2/8ADjWNy9tdWNzbzIMsg5OPUDnI9xWZNbafAPne6B7KUwT+Yr0W1uk1pBo80paQBvsUznLQyAZ2Z7qfy5GOoA56a8Pl7WG1+jqexHUVtTjComnpJeX/AAx0YSiqkuW/6nKGzeZsW1vNjqGkIGRUw0S6Izui/M/4V1E1tEltZXpkf7LO2yQ45Rh1/Cpl0mcapcacHAmVC8YxxIMZH04rwsVjYU21B9/wdn9x9PhMlwUlevJt+WhydvpAF4Ir+dbaEgkS9QT6VnyxFGbblowxAcDhueteif2TBqOleWY1kleM7TnlGIxnGe1cvqlrNpflaLIATIFYS4x1c9vwrHDY9VZcvXt+qOTMcnp4dvkdo9Hu23a0Wrrz1t6nP0VZvrM2U4iL7sruzjH+elVq9KMlJXWx8/WozozdOorNbhRRRTMgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK9D1pmuvBuh3MJYxSy3zk9i5m+XPvg155XdeCtSs9R0q48K6ncpbiWX7Rp9xKcLHNjBRj2Vh+R98U0xp6WM9fBWpvZG4iQPGwV9yZOUPU/yqrq2nv4b1ZrBL61vAqhmmtX3IQRyPqK9a8PeKr3wRby6HrWlySxDPlEcOPYHoy++ePU9B5r4hifVtRaSGN0R34BUDOeg+XjP1rSFSUHdCcU1ZkfhW4mutatQNxJuYsY65Dc/0qTVVMviO9hix+8vJFXnjlziug0rSV8F6b/at+mzUpUK2Fo338kY8xx2A965ryieX+ZicknnJp80m3M9bKMJOtV93ZHdzeHIJL+y8LiQ+TZp9ru5TwXPoP8Avr9fapLeKKa7uPFDr+7X/R7KHuxx1P4Z/Wp4NYEkPh/WQ8baoWa1ukyMywg4yw7f41cggsvtHiHQ0kX+z4w1zbSA8ROuOB7ZOPw96/PqrrJtVHr1+/3vv0+Wh9LGnKEffT03+TtL9LeVzI0PR5LqQhGfzBy+0gd639Y8Myz6LeQeSgnmt3SMuB94qcc9utQaKs0EasrGPKgbh1asbxJ4s1TWI1tfC97PLd2sjLcqEA2jp/GMHkHpXPGOIr4j920kur2XqzPNMTJS5d126/I85l0y30nTJ/7St2e5k+W3eN+FOO/IrArobLWoGkmTX4pbsLxGqqvynnPcVz1fd4f2l2qm/fp8v18z5bG+wfK6Hw9nuvX9PIKKKK6DhCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA6jR/iBr+j2IsBNDe6eo2i0voVmjA9s8gewOKun4n6xEp/s/TtF0yU8GaysESTHsTn+VcVRQM3JvEs9zO89wjT3D/AH5pZCzt+NLBrkTNiaMoPUHNYVFXKcpLlb0O7C5liMK/3b07WR3+lFJ5A6MHXsQeK6+0itoJY5ruSGFWO1fMcKGbHTnqcZrx7TdUudLuBLA2Vzlkbo1b3ibxHaa5o1ksW+K4jkJlhYZHTqD0P/16+bxmW1atdJP3Xu+x9JV4jjWw7la00tuj9DrZfiLbaLrl/ZXGntNFDIUjaOQHOD1welcjLcyaLZjV9J1yIT38hMtoiqXiGSRu5PT6DrVS+8TNe+GrbRvsUcYgK/vg2S2AR0x71gV2YTLqdNP3eW+63Uktt72vufN4jFznK/Nfs9rf1sKzF3Z2OWY5JpKKK9U4AooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD//Z", "export_temp_image": false, "force_export_images": false, "flat_export": false, @@ -25,7 +25,7 @@ "custom_variable_prefix": "uic", "separate_screen_save": false, "hierarchy_state_save": false, - "backup_cnt": 91, + "backup_cnt": 92, "autosave_cnt": 0, "group_color_cnt": 0, "imagebytearrayprefix": "", diff --git a/ui/PyroVision.spj b/ui/PyroVision.spj index ee57874..c5e75c4 100644 --- a/ui/PyroVision.spj +++ b/ui/PyroVision.spj @@ -1362,7 +1362,7 @@ { "nid": 1001724, "strtype": "_event/name", - "strval": "ScreenSplahLoaded", + "strval": "ScreenSplashLoaded", "InheritedType": 10 }, { @@ -18737,7 +18737,7 @@ }, "animations": [], "selected_theme": "Default", - "selected_screen": "GUID40629891-934771S164356", + "selected_screen": "GUID66987770-852891S3274354", "info": { "name": "SquareLine_Project.spj", "depth": 1, @@ -18765,7 +18765,7 @@ "custom_variable_prefix": "uic", "separate_screen_save": false, "hierarchy_state_save": false, - "backup_cnt": 91, + "backup_cnt": 92, "autosave_cnt": 0, "group_color_cnt": 0, "imagebytearrayprefix": null, diff --git a/ui/PyroVision_events.py b/ui/PyroVision_events.py index 95586c5..1563400 100644 --- a/ui/PyroVision_events.py +++ b/ui/PyroVision_events.py @@ -51,7 +51,7 @@ def ContainerMenuLoaded(event_struct): return -def ScreenSplahLoaded(event_struct): +def ScreenSplashLoaded(event_struct): return diff --git a/ui/project.info b/ui/project.info index d9c766e..b30e35d 100644 --- a/ui/project.info +++ b/ui/project.info @@ -1,7 +1,7 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-02-06T07:11:20.7294523+01:00", + "datetime": "2026-02-07T12:27:13.6536638+01:00", "editor_version": "1.6.0", - "project_version": 105, + "project_version": 106, "user": "Kampert Daniel" } \ No newline at end of file From c91d5e693be90d04ebffed9ed30c8dc20773bcf2 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Sat, 7 Feb 2026 13:56:16 +0100 Subject: [PATCH 11/26] Replace logo for the captive portal --- .../Network/Provisioning/provisionHandlers.cpp | 12 ++++++++++++ .../Network/Provisioning/provisionHandlers.h | 6 ++++++ .../Manager/Network/Server/http_server.cpp | 11 +++++++++++ main/CMakeLists.txt | 1 + platformio.ini | 1 + webserver/logo.png | Bin 0 -> 23134 bytes webserver/provision.html | 9 ++++++++- 7 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 webserver/logo.png diff --git a/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp b/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp index ce3988c..2e6c8b2 100644 --- a/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp +++ b/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp @@ -43,6 +43,10 @@ static const char *TAG = "ProvisionHandlers"; extern const uint8_t provision_html_start[] asm("_binary_provision_html_start"); extern const uint8_t provision_html_end[] asm("_binary_provision_html_end"); +/* Embed logo PNG */ +extern const uint8_t logo_png_start[] asm("_binary_logo_png_start"); +extern const uint8_t logo_png_end[] asm("_binary_logo_png_end"); + /** @brief Send JSON response. * @param p_Request HTTP request handle * @param p_JSON JSON object to send @@ -79,6 +83,14 @@ esp_err_t Provision_Handler_Root(httpd_req_t *p_Request) return httpd_resp_send(p_Request, (const char *)provision_html_start, provision_html_end - provision_html_start); } +esp_err_t Provision_Handler_Logo(httpd_req_t *p_Request) +{ + httpd_resp_set_type(p_Request, "image/png+xml"); + httpd_resp_set_hdr(p_Request, "Cache-Control", "public, max-age=86400"); + + return httpd_resp_send(p_Request, (const char *)logo_png_start, logo_png_end - logo_png_start); +} + esp_err_t Provision_Handler_CaptivePortal(httpd_req_t *p_Request) { char address[26] = {0}; diff --git a/main/Application/Manager/Network/Provisioning/provisionHandlers.h b/main/Application/Manager/Network/Provisioning/provisionHandlers.h index f244984..7b7c096 100644 --- a/main/Application/Manager/Network/Provisioning/provisionHandlers.h +++ b/main/Application/Manager/Network/Provisioning/provisionHandlers.h @@ -32,6 +32,12 @@ */ esp_err_t Provision_Handler_Root(httpd_req_t *p_Request); +/** @brief Serve PyroVision logo SVG. + * @param p_Request HTTP request handle + * @return ESP_OK on success + */ +esp_err_t Provision_Handler_Logo(httpd_req_t *p_Request); + /** @brief Handle WiFi scan request. * @param p_Request HTTP request handle * @return ESP_OK on success diff --git a/main/Application/Manager/Network/Server/http_server.cpp b/main/Application/Manager/Network/Server/http_server.cpp index 170f951..c220842 100644 --- a/main/Application/Manager/Network/Server/http_server.cpp +++ b/main/Application/Manager/Network/Server/http_server.cpp @@ -507,6 +507,16 @@ static const httpd_uri_t _URI_Provision_Root = { .supported_subprotocol = NULL, }; +static const httpd_uri_t _URI_Provision_Logo = { + .uri = "/logo.png", + .method = HTTP_GET, + .handler = Provision_Handler_Logo, + .user_ctx = NULL, + .is_websocket = false, + .handle_ws_control_frames = false, + .supported_subprotocol = NULL, +}; + static const httpd_uri_t _URI_Provision_Scan = { .uri = HTTP_SERVER_API_BASE_PATH "/provision/scan", .method = HTTP_GET, @@ -627,6 +637,7 @@ esp_err_t HTTP_Server_Start(void) /* Register URI handlers */ httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Root); + httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Logo); httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Scan); httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Connect); httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_CaptivePortal_Generate204); diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 0f0962e..f2fa6f2 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -4,6 +4,7 @@ idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "Application/Manager" REQUIRES esp_http_server esp_timer esp_wifi json nvs_flash driver EMBED_TXTFILES "../webserver/provision.html" + EMBED_TXTFILES "../webserver/logo.png" EMBED_TXTFILES "../LICENSE" ) diff --git a/platformio.ini b/platformio.ini index 9d3540e..1912245 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,6 +29,7 @@ board_build.filesystem = littlefs board_build.embed_txtfiles = LICENSE webserver/provision.html + webserver/logo.png debug_tool = esp-builtin debug_port = /dev/ttyUSB0 diff --git a/webserver/logo.png b/webserver/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..60e7e96cf3e55d7894260166f9b3ce80a81403f1 GIT binary patch literal 23134 zcmY(p1C(Yx&_CF=`LsDt+qP}YOi$akZQGo-ZBN^_ZQI^{zy0>VyZ4;j;9xDBO@&{RK>+}V^8HwOU>w}YbIUOPVU;QH{W=21fBsN*=FA%{3%G}uq+FM zAN$f}-@i9Tnq&06h*L|yYZQU&W;xYXQcY&5Myc9x=)YtuK0a|9jaY{U1(%Gch&twi5P4bwlgPrp`5F7w!@9@r7;F>rzhtwYN4k z3rwlLzJWq=+V5oija2-e6j)oyKMo)u@TmVKP#;5`xNjnqzKn$EcmDmnh_w5BPg;nX zs+yykoGiD2jTOC~p^d%~y{nb&|Fqy0aJAJlurP8Y);BUSv*x3?YVV>THZ$a-_{}EA zC}%5TWNIeqZf~UGF0X3fZehS>NFl(F2*>Nn{msG3$Wf2j)ymS^f!mdj^nVz0f0zFw zGm!H0+8Y{kD~pQ%Z;S6QK2lRhM_XdKVUY8+#K5CN3^621aHEW@ftY7IY47 z){c6vbk+`J|I0ws$icwg%+}G&#+vv)hI;xoPL6z}PEKZq+{SvwZ2E?VY;^j1EQWMU zOon=NdWI}abcQS}h8%26oXo~d`lSCW-qFnX|CMj;@V_v81H$lM4FeNB<9}WLugtAr zZ)Wt}i~mIOGx7dU{r``~%kW=E{y!b#|Gz2UWBo4uA7uW6>HnZ>Wc>}P%QtqkiK*}) zAip-GM1@pcwJ$nc{u%vr`})$hXjZvuJ$m#g<}d~Tpa1}OXjD}}A)zQpj~@TQtiWpE zAo-waI8@Y2x@b=o%xqvTvXg0F_r3Sk`liB$M|GpOPleZ|CQvt&ZR_1ryPEH4-QkhH zerhxOE^$gFxsPbyC-(0S|Fug%b=S7-%V$#0I?vSx4-Qe=5YayJ?OAx&=iX*gpUx9U zDi7b?JobkTep}xcR9r~sHT28IDEig74&yV$?PLP>;8!ypUUe?f>(DQhSNdD|feh2_Mx9p8FP&gMjK$XZn#gKCgr}c)v(q*;Qih4E;Zq z8N~uGeXE@!F)v=DMBR@(iP?l1T28y3oy!Z8FZ*nvFnbo)pva=~jLHtdopv!k`zF>j zh(zx1x%N|A`}_{;`VS^Efsde(7O~3c1&GajK!K;zuCOYu`_!%C_nyelXu}QI$}2vH ztoo|*w7VHNl^7=R08rMP^CIECjJ1YG=)3#Ma{Jdx%BW}rs3;{|7MY9*OOh7xhWXeK zqSrqRlq4vpe==&T%>rn?hV(9wb>FN;2reqG+KG=g*_WbX3ac1bi6cQPdjRD#yDPfr zD8dOA{jD-`uhUZ=BvSBu#H=s@jKqwO(b56s4GzbjT{bV^%ieeK9%Zc`XC@{Gza!%F zO3h>q1^s5A8X(gZd;RIKuuMnOl}<$1$>as@MRX)1Q67{>^ek8P45d#?#Jfr}ybh#T zFc;-MrayePZsYN11cqf2d?p*JI|WBAu=o4J3dmG*x;bK*LmR{k3?zqQ*<(>-!STBX zF0o-m(Gh-r^mMiHH6D(+M13f~?$P`<f zdfjBUIa3q;8hQ&b206AZ0;^G0V3<)0Ksi7)dhq8hsX+ZephfF-YiK312oujVhaA~W z7+=7sm&9FwR!B6onA(Ne4=Zf^Ne=cDNPTPC)4y36;7*Ugpp+n1hKj4xB?HAffr&#RDJMztrF$aPy+bH~AY~vf z?qMQ^bWMJS1cgiqLv{1GNjgX&a+m)ia68WS_Yv?6b93q_XhcCV#BVi<0kj=^H6}p6 zOk`{eK)`hQdk$W3y-0C=1^*uU?4oD4uR=qrMTLPFB*#b}6wef<@BtAgM1aCYH6_mh z=2)Nq!c=5Wl?qCmPPJp)1Fm!@S`sV0A+~%~p*p}-Qg10K20a2*OwAWxJOwqV6J9E} zcbji>zcdcOOMg&o?N_~TwmZIV=0~~I=0l=_MFj}@qhS3;L_+jK@l{&9m<588C_)a3 z*6BSA$JT0O`)TK7iI&-cjZT9_0eZK5^8LZ{#oLB6-4deRxH(OgfFa#Ko12?h98NQyhse1C{+hZPCS=vn+a-A zB6PBU6$q!43?zZdH}?AtZ)#YJ(BI`(Cv6ZJVuL~tGvqs;Bda?uBa`ysa`4|kret_p zEd~|1&C`apnW1megF=5?P#0OBimKj(-pp_U3PMr)VRA1FP{_a_JB14jWVr)n5jusQ zrRGlzyqG9%`U*HDeK<$7V0{OCDY~ULpU!LZ`t&5a9LDN6l635jOTj&#SbE~QHuS9k z;lp;_cHK_|o;vPp&gCXm&z5fJ-C907U)!mLr~a?3b=zsEygdeMVh?o;P$mdTV*w%F zm(?_13jP;)30uj(=lneGSiX3@k3G7=F{rRM_X%pZZNrBSgSbk?B3Lvc>kFW_?Bt@R zRha@gNqa?hP|#8VzfJ!JMkNUcD8euZLyY><69{ql78t;zZK-v))U#8p;1XLJim7yi z84v~4Q!v0bnDlU z9~tHP?dud2)7gD_Tn^KGrsp)@nDH z5jj@gF2LRkt?DPvtKK`*WZTo94Oi(#Y>!*+M?+)`o z*%grj_M*!X*}2we5hWsW2H9H$!o`iNkC)b~($AH<>f}#Aw}CPSj5~3nr6lW)e0ljl2XAM9gTdwq;98CUIzIv28yk+`c zoR(K>yZ6vA@HfTM;BU>$wDme=1`VbL$;okPp6qLG)laf2mM2Cq9<`9I`uQQ+~kp?g&R; zu-nD0D%(3*_8&CW#N10y1+l73Wo)6;Ok7YCZ2|U^^`hG4ZP0GxV}LRtk@zp0b5IC# zqxMF{`UyY7&7qUQ4VGmm`dQi^4A9mf{@5B<(0=m$l_RC*a5^Pz#r4>9G66;n+f6Q+ z>G?^8)PNU?OIiQL=GNzh?DqB6{aCfsResSyxpzCqPS%hJPnT?vB^NSP5q9}}i;#)li5!l^pdd2VI?$H1pcs`3 zF&b(~mz;5nm^;2KCfGRv_5$_CA-V;#9C;38|IJ{02Vw$E?VDwa;zBYC)`*1}l0O~4 znlU+JEX#VUw)f>fmw&F1SM7_jT+Z4mE`K0}jZT3j8bR&EA+~awo%e0hU%5m7R9_aZ zJ|l)bHt%u|Yk`?x%qV|@OZ2(Tp zVOV=vpnKS-h*!~T*nIZ@0Ek}l0N*GkBQY+1@PY#`wji3!~3ivBDa%2vP*RAkC_;L zdK>6!)E^dL`n<;>cfIYa$a~(sL*8j*JryxoZvIOfBJ_$JBJ_#3(rBJtTN)Z3hL}5m zQ>sAeMR6sRd%>rpgIrx(Q>!z?86vDtXB(>2I~eU7Ij}F`6t@UEf{sK&&iLr)5b)Cd zc>TKbL-yQGJNn4(KG?9~vnthmp4uSw2`p3C89?ofzSb|_(5$QwFviGIas`O)#znAsYJ(pX61knp1TiM!%zG9oc5kcF?_8tW%-v8Sgh zG1R(6*Ib&Ts^!tO1U7VArs^d-{4TH{OJ3lVuq)*-bb*Z*O046 zHEmZ`ud&_%q-Im-8Dj*?V{Mn^dk)BahlQgyV3uS2*M2dYPAeAlFZpu{0)>!nu@sxF z2GD1hZ5ephEn(1$0>k(7rnk}E@NgLLa)$M0{=^^%jpmusjlGVovW>ia=w8sJKzX(H z;NP0ApxD~a_R(r?oO%GXA*L1C^v}=FunQjNj}IJ^%!l90Td$F{lY|R)c8}ve8bEh? zMkUBna|r7GIqDTsd;>4mB>=u^-o(7@J{3CpDehYvWV+WDMXyZWPb!RP^qp|(=ujpq z6nHYj!9$KH48}r~T2LL`n&(u}% zkvHvo(p_yA)-t{O!H+AqIiimlwj-VEx++favpoIlbb=NN3 zrt^UYr~ZL`*#a(mGcg*q}eeR?VB%1 zhvO%?nx)gLv!m13$Isx%ytlbyIzB7S*)F}^A@ILH4|eK~ROB@!%DAbFyx6DuIS2j6 zdOD38)5UMWbkQFH@GSs|B`K|BGB4HiXB+3;Bx+Y2M6&=j6f$Kjh$6JUjNd&gGNE1n zK=e9aTx@$e0~`){iO@veD6xO-Ueo?MOyY1> zjRhBH?c^dV)LQ5;G}g%TXBW1Y2fW-J)#&cvA5L5tU;d?UYv(yWHqTcaCMnP}^z^@I zf2wmklLrEUC+El8C1f!<`5ggX9UtpHUta5WM_P_f&h@V)KV?&jMhultg5VGTy~h96 z!v8pH?sWP(ckpTXoNvqb$1HVDI6(xf;Q@vdm6!y_&1-j|zqOin3MT(=w zb=75@7bok<-&1a}NB)hrnt?u*@_R-YQ0nnr&-Gs=k#MDno)WuQIJ?n*lY599ubfkX{W>q@>0>*-*FA}EZN67d#va&r3Sh}USk>$+v4@w#&POrkS@Y6Q=90+-B{Lg-9W7g#JJjj97aeiO#UFZ2S zn{TlI*LhWM@?`yaukeMuSVT{&@8>ySKG3w;532 zWxL_VzTZex9VTQyQ$~|1sqaXq$W2*&jh7Z@zovwE$0!_bI_{ab>HLf+x{gG|+NZ5# zU(;+;la~ipv%zRV2W7;z9dlP+(azpR5q2|vUVzK~vqHC$^S9K1s9MlY#MESlekojl z$@$kjx*4%FrygwzTfqRtYbm9CUc(%YXhQ{1zm=c69-$jH7V$9*yF%5%hz^>w&M4v` z#bT#6^rVuT+6r+JJH*qy^>6Q7U1-91=uAgyf7BHvlkx2S&Tf^pv7igZWe1ng6tiB= z9h_>VUw8j+bJb>E=Kp%>vhnG|qwloX>4lU?E&`4i&hoxqlX*V(`HYjr2uSC)CZu$o zTY7FCbwU&A>AI#?O(G@JYLBnC@)f914GsYT06>9{ZtP5)9+09~Q7JW%O)_wA*NsqU zJ3+p9z-RpRL*rQRj76M~RYE zsd~w-V2lhe>vg+m1H$71|0^WysJIO0cXB3f0fIoNUKs~QZI0;i}}jraw&Ldz|&P$Zc77! zMJrn#zUHmtGZIyXBfDML7i)b|6xpMVIv;R+8(N}vk-x5=_cAtZZ!EN5Hdb_w zX`fmW80@3fm;AEB1l?=kSz6Ke%Z;)Odq;GZ&RnC4MA&tL1UWIdgHC)q=sLFu7#5eGqU0?71! zf`XO+oI6~|jHg(G*h8?EcE>qKj-i&uApk`hg3!@JvN+4cyJ2H1Gm;WBHv(?%km&=QQ6jH@= z73~fLHa<^3?;kG?hJOy(U#=9}E_EQ++THy^(&+S0qDh%sTpXO9rhM9ZBUZ3ho9cfC z6#w;v`)?1Y_nP>j>3;I#ulK1LzVov3;p6@E=Ay8QN_0^X@5ICeD;wJm1Ql!W>^z2n z0a;{B3|WDQg+*MlK1;3g`D$&3a%*pxMNF=CdA;4<9Ph`x_@uy>5kx7-l#`hSUDn(N z*U=8oRoh%}LpPz9?w5Wu1)EO8-zwQivuE?LFCgQivF-<(jOzH~QM|WYr4r?;z;Ud0 zq2LfqDNd_i{AxXkkaR3NE-K#cGV#`$Up){~oeUy!onPEYB+XGg-VDPl5#cZuVV5s+ z8vuc(G86gHLR7{iq#mD~yg+O>7u%GKWPl>(N9!BgtNcSgpgAEGM%2&}M2SO@CACe6 zQbY~?9M|!4@6AP=2Wj);E6el2=&~!jLG)`vukvt%rhTFv`D}ONuI;}4Y}V^ZNcmiB zKV$3t@MNfh>r^Gl9COIY^>l=y^))}+P&X&#fF^pkK}BJ|NMoti!-qkF$N^z2nNCc4 zBv^v*Xi~#_blXqs-=&kye&^feLFe1mVfEKxwd;e0w%qnxzny5MdZB81kt(%P>95iy zkvvW)y^}~weubiC{|xIq<;r@GpPqYu}L9GsLsm-SRUf_M}Zc}}E z$&l}E6h2|~_zKjkXXgLf@ISrRcexJYm=qZMH2YY$zQFSgJfr);C<>3?BWQ@g!3D5G z8T9u^Tg%qLs>XZYxAEQO0KGRB=y|5HC7Vuvw&0i1!UgN&b^I^;gSu6P_l-WF5ZEK z9Hehzj;4xT#(GK`;)eBqW(Ry_>rI#^szwU55@0o-QkK%cqcJA(TrY`TR9G7JcK9sI z0^Ql#cSn{RkNBBdcbs|`weRmuP6#mywWlRN8(bP#*w`jMT(+hjClu_*nJk_M2)ef4 zw!V;xGo9g>Nj$OX)kRHyW9wn$HHy>e9jqk+;mFJ%Vj07~{nA=Q6qyn&I6#WQ zl};!4ggt|XX6!!=hM0~jQBmR&w&nr8Isa5x zUMxdz0_9#r{fB+usz@)v5cNV)f@h<-_mER;!PioB^%)It9fZ+$^GN&SE^>+ohml`V z$#AQYK3PM}rdOBY*2qoF@%?TB>9~lb>(IyslQUz~qs%hME!h&y-u?CQI!>1rzu3km z#==vlbxEy0Cd)3$Lq+sd+8BV}i?(^Q$@L}=9avl(wwGG%^^pBCK+ud@VE_H+hgJ9( zf`j+v)9Tm(CI(0o&{cRHzq}%2?r)o#yCR&<7VS1$j|7Da)1XYi$1??xD-lOc^)buLEkBg)y|@fT&cI92mlAixaGp4J1kqox)j_tg)>sDQUT=@gwmB)5+&RVV z34S|F>^2)cQWi@f*T`SbKZBv5OF~esDl5|*CV5X1>N|lTJZaCnEu|s7k`~m6rUrZ* zQQc@n&K9Y&k|GmIw4d!#?{4VFr7$@2X`7rqpB6)stzgI^P1fBm!=9y~bEtZwO_P=X zywW>;2!KggEyA(b+p@U*Np64ZAri}AaP)d(Z@Tb+e1$iK-M_b~*BXA{n$aT&0|Hs6 z#zH0;>kzl(fvA>yDb?{SWUKrxtot2rAZ@kdkNi z1#KAi^2zq=%vO0;U9I1&%@?>s==lCxtu@p$?68PQt2p$(s90* zhd&>2r|zJTumTq?U+Ym%J5Ys2p`cFc1}orf`BxzpQ1SqAVK^U)j1L;c!x-e&`4x0# z-nCl(uwgu7=DN6`-6Y;xVAR4#@m{w?|yf>zukTf-~+ z(iqfE%rBQ&?Ed+=^XDh(R66z4ui}Mz21zeX=Ut~s#BOFbow+j>0j-nFe4 z??kMBr^^C*GQ`r<=_oVL2Y9~~d}j}J`T%;sK=#6h*PB;LfR%^~5&%M93U024#Ky8qFXrv`7GpK3##jVGWcA7W_r)V=IE6xX!`z7;m{VCS!V+?E z^wP?N`@8|NB?w5+O0u&*qi)G`bTzS6K$zinek_pq!XhxE#5yy zf#$fyNBPc|2cNwB$|QXYypU>5x8ouGNIg%_zj1MTyPQS8%4e3=hAubSm$%l&j*lT0 z%rn(1dzX(Xd0Z}c1bv7G0R-~cJLc#@bIB4EZ7R=ZjP)11| zIB1C<*p6+%9a_uZ);$>7p}@}Ada(#2e$58gnIk%`y|@C(F@c6AKJ*vvv%kMdV((8=tE7aAde6&^3an1;C1zy*cc4Mg*!%o5~Y%)O1OnF{Wf` zoktjazP1KWsr}U^^X;lJ(zg%i^KhFCi)V^{WL6Bho^QBj7qo}po)dWU>%;fhwR;|QLyJd$hO=Xx}(O1q2d zuVosE6=2A+In;`E@UnsUvJDW2*$63>8-9|`VIPtWpulS(VKq#uPMv7dKJ4#b_JFas85*``QBdzck1t}3#K|X! zoXQ2o4JixD=}Y$yA7dK%92$sLEdS?ImNLO{muR%mYH`9xpdd~9lVDxNK^rzu3^j&AvQbdvp!=gq7HB~A-) zN^5AKPTc_radWi^4JOyc{<`+w;B!t-&EI3p&COY^KeIlqJ8`&dIdKTQj3~Iio)nK5 z*Z)W6_FJX$eB*e*DO`46dTWI4$b6gzP%qTzR^r!j2u3)KVn~%!L1AM3wdH1 zjZHO-$7Rb!+nNByZ>U|}o*x61Fc4nL;^^ekKSCsd*A!9UE@G>sgb(6{|GNmIq5_jY zQy4nae(KobADx)9wtx}XBL%;H0M-l8hg4SC#70M^Ru+?N6q(jTp>w{Cqx3gr4y9%^ zqAg^qOc?6dA-g$}HIQM|=u0JdB?JM>hXCe^MVj0Cu+wLR>EmgT-C~f(bu*-VK{UbB zw`@NzChL=glNC`=xZc+efusslC-m$n73{^18Nr;9hJJ+ahBW>I{zfxp~^Cu;8RZT1^>~M;2|>z^IeZ8qI@bfy9!9H~`$-;&$+9 z-urDbNzeuJq{J)2M~dvX_1%@N4&VwtnQcP|BU01FGKnm6ffIgRB@%peJmZ1-(1_i! z4^n?i-T>P^K|o?~I*3VDgF5*lG3!n$DSyt5XFxy?dXv3qD8!@mA05@9{-jv<1(aYG zPno(O?~&4yt1B)wc7JfO?4b;$rWwJp*l6-3n{XIAukFMG!mM-$5u(`6)Xpgrbb#@J z|Gem`oj}y#2l5?O5R_rQT>(?cRy-gf!Vc&kAAS3GIG$5R_V(fCW^e+-^{z8uP$9v9 zY=D8GW8zF4sfQyd^vV&3dV?GY7Y5jQ7f$-4xWIdmh&Sn^l!9?N`7Ygwn!tSW^8(Jl!Qapn}EACn~2a-9{;9=d^{17tz0th`*Dd@)Gh{5&fPvxz*15DFtF=kW0{ zB^eo6B)RTdn-}yQHhtcepn%J|9R)i2-uc$jSY>nN-sjuZK|aw7jLVi6w$95NgTo!2 zz)`%6jso|Z5cSV)KoC<>pyzezqJFT1bVIWP!sA?}&51exe$~Low+|K0kFF~uN8A?FJbp2owH4i6OLI{W- zBjWEhb6U1^Ryd1{5Ck~?b7m<`3s3tz(L~^8c?A*XO5LSnan6Hgi29G#T5b~E$|0ZW z*Av6%$SgK?HjE}(Pq>M*Q zYajyIF6ZErmTE;w@|bUKdpmkQ=7RLXFALRCRg0hE;u2IzV+~D>4rg@DjLh7<$H$y8 zmag9i)~r1vhW1#Csuvafqnt~v7E_Xk^d6aq?PB+Mn6mhq6f+=2nIwkqsx%$vd8EPVs$=WBe0>Wqt{$>7IP%MbGex(W`T3pgp#kdP% zmA^0>?SIY}3IE9mHMAmkJo8Ar8v_q~DV;RByCp!|{&zQN5uR_VSAd}hsPl-qAR0ET zmsLm+)Fn8l%==Xi8m|cy+3F_Na5>i>i{3b2ug~UtdtGia;1HK|zFZ%1n6fHTE}dO- z@g-Pmp3$VObG;FEzT%SX|8{ygOl=_NB<21BUvHJHo-2byCHadGjImHgoLP(6yX}X7 z!Ys&1-+L3s9H1OtLx=_eDzvRqxnMSG1j@1filMGj9`!hSJF(hKo3n_0oAc{ zvX~om4i1<|F5PbFEm(IY56cB!+mnc}Lf>~?>Fea}Zjd6iVsk>eb&na?D$sy_SA zufi|V&p)`$pQ1-KUfORsy*mKkXxDHA3Oqh_wV$1R5iCxb^p0Kw`I+PW0y&fBiojti zwWMhAyu2vJ$C%ga{dHvirdj?d=Ic`Q^SKMpipzQ6vDGHSiS8?5_|fss-$3KnBe5_KhTHy# z9B-{1-drKG0^b8GS;AbTeDX@Ojet7M;bi8}VARz0AcywI@2*G0s*hI=uCIgY!Jh&k^ z_02=(UqN9o=JlCRD{*?tS?qWJZl1=C$rSSYdxp`FJ{Kdq0WwysgRVH>El6^Io^}LY zo?g2$eI(4h*6Irb&I3bY%UcNSiWTEt_dTp5EvfcLt#n!ygKaGde272-M?D01Y)TQjzFB z-Y0K#N2G!jhLcp5v8$M_)!*{-7B3z}h*Dr?;|l`$&z1hq2^*R3nfQ0d*T%mmzN_6@ z2@YaI^jN4gC>+7*Xxj`_AjFVR3zt6nwku@d@T!*~h`jH$GP~53x}sU7UBakNA%-6j zh$8)Oroo&>abaWc+GBQlDBoUUGzE3m_?V&{t@eUK!#(sr-k(u_2_i75#v6bKgPJ#X zA~N+PqGU{liswF(H~o$DhLEI-squqO2Fc#N0~&`pWHJPARDFhBhmQ(eqH|RjY*7fZ zxNQt}rk%99wrIcxt0M>*Ir0iCVF5L|AGiXEP$-zO(}2fr5!0BotF(V6F4CXu{iDk| z*9>u8Z9g33fBzD2Qh)o=tx4p+V-@(wRNL-&&R^f{nJ6KPU&8n|lPVC=&(A zb{ol}y~T5uA|9;(dMTTnw4~9+!`%yD_5k_%)Je>92|rGgxDS-0)K+YGn3)IX`!SST z1fhiBl^aM!p>~X8y|GSAP`%MPvB;yddtmEeI0W6f@T*7opHv?C7y|ax>7c==@bQOw z;-a;#h1Iv%qVsViG}@vkkJ^pB_jJ7|NywSgfK;(8J~BHb1v2U_@7v`UyiPKU@|0z` z`d9(41T-o?FUv_;2KGZXD zHK^7b^w_Ld%AoL&`E%*0Rjj9vIO(F_S)XoP$yG~<2ZfeoDga2 z#Fzts${F=3Q4uLHh(Zjd3K$VF4C>usYs!K9c?|CG9726_C%jj1y-NR?$0B%72s26F zLx?|y)FHB%u~jyF1}9_z#_OtB97z(cIDy%HQU|v02(x3`u4e1R5qoO(OLm%?zgMN9 zQ)l{xhjGSkvwJ;>e=vuNmc!x~*xCg~V4zXqL(u!}k@m9cd_}b0^JfaT)XJG6FI6h>_xrN9xA?gDF z^2U(}0Kjaj9(W&AFov-tSuiWY;Jo;!Ma|D7=EkxgiE_#yC>GO~v^9;!t0FiaNZrxJ zmlS17OzL}_NQ*wf>Hty#Yyyj2H4*~o9m#I;MpHOU8VwMffmBMUd`bm5(x^JQ)3(i) z0aNrJ`xPdBKo%H|DD-`lQhd_k9m7>YIo&*_g00{TYGS@@RbY&*@^*o(vfJNp{7h`U z;QI%!ao3K|S4&u!3PFUZ+4idYYwcetka=Um$H!!8@v%wP0|fhOLHcW_qGT4G07Mfv zjZ+i3yrwjavIFLU2@I%-a7YS!wHgq_Onhv%^`aw>c~(74Xg6KK+qW413s;+ zUKdH;+~?SCWC*IjVP9F2f2_|q*Y(4y@WQzB{ZJt5MMjbg5s8E=MWpH)^{0h!Ev3BL z+%b6jwjaRATJ%QdRs>;5)e1>S{)g#KZCX~6z-~MI+0y$-FO8=0EbTP*RC)@~G)Q%Q zVLA~wPDyfrl(u=(#fZb$!-#3Za5n}9H|yA9?=NzXC<#l=+wRW}B;=3o=Fo88c;Yqs z>tvy7c2U>@FP`O?hcDyMA#!1O*^NPIt8x+q#KvjGhy<<{Yi4~R|5zvz2w@8ThK8Q7 zjrbhD;NPq~Ka-CA4ZB-YFP0|KgYWf~Q|y1+h-qtNqAkhGhFQq$?XKo3RsCdZt*?#2 zFOPYsxYQ&8Ww-V;oz->L;2^?cNJkbdRqa6r3&aqO6P6AmBKQ5tB+4Xi7O0Fe1ke&e zQK|gNv>H3MADUi%g=Hpj2UV>*8d4R5IvEG+Tm_pI{Y;+o7zzw95<&nTye`Zq*`)tFX zfC@;fRCz;BZ!>s))ceA!O4dSr;RIvyw5~J?<`v%C=E7V1@z?$`p zsA+_LRN;XfQamm+J#ZL627YnJvMx4jvc(hHs~$q3bM6CwC~{6YPiXLEVdv3X|6Kbu z{Fv0!-|)R+MHqGNqns#_3UZ+)I#3Nz2Fh6JW)jD!5@tb_TuBubbUlDd_2TdmvuvaS z7@>oEo02+7V2*P6m9-{}Z{cgni&@$P8GgZiJe?#MI5f#Yq?uDe2pRsYGUFeq`U9LT zb7Z3lZI623)t}Qpu(pB3h_Z5U&Ndj2>hp-Im_h9DdjOG0x@>Dh&yXhAY5CoG`1M5a zEI}&8K{fbdtAbLwS?D69bZJx^*;J7Bp2h)o?jLo3vuqK1mz?1dn2lnEn8BA9p2b%w zFP1Re9N$LYM)e-{`^6Qhli2(1WIMDCdi-C;Gv@++IamDT&nQwa&1)b@m>|WU^5!D& zuL5N|9|eI%JnX+`U8QvAZu6s@S;c{HL*Whn+FCXHQ5L_tEsrt&1G7k2$s4-1_JfrNwUw{H zoDG)+VzHDoO*D!~3h5;{=DKMrGMN zE6A_XK_*4Yy^$8iV`|(j)#Xs3d+!Ic}13XGwY@%*Qu@&cl*d&4vc_WW57A@)< zL#uIKv(xbg!B1||W~8gK{Wux{`*n{akn@$Lx9j0$fV4$89o@I*A})4cSVJSD^k;dX zk}P*Z?W&xC7juGX{R&Z*V3kcxwkJ@+q?YF8!ym;Aeu6jCzvFf5-a0Rn;|OM2ehF3euRT$afXyhM1hJJbLp>wG8VR5jA36chqf7Y7G`dF zi(0`}T;+1v8p{>Z^awHiLY(Zs%myl$XBfcvnHm25t&@0fmT>u?@E zY*}+ZhFfIBw4Ro~?q^i}qVPVnDc@?Dw&8jwI7vp|%Cc5}yL5EFSU9;~RXCiZcsJwr z>K(vHH_;iwM*kB{6XV1>;WVY?+G_{0^*p%5E-NQzbEk=%k4W*?G$RfQ3fgSc#I7($ zvkJst*ntILDSb4pAWohYu27--`^wrr4IiH8aEGVK8WF!BV+fJ^hUE_SHsYE&Q}QG? zk6W1LaOz~cMhqUX?Bgr_qoC3YG|dt|O%**YN06H`cA|la=^aL?GNx&gzKwe|E%mRy zqhn&$rTpt_2bvo5glepE0kX3dG-SG@$r$QT=+^BP@q|AKdw}Ma{gDMky)xzJwLy&yZ@MTK|RWnUxGWO zQMQR!EyNTDn6V0qO~ou)YiP1%eX5i>ka?H3G%LlQ)QdXXbZ-_l%TAR7r|j5>#pSu9 znXZE4Y`H1afx*;u#0b~w%xsgI zzFHNb-WU&~zz>=E4l6{luYZiQOpS}?RcqW&8r*vCl!O9yTqTFZxao!4hzSZBy#JzT zgZ=A|gu{kTNd_8CXqvK33wGt?{UeWWyblxI-JMvA;#+umB+!cd`HMPF6(>PXe1f!$li4QG)vQUP7{pksk&s& zJc~m&2osmA8kT-EE&&tQsG`nRNVLBShp#L@RuU9X$&e`0x?HJ32$~XSZlv6w9_l<#zy=2?N|y#XcLMh~EmzP4QG%G>kP+5d z--O4XQaU-NSiHXAKsalc>D>?;8w;d@dHqSizuv;<^-xeKN zuW~78uh!($I8F}z_SqKp{SKpjOeK{sc(9bR>H%&?;it$l=otC=g#l)VkB-dz-13#b znm=GJteQIHpJBzeceeNTcFABP$%AAzM`m^#&?#ebYf+t_o@P1LhnAl~(9uOAqmb-# zT#$L1_=h&Fcw!4f#U?gr=^v-j3Wi}q9zBzPhBVeTln4D7KytSJL>8CGA|J-!eA#d8 zm#()OB22Ht!J-#RbDmrc#T90c)Xpw228ACDnE-O!s=ThG7~-d2EF<%AotaFsF_?1i(2#ixN=jA` zDqSU$swMi!BL#U9st|f?uQ_KLWkIx9x_&zyA6QRT2)W(>F@ayP)knT6F)n0eJ&d{* z+A*wO8cHgYA5K!Lo*xbtBPAm=ggf+cRP2g5&8&ACOa*%~$uK3;j8fgCWWdBLgD9A> zt^K}9FGEeyS!y$|dPpRoPX|6floH`jttU=(%QmlIy@w9b-H~I$jh48?(DzN2$twEW z3CL+UGA+%W*nuA?NS(IVg%K3wowmbVpaj+|5&rUrkaP{Pz@N~?_`4|v;k9GCIZ2p7 zZnS2nMPp+#`s6{9j9ovbhCZJ;KX<1T_I4v;4#MOFwp%Z@#3i$Tcb*C#I=a*v3|W6i z0XPo=_fD>e49s^yES9pmr6}+vN>vB$JoAP8(~GFvW#8LPi@C; zJ3#LMv%_F^7}#!LyN0a>wiv`F!}Sl#BO2G@#l$f}(g|*{Bqdy29DE!LJ}l@`!llK@FxPKpQL2OGnJ$)RJ6W3U zV6I=FO{U0cL6a5~aVb%ZA6FKsr8edGi%0tx2VPhKEP{?z!io?=>#KQJv>?GHLuawX3CH%$jELXyoX4Y26loIyf$+!@kV*oj!xq$8bXXlqwngrV zyIiJ6BsnB01X&{p5`#21A$9v!P4nVMd=Wdh{EL*gY(Sac* zCMNM*kGTsM5TsHV6;qNCB^luvNzQnrghwD;Qo<#TLkfogNeYLIaY!5cm@$H!fhGe* zBn2D_+NIOYP}>yqwa>5PRj+v$AHMqCK%MhnaS<;&_YC^_2Dty>$0+17oN(-F?z-a__jzW5T>9)AqwatYt_=pP>b`>%cNZwDF|;MkV4{-h=7o>!v=26BE8-^*ZxoQXVz zY^1L|q~qaA>#GUn@bc51C7qAJKxx3?CqJKyuL|U4nyg5Z5kAuRWL?eir;Z_v0mrcC zamnTfJ(?4(mP3-p(k0D##j3NFy*m*+d8^CdUO|&5@r^^qxS(BhJsBd?NPdR~6WOR$ zB#Z6Zj6|XUjWxG3si=f6$(#6>n$hXDp~=m{dGj5P`-U4+{^d6Y{^dV*{mZX+QdfN2 zNni1l8$6FfdNG-aBEERmmrsAwVXwYd$&i2B{M|D@bI&#R0$hLHb=R#tZ0Q>&CMU^e zvwZIJf6YxlzmXtaWbLu5*x!4Ay$1&9p3_62kS7X5`uqAQPfdg4;0m8slc7~)$x0tr z*nq*6F20i@<)rXs3eO4f{S1MdCUDdEUWQaqAfIU?pKf7-koAKP@rxZd5`}wkygV1b z`jwn>)@khT?dNAV|AL{RA>MrXB|Q4*M%J%i$HGO+`Np+hAr<(fQUSdO2Dkt7PkwsL z9pCv*8Q`4d?_YI7;j9O9Cdiq32`^H(K&3v+czGDtI7p)rI!^jkt@@BABB}^ZJK`ZO zyl4YxP&N3EA1r0t-Zt7DLk8=Ic}5Xw%@N1#X7vSQAYrV};r8n@h>9R1AV87^9JD2{ zJ45EI(zqEY4NA5=;!tuWSt)4}lC-dV-=f7O@~t6S%7e>Cx(TuzFg{2h2B$@J(?<6@ z#)xTcv?G+AyfA4~scO@-`0*D?we_=s@!OEuA*-|Qb-(!G+4IkO_1yz^J#hAS&OaN7 zuDa@~MHjs6oQK+4TRX!rqFSr*p^tou&6_upZ|>xzwq5M&>!+iula`id1j07I z43D6d2FD?dN4v<?%K!AKfjT5CdWVh!5PtO424!0trEsU5C~1)F&w}nBL!(GFvh__vS{%%xt0*^&RRp>we_b2w&Yu6 zVC$qixZ=9A7r<@5B<@_9JNSG+LOy)4xx2rrJdYpw{LBC5s8{y9{PB)_r+f3@Z6AEc z_ulf40AK#{moGW?sH1)=gu!uLdi(nM$j3fSU+->;tvwvGY6UxY?Pc%&0~Fg@Y42zw zoeC&TmlzxzrZinj=xvE3Jeoy{R*|Di7AcAxX(xr}rf}T=BP7$*88bEZ)%)08-G>gx z06~y$=G42 z(!ncD9aD?(bV$ybBCHrPG9*PzU=%^JMuJ0ZSAWsAb;cniMIA>(K!}631qn%YufYBv z28~9LmWGT}3=t5BWXLlP4zOV1G`ZFUYz_!dU>YmDxXI+nwBWf3Iehl*{*i;_^3d%2 zeRWgQ(hus|pBWW*?UQn;BM^bWI2zB@+_kzIzh(CRzpgwlXuWI49fL=7AJ=hY@u;<~ zl4r|w>i#EsAKiQV?YD0^|791H+uB-RR;g5JZ)@S`)vI{$p~n~M{sRDBmuR=2Xbw3$7n z?Tpv^F-FkYHHVWi?J&BQ#F>bi&7Vf#{0p@gfa>*;s=gB8GaqF$O05Ko< zz}39<&6hJaI!;?#EBpKU@A=fHKJ})tu`va3_UccsU0gWj>n<{*RSjuuKb1{H8C)PE z10+yWwV5=NOiHdT;cD=O#xVvRyJRI~j3h9&%)mt_$#jEj1isJ&QV|G+D;f@aqiE6+ zxOTJ89W1Z{X~+^$7Cs28(Hvu|c$-^l_-Q@UuwuuWVi)E}z=kInDWkvtjPp;EM5WpH zd$Dm&euESJRlBE`EOd2ozN?$(c&6CxnWlEk_~+{U`|SOHUHMN8$*og2-gj2VdFLKe zT(ck`b^LSn9X}cz?=AoMCqI7hv@_0`H*ap&v6GXN^mKJ`?6F7l*oLPV89u`GC}XpB;rWUT?|y5yS*%$+xv zBad3m%U*UiuXx4z9DD3)sDF9o_AB$Z|RPsDZ6^MZe%@e^@VE; zu7RABB8uxoI>ZqU!dSpb>*M2S3o1`&JT#uxGs{QXMb;YN)pis1Z;8PXjb=e>UM$EY zZUe-^AQ5=dkd=y9cu7sOAtMYap~!g=Ze(mEToZ^2h_Ya`F4bNoOT#s%K3W&?NJZ>_ zcqI6j-g^CcQDqz_{Ad}6|Tqsa%X{K0gCZEp{#frYZ zel|V3nWvuK#PrlON3S}ZQ%+jT(9j6C-+4b{!+U8icJY}{|1p=m>HW4>P49g1W+s6`nG9O5tmbuNA(I2$UkNK{Y$uIN6XJ=+`U!TRgP0jD*chB@ zXZLodrf5x7G0Ey1MjGnV9&RLXTxIEtq!`jdMB~g#rb-9a$EgS2SqlD0AdG9Y)8wT~ z50nOm553RlW}43b7g@b+A(7222pe1o0aYb#&rIuIdFh}Rk{1LUz{igN{5hw0oq7BG z;u2@W^dtZB_Mcw-z9bpr+Igamnl&G3>zRAekDJr;P8a1tQei|8D*PzIRSHijf>;q~g{NcEN)sr9XEc>)nvv?L z?d&reRI<35QWk6~#M4m%xH9Sq4 zPuS|(%0z%|FjGlCOG1lC5K`L;UB?1VxRQJ8&Oe%HzlKho$p?E-JchWO`mdI zk2sD=r_B$FVl&lhmCf7su<^OA5KYk3+{wG%@h0AW<(o(a0i{xfrluyg zY}@|i6Hh*M*{44Bsa*gkU-XYXh0NOPGH%zIqB=|vN2J1-RHR6U3SSulEl4ZKD1)cN z87(Jt9jPL!s=`!#8mTl=*|n}*9V1j7ttv=e!&4D{TqmXK1k~`8#X3YXDWtKE!oi`b zjh=fOAZX*zogSk#Q%b-FNJDKhz|;kfR0+6}GH;tvvq6Ql)T$Daf2;Ygd&gwe{_=l` zyegA<<+oM+rh-<9R+~woGNE~>sCeEilwVhVDcAt6KIyaXJH7iAUug0=njRdu`{o<^ z|KY8VZ+m1$reJKp{l zR<2ym(=CYa#MV<3}~5F5{RIZlc9Rvg)#3AtpkaB>EHw!Dk24NV+n^v}A2>Rs#Ul2_Ic| za2b!`yZEeLVg2GlXH16C}V*XKBi1$!F7KvKca|0LOD} zb8{F`DOVVsm||>v5))0$oJY^x#k~Byv-zVpT*j(ZM^dd;iK3W7p^3fw`}%h5-2LIp zFTeap$?ooPm)!KRRHpm$sdTq+;<_FFQkz27Cq|s8`gFb2|FkHNZ7NR)sQe43BDc&ms}J6cUNe+M#5(s zbt1ntc}ZXcc-NXgKXp-I^>^nMR?O`UcMWeD-|)qMfACMflH~uzKYZmY@0~ku-Y45y zn&;K)HR32Hok*SYG-sc6 zI&0UiWlmQIwOW;Wy-p^bVR&qe!Qrv%ZoTWlYyS50f4UQ3_3FPnCEIiC-=#W^UaR6U zbiJ=niuwipas$P@Q&oqGHek8JV? zoOJAa+uEAn*w)fA-}QVubHjBBf)obBIKj)x&aNIc(TVBi1;28M2Y+)Khi*8%B^wcnWW{;64cgE_3tWbw_ z8Z9!$md?gRXrfu#Ek+uRL?eWyQY7}#L*q$f0|XBUBvoKrpuRGkK75ce8IaH2KlCUeLDw7@7S3H;@ou=XH2sr<9ia#1zEjfooi?X-8r7spAqBVXk?SvbRG)h2 zzP}6kRlo+onJcb5V^QjVG%^wxi$nT7RCTCX>muwidEWdjgT|_Jq^p;TBw_ z=Q&y}2#ipmiQ=k2MPb@_yM0HFm%|d%wb3x|1e+(-#O?#}o_$+KxBi!o_e+*Fc;`N| zVCgA}Me|Lxpvhrgo6#Lw*B8$t)<|Ix5@TXVqsJ$V+Ht_~hc~-C`>&Ps6T2B2JoF=H z%L8k@TTbbSE+Dow1j2{g2js0Ue@tI^=)S)T`IW(zNcQ5@pL}OiYTi41zj#DV8^&sb zr8@PW)%Da*)<5~}N1(T_vGa#M^r7ZCbLJekaN)wvQmJxyPgjSWu2v889H;2Jt}?=i zdOaeW&Fs+H9PoXA%Z3e4@BYLmzW5yUHzJG|mj!1u&n=#`tl2MgII4b_CZ<+ zi-a-Vo^-Q;@H`(E&q!QtaFnGmq%yd%#x+<6-q`Mbts{)CV+hNjh86Lasc_<{a$LUa z)}aRP zfcb^_#iN(J?G1+9$NivVzLE~p@g$S=k+H~$ZZeKuSFMlSwf*U@_x~4B!Ap@;Q`5>! zX7M>)#?7vhj=#|Hn~uboBP4Q;hbX2HULXXXaBz&a4!71wt#FLS)pkOpqm4~XDTAXl zPHf+kNy6QZA<#&paYT}C5&}#_Et;ktm3LNk_0Gw7@|K$??z=PT7Wf|{_pOq5pEk#w zNo?$`_6!g7%b%b2lz!Er`~EKEHv+bXENwYsZhQN&?{K}Q*AQfnl<5u;dxB8csK=G@ znyw5Otu}@A=^^3yTO+Lov|&=mr8tf%qAYUT{iX#aF~0FAC*STWW1797)e%xI5Jt}x zUZxvZB5`}9lg>)V%Sp#W8VxE$s5(wu$JHU8QAwwgO#pjF;uvtXotxwt2hT`+1D;YA zWU;}~HZx$WJ1p=Vt!>b)BMcE*)o@gVrwvkQs&SdRs%)Cjl^;D<8@&FhaC3uT{JqN8 zmpSL2*lapfgxOq?-A8A2-`$g9h2-J$#bF61`~wpo%|v-;|zgcH0?q*~9=PG*Jn z3uwp32!S!SH$F~^M-j%Z_vyG3NVjI6j~(%`$(E`1=i_E zf(eXGBRQ&$iOUF8ElK1~2h(d*xYvzqlOn3@airc~Ee)t3p4z;3Y)7@!|M=)jBy4|~ zq!(ls6pqLq!Dw}KX}g;(cDtF_pqz14nOi{S!mzS@IZBa5=(`XYH_4lNxG1#RR&HoT6NJF*k=SrM|Hnt@$E+Gim6TdM%Q-< z>F?HIX)2w{?5&RNsm9Zr`$o3>bU5J){viKD<^Kax!wWZxYUOYM0000
-

🔥 PyroVision

+ +

PyroVision

WiFi-Konfiguration

From 333b8515b72a1025f9417690aa69286d1270e170 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Sat, 7 Feb 2026 23:10:35 +0100 Subject: [PATCH 12/26] - Add save button to main window, move wifi button into the settings menu, add coredump functionality, add memory manager to handle the internal flash and the SD card - Remove the settings file after loading - Add USB support for mass storage class, add USB and memory manager - Fix CI/CD - Format style, update firmware workflow - Update documentation - Add version to settings, rework settings structure, clean up code, add task skeleton for the camera - Image is stored as PNG - 240x180 pixel is used now - Move Touch I2C into Device Manager - Add Skeletons for the new sensors Signed-off-by: Daniel Kampert --- .github/copilot-instructions.md | 243 +- .github/workflows/firmware.yml | 65 +- .gitignore | 1 - .gitmodules | 3 + CMakeLists.txt | 14 + components/ESP32-Lepton | 2 +- data/settings_default.json | 1 + docs/DevicesTask.adoc | 217 ++ docs/GUITask.adoc | 580 +++ docs/HTTPServer.adoc | 330 ++ docs/LeptonTask.adoc | 653 ++++ docs/MemoryManager.adoc | 1176 ++++++ docs/NetworkTask.adoc | 347 ++ docs/SettingsManager.adoc | 4 +- docs/USBManager.adoc | 1040 ++++++ docs/VISAServer.adoc | 564 +++ docs/index.adoc | 347 ++ main/Application/Manager/Devices/ADC/adc.cpp | 27 +- main/Application/Manager/Devices/ADC/adc.h | 32 +- main/Application/Manager/Devices/I2C/i2c.cpp | 9 +- main/Application/Manager/Devices/I2C/i2c.h | 40 +- .../Manager/Devices/PCA9633DP1/pca9633dp1.cpp | 456 +++ .../Manager/Devices/PCA9633DP1/pca9633dp1.h | 148 + .../pcal6416ahf.cpp} | 89 +- .../Manager/Devices/PCAL6416AHF/pcal6416ahf.h | 58 + .../Devices/PortExpander/portexpander.h | 66 - main/Application/Manager/Devices/RTC/rtc.h | 143 - .../{RTC/rtc.cpp => RV8263-C8/rv8263c8.cpp} | 165 +- .../Manager/Devices/RV8263-C8/rv8263c8.h | 141 + main/Application/Manager/Devices/SPI/spi.cpp | 12 +- .../Manager/Devices/TMP117/tmp117.cpp | 373 ++ .../Manager/Devices/TMP117/tmp117.h | 170 + .../Manager/Devices/devicesManager.cpp | 174 +- .../Manager/Devices/devicesManager.h | 93 +- .../Manager/Devices/devicesTypes.h | 48 + .../Manager/Memory/memoryManager.cpp | 533 +++ .../Manager/Memory/memoryManager.h | 209 ++ main/Application/Manager/Memory/memoryTypes.h | 49 + .../Manager/Network/DNS/dnsServer.cpp | 14 +- .../Manager/Network/DNS/dnsServer.h | 10 +- .../Provisioning/provisionHandlers.cpp | 16 +- .../Network/Provisioning/provisionHandlers.h | 6 +- .../Network/Provisioning/provisioning.cpp | 271 +- .../Network/Provisioning/provisioning.h | 2 +- .../Application/Manager/Network/SNTP/sntp.cpp | 6 +- main/Application/Manager/Network/SNTP/sntp.h | 11 +- .../Network/Server/{ => HTTP}/http_server.cpp | 142 +- .../Network/Server/{ => HTTP}/http_server.h | 4 +- .../Server/ImageEncoder/imageEncoder.cpp | 42 +- .../Server/VISA/Private/visaCommands.cpp | 2 +- .../Network/Server/VISA/visaServer.cpp | 11 +- .../Manager/Network/Server/VISA/visaServer.h | 2 +- .../websocket.cpp} | 447 +-- .../websocket.h} | 44 +- .../Manager/Network/Server/Websocket.md | 445 --- .../Manager/Network/Server/server.h | 28 +- .../Manager/Network/networkManager.cpp | 55 +- .../Manager/Network/networkManager.h | 132 +- .../Manager/Network/networkTypes.h | 14 +- main/Application/Manager/SD/sdManager.cpp | 365 -- main/Application/Manager/SD/sdManager.h | 72 - .../Private/settingsDefaultLoader.cpp | 7 +- .../Settings/Private/settingsJSONLoader.cpp | 250 +- .../Manager/Settings/Private/settingsLoader.h | 10 +- .../Manager/Settings/settingsManager.cpp | 335 +- .../Manager/Settings/settingsManager.h | 82 +- .../Manager/Settings/settingsTypes.h | 66 +- main/Application/Manager/Time/timeManager.cpp | 82 +- main/Application/Manager/Time/timeManager.h | 118 +- .../Time/{time_types.h => timeTypes.h} | 11 +- main/Application/Manager/USB/descriptors.cpp | 46 + main/Application/Manager/USB/descriptors.h | 45 + main/Application/Manager/USB/usbManager.cpp | 332 ++ main/Application/Manager/USB/usbManager.h | 62 + main/Application/Manager/USB/usbTypes.h | 53 + main/Application/Manager/managers.h | 5 +- main/Application/Tasks/Camera/cameraTask.cpp | 179 + main/Application/Tasks/Camera/cameraTask.h | 58 + .../Application/Tasks/Devices/devicesTask.cpp | 72 +- main/Application/Tasks/Devices/devicesTask.h | 18 +- .../Tasks/GUI/Export/fonts/ui_font_fa.c | 3 +- .../GUI/Export/images/ui_img_logo_80x44_png.c | 226 +- .../Export/images/ui_img_text_218x40_png.c | 550 +-- .../Application/Tasks/GUI/Export/project.info | 6 +- .../Tasks/GUI/Export/screens/ui_Info.c | 116 +- .../Tasks/GUI/Export/screens/ui_Info.h | 102 +- .../Tasks/GUI/Export/screens/ui_Main.c | 134 +- .../Tasks/GUI/Export/screens/ui_Main.h | 70 +- .../Tasks/GUI/Export/screens/ui_Menu.c | 34 +- .../Tasks/GUI/Export/screens/ui_Menu.h | 24 +- .../Tasks/GUI/Export/screens/ui_Splash.c | 28 +- .../Tasks/GUI/Export/screens/ui_Splash.h | 16 +- main/Application/Tasks/GUI/Export/ui.c | 10 +- main/Application/Tasks/GUI/Export/ui.h | 2 +- .../Tasks/GUI/Export/ui_events.cpp | 45 +- main/Application/Tasks/GUI/Export/ui_events.h | 10 +- .../Application/Tasks/GUI/Export/ui_helpers.c | 238 +- .../Application/Tasks/GUI/Export/ui_helpers.h | 80 +- .../Tasks/GUI/Private/guiHelper.cpp | 232 +- .../Application/Tasks/GUI/Private/guiHelper.h | 16 +- .../Tasks/GUI/Private/guiImageSave.cpp | 171 + .../GUI/Private/guiImageSave.h} | 22 +- .../GUI/UI/Private/ui_Settings_Events.cpp | 173 +- .../Tasks/GUI/UI/Private/ui_Settings_Events.h | 63 +- main/Application/Tasks/GUI/UI/ui_Settings.cpp | 518 ++- main/Application/Tasks/GUI/UI/ui_Settings.h | 12 +- main/Application/Tasks/GUI/guiTask.cpp | 625 ++-- main/Application/Tasks/GUI/guiTask.h | 14 +- main/Application/Tasks/Lepton/leptonTask.cpp | 360 +- main/Application/Tasks/Lepton/leptonTask.h | 50 +- .../Application/Tasks/Network/networkTask.cpp | 179 +- main/Application/Tasks/Network/networkTask.h | 45 +- main/Application/Tasks/tasks.h | 1 + main/Application/application.h | 4 +- main/CMakeLists.txt | 2 +- main/Kconfig.projbuild | 53 +- main/idf_component.yml | 6 + main/main.cpp | 18 +- partitions.csv | 5 +- platformio.ini | 2 +- sdkconfig.debug | 177 +- sdkconfig.release | 3303 +++++++++++++++++ ui/PyroVision.sll | 4 +- ui/PyroVision.spj | 40 +- ui/PyroVision_events.py | 8 + ui/project.info | 4 +- 126 files changed, 16194 insertions(+), 4201 deletions(-) create mode 100644 docs/DevicesTask.adoc create mode 100644 docs/GUITask.adoc create mode 100644 docs/HTTPServer.adoc create mode 100644 docs/LeptonTask.adoc create mode 100644 docs/MemoryManager.adoc create mode 100644 docs/NetworkTask.adoc create mode 100644 docs/USBManager.adoc create mode 100644 docs/VISAServer.adoc create mode 100644 docs/index.adoc create mode 100644 main/Application/Manager/Devices/PCA9633DP1/pca9633dp1.cpp create mode 100644 main/Application/Manager/Devices/PCA9633DP1/pca9633dp1.h rename main/Application/Manager/Devices/{PortExpander/portexpander.cpp => PCAL6416AHF/pcal6416ahf.cpp} (66%) create mode 100644 main/Application/Manager/Devices/PCAL6416AHF/pcal6416ahf.h delete mode 100644 main/Application/Manager/Devices/PortExpander/portexpander.h delete mode 100644 main/Application/Manager/Devices/RTC/rtc.h rename main/Application/Manager/Devices/{RTC/rtc.cpp => RV8263-C8/rv8263c8.cpp} (69%) create mode 100644 main/Application/Manager/Devices/RV8263-C8/rv8263c8.h create mode 100644 main/Application/Manager/Devices/TMP117/tmp117.cpp create mode 100644 main/Application/Manager/Devices/TMP117/tmp117.h create mode 100644 main/Application/Manager/Devices/devicesTypes.h create mode 100644 main/Application/Manager/Memory/memoryManager.cpp create mode 100644 main/Application/Manager/Memory/memoryManager.h create mode 100644 main/Application/Manager/Memory/memoryTypes.h rename main/Application/Manager/Network/Server/{ => HTTP}/http_server.cpp (81%) rename main/Application/Manager/Network/Server/{ => HTTP}/http_server.h (96%) rename main/Application/Manager/Network/Server/{websocket_handler.cpp => WebSocket/websocket.cpp} (55%) rename main/Application/Manager/Network/Server/{websocket_handler.h => WebSocket/websocket.h} (64%) delete mode 100644 main/Application/Manager/Network/Server/Websocket.md delete mode 100644 main/Application/Manager/SD/sdManager.cpp delete mode 100644 main/Application/Manager/SD/sdManager.h rename main/Application/Manager/Time/{time_types.h => timeTypes.h} (87%) create mode 100644 main/Application/Manager/USB/descriptors.cpp create mode 100644 main/Application/Manager/USB/descriptors.h create mode 100644 main/Application/Manager/USB/usbManager.cpp create mode 100644 main/Application/Manager/USB/usbManager.h create mode 100644 main/Application/Manager/USB/usbTypes.h create mode 100644 main/Application/Tasks/Camera/cameraTask.cpp create mode 100644 main/Application/Tasks/Camera/cameraTask.h create mode 100644 main/Application/Tasks/GUI/Private/guiImageSave.cpp rename main/Application/{Manager/Devices/devices.h => Tasks/GUI/Private/guiImageSave.h} (67%) create mode 100644 sdkconfig.release diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 4d804cb..6bdb81e 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -187,30 +187,37 @@ Use Doxygen comments for **ALL** public API functions with complete documentatio ```cpp /** @brief Initialize the settings manager and load configuration from NVS. - * - * This function initializes the settings subsystem, opens the NVS namespace, - * and attempts to load stored settings. If no settings exist, default values - * are loaded from JSON or hardcoded defaults. - * - * @return ESP_OK on success - * @return ESP_ERR_NVS_NOT_FOUND if settings namespace doesn't exist - * @return ESP_ERR_NO_MEM if memory allocation fails - * @return ESP_ERR_INVALID_STATE if already initialized - * + * This function initializes the settings subsystem, opens the NVS namespace, + * and attempts to load stored settings. If no settings exist, default values + * are loaded from JSON or hardcoded defaults. * @note Must be called after NVS flash initialization. - * @note This function must be called before any other SettingsManager API calls. + * This function must be called before any other SettingsManager API calls. * @warning Not thread-safe during initialization. Call once from main task. + * @return ESP_OK on success + * ESP_ERR_NVS_NOT_FOUND if settings namespace doesn't exist + * ESP_ERR_NO_MEM if memory allocation fails + * ESP_ERR_INVALID_STATE if already initialized */ esp_err_t SettingsManager_Init(void); ``` -**Mandatory documentation elements:** -- `@brief` - Short one-line description -- Detailed description paragraph explaining what the function does -- `@param` - Description for EACH parameter (include direction: in/out/inout if relevant) -- `@return` - Document ALL possible return values (one `@return` per value) -- `@note` - Important usage notes (at least one recommended) -- `@warning` - Critical warnings about misuse or side effects (if applicable) +**Mandatory documentation elements and order:** +1. `@brief` - Short description on same line or next line, followed by detailed explanation (no blank line between) +2. `@note` - Important usage notes in a single consolidated block +3. `@warning` - Critical warnings in a single consolidated block (if applicable) +4. `@param` - Description for EACH parameter (include direction: in/out/inout if relevant) +5. `@return` - Document ALL possible return values in a single consolidated block + +**CRITICAL formatting rules:** +- **NO blank lines** between @brief and description text +- **NO blank lines** between description and @note +- **NO blank lines** between @note and @warning +- **NO blank lines** between @warning and @param +- **NO blank lines** between @param and @return +- All @return values in ONE block with continuation indentation +- All @note statements in ONE block with continuation indentation +- All @warning statements in ONE block with continuation indentation +- Continuation lines aligned with 20 spaces of indentation #### Incomplete Documentation is NOT Acceptable @@ -222,24 +229,43 @@ esp_err_t SettingsManager_Init(void); */ ``` -✅ **Complete:** +❌ **Wrong order (return before note):** ```cpp -/** @brief Set WiFi credentials and update configuration. - * - * Updates the WiFi SSID and password in RAM and posts a SETTINGS_EVENT_WIFI_CHANGED - * event. Changes are not persisted until SettingsManager_Save() is called. +/** @brief Set WiFi credentials. + * @param p_SSID SSID string + * @param p_Pass Password string + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if parameters invalid + * @note Changes not persisted until Save() called. + */ +``` + +❌ **Blank lines between blocks:** +```cpp +/** @brief Set WiFi credentials. * - * @param p_SSID Pointer to null-terminated SSID string (max 32 chars) - * @param p_Pass Pointer to null-terminated password string (max 64 chars) + * @param p_SSID SSID string * * @return ESP_OK on success - * @return ESP_ERR_INVALID_ARG if p_SSID or p_Pass is NULL - * @return ESP_ERR_INVALID_ARG if strings exceed maximum length - * @return ESP_ERR_INVALID_STATE if SettingsManager not initialized * + * @note Changes not persisted. + */ +``` + +✅ **Complete and correctly formatted:** +```cpp +/** @brief Set WiFi credentials and update configuration. + * Updates the WiFi SSID and password in RAM and posts a SETTINGS_EVENT_WIFI_CHANGED + * event. Changes are not persisted until SettingsManager_Save() is called. * @note Call SettingsManager_Save() to persist changes to NVS. - * @note This function is thread-safe. + * This function is thread-safe. * @warning Password is stored in plain text in NVS. + * @param p_SSID Pointer to null-terminated SSID string (max 32 chars) + * @param p_Pass Pointer to null-terminated password string (max 64 chars) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_SSID or p_Pass is NULL + * ESP_ERR_INVALID_ARG if strings exceed maximum length + * ESP_ERR_INVALID_STATE if SettingsManager not initialized */ esp_err_t SettingsManager_SetWiFi(const char *p_SSID, const char *p_Pass); ``` @@ -541,10 +567,138 @@ docs/ #### Documentation Update Pattern -1. **Update Code First**: Make your code changes -2. **Update Documentation**: Modify the relevant `.adoc` file(s) -3. **Keep in Sync**: Ensure examples, function signatures, and descriptions match the code exactly -4. **Test Documentation**: Verify that code examples in documentation still compile and work +**MANDATORY WORKFLOW**: When making ANY code changes that affect public APIs or module behavior, you MUST update the documentation simultaneously. + +1. **Identify Affected Documentation**: Use the Module-to-Documentation Mapping table above to find the corresponding `.adoc` file(s) +2. **Update Code First**: Make your code changes in the source files +3. **Update Documentation Immediately**: In the SAME session/commit, update the `.adoc` file(s): + - Update function signatures if changed + - Update parameter descriptions + - Update return value documentation + - Update code examples to match new behavior + - Add new sections for new features + - Update diagrams if architecture changed +4. **Verify Consistency**: Ensure documentation exactly matches the code +5. **Test Examples**: Verify that code examples in documentation still compile and work + +**CRITICAL**: Do NOT defer documentation updates to a later time. Documentation MUST be updated in the same editing session as the code change. + +#### Automatic Documentation Update Rules + +When you modify code, you MUST automatically update the corresponding AsciiDoc documentation according to these rules: + +**1. Function Signature Changes:** +```cpp +// If you change this in the header: +esp_err_t MyModule_DoSomething(uint8_t *p_Data, size_t Size, bool NewParam); +``` + +**You MUST update the corresponding `.adoc` file:** +```asciidoc +=== MyModule_DoSomething() + +[source,c] +---- +esp_err_t MyModule_DoSomething(uint8_t *p_Data, size_t Size, bool NewParam); +---- + +**Parameters:** + +* `p_Data` - Pointer to data buffer (must not be NULL) +* `Size` - Size of data buffer in bytes +* `NewParam` - [ADD DESCRIPTION OF NEW PARAMETER] + +[Rest of documentation...] +---- +``` + +**2. Adding New Functions:** + +When adding a new public API function, you MUST add a complete documentation section to the appropriate `.adoc` file: + +```asciidoc +=== NewModule_NewFunction() + +[source,c] +---- +esp_err_t NewModule_NewFunction(void); +---- + +[Brief description of what the function does] + +**Return Values:** + +* `ESP_OK` - Success +* [List all possible return values] + +**Thread Safety:** [Describe thread-safety characteristics] + +**Example:** +[source,c] +---- +[Provide working code example] +---- +``` + +**3. Behavior Changes:** + +If you change how a function behaves (even without changing the signature), update the description and notes in the `.adoc` file. + +**4. New Events or Types:** + +When adding new event types, data structures, or enums, document them in the appropriate sections of the `.adoc` file. + +#### Documentation Update Checklist + +After every code change that affects public APIs, verify: + +``` +☐ Identified corresponding .adoc file(s) using Module-to-Documentation Mapping +☐ Updated function signatures in documentation to match code +☐ Updated or added parameter descriptions +☐ Updated or added return value documentation +☐ Updated code examples to reflect changes +☐ Added new sections for new functions/features +☐ Updated architecture diagrams if structure changed +☐ Verified consistency between code and documentation +☐ Checked that examples compile and run correctly +``` + +#### Common Documentation Scenarios + +**Scenario 1: Adding a new parameter to an existing function** + +1. Update header file with new parameter + Doxygen documentation +2. Open corresponding `.adoc` file +3. Find the function's documentation section +4. Update the function signature in the `[source,c]` block +5. Add the new parameter to the "Parameters" list +6. Update any example code to include the new parameter + +**Scenario 2: Adding a completely new module** + +1. Create the new module source files +2. Create a new `.adoc` file in `docs/` (e.g., `docs/NewModule.adoc`) +3. Use existing module documentation as a template (copy structure from `SettingsManager.adoc` or similar) +4. Document all public APIs, data structures, and usage examples +5. Add a link to the new documentation in `docs/index.adoc` +6. Update the Module-to-Documentation Mapping in this file + +**Scenario 3: Changing function behavior without signature change** + +1. Modify the function implementation +2. Open corresponding `.adoc` file +3. Update the function's description to reflect new behavior +4. Update notes, warnings, or examples as needed +5. Add version information if significant change ("*Changed in v1.1.0:* ...") + +**Scenario 4: Removing or deprecating a function** + +1. Mark function as deprecated in header (if deprecating) or remove (if deleting) +2. Update `.adoc` file: + - If deprecating: Add a "**DEPRECATED**" notice and suggest alternative + - If removing: Delete the function's documentation section entirely +3. Update examples that used the removed function #### Module-to-Documentation Mapping @@ -552,13 +706,18 @@ docs/ |--------------|-------------------| | `Manager/Settings/` | `SettingsManager.adoc` | | `Manager/Network/` | `NetworkManager.adoc` | +| `Manager/Network/Server/HTTP/` | `HTTPServer.adoc` | +| `Manager/Network/Server/VISA/` | `VISAServer.adoc` | +| `Manager/Network/Server/WebSocket/` | `HTTPServer.adoc` (WebSocket section) | | `Manager/Devices/` | `DeviceManager.adoc` | | `Manager/Time/` | `TimeManager.adoc` | -| `Manager/SD/` | `SDManager.adoc` | +| `Manager/Memory/` | `MemoryManager.adoc` | +| `Manager/USB/` | `USBManager.adoc` | | `Tasks/Lepton/` | `LeptonTask.adoc` | | `Tasks/GUI/` | `GUITask.adoc` | | `Tasks/Network/` | `NetworkTask.adoc` | -| `Manager/Network/VISA/` | `VISAServer.adoc` | +| `Tasks/Devices/` | `DevicesTask.adoc` | +| `main.cpp` (main application) | `index.adoc` (overview section) | #### Documentation Style Guidelines @@ -651,10 +810,15 @@ Documentation is automatically built and deployed via GitHub Actions workflow (` - Check mutex/semaphore release in all paths (including errors) #### 4. Documentation Synchronization -- Update function documentation if signatures changed +- **MANDATORY**: Update corresponding `.adoc` documentation file when changing any public API +- Use Module-to-Documentation Mapping table to identify which `.adoc` file to update +- Update function signatures if changed - Update parameter descriptions if behavior changed +- Update return value documentation - Verify code examples in documentation still compile -- Update relevant `.adoc` files in `docs/` directory +- Add new documentation sections for new functions +- Update architecture diagrams if module structure changed +- **Do NOT skip documentation updates** - they must be done in the same session as code changes **Example validation checklist for each change:** ``` @@ -665,7 +829,10 @@ Documentation is automatically built and deployed via GitHub Actions workflow (` ☐ All return values and parameters documented ☐ Error handling implemented for all ESP-IDF calls ☐ Mutex/semaphore properly released in all code paths -☐ Related documentation (.adoc files) updated +☐ Related documentation (.adoc files) updated using Module-to-Documentation Mapping +☐ New functions have complete documentation sections in .adoc files +☐ Function signatures in .adoc files match code exactly +☐ Code examples in documentation updated and verified ☐ Code formatted with AStyle (scripts/format.py) ☐ Run static analysis if available (pio check) ``` diff --git a/.github/workflows/firmware.yml b/.github/workflows/firmware.yml index 5c6e530..ea7486d 100644 --- a/.github/workflows/firmware.yml +++ b/.github/workflows/firmware.yml @@ -39,11 +39,15 @@ jobs: build: runs-on: ubuntu-22.04 - + + strategy: + matrix: + build_type: [debug, release] + steps: - uses: actions/checkout@v6 with: - fetch-depth: 0 + submodules: recursive - uses: actions/cache@v4 with: @@ -66,11 +70,45 @@ jobs: - name: Get release version run: | - BRANCH_NAME="${GITHUB_REF_NAME}" - echo "BRANCH_NAME=${BRANCH_NAME}" - BASE_VERSION="${BRANCH_NAME%%_*}" - - IFS='.' read -r MAJOR MINOR BUILD <<< "${BASE_VERSION}" + # Try to extract version from commit message (format: Major.Minor.Revision-Dev or Major.Minor-Dev) + COMMIT_MSG=$(git log -1 --pretty=%B) + VERSION=$(echo "$COMMIT_MSG" | grep -oP '(?<=^|\s)([0-9]+\.[0-9]+(\.[0-9]+)?(-[a-zA-Z0-9]+)?)(?=\s|$)' | head -n1) + + # If not found in commit message, try branch name + if [ -z "$VERSION" ]; then + BRANCH_NAME="${GITHUB_REF_NAME}" + echo "No version in commit message, trying branch name: ${BRANCH_NAME}" + VERSION=$(echo "$BRANCH_NAME" | grep -oP '([0-9]+\.[0-9]+(\.[0-9]+)?(-[a-zA-Z0-9]+)?)' | head -n1) + fi + + # If still not found, use git describe as fallback + if [ -z "$VERSION" ]; then + echo "No version in branch name, using git describe" + VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "0.0.0-$(git rev-parse --short HEAD)") + fi + + echo "Detected version: ${VERSION}" + + # Parse version components (handle both Major.Minor and Major.Minor.Revision) + if [[ "$VERSION" =~ ^([0-9]+)\.([0-9]+)(\.([0-9]+))?(-(.+))? ]]; then + MAJOR="${BASH_REMATCH[1]}" + MINOR="${BASH_REMATCH[2]}" + BUILD="${BASH_REMATCH[4]:-0}" # Default to 0 if revision not specified + SUFFIX="${BASH_REMATCH[6]}" + + # Reconstruct version string + if [ -n "$SUFFIX" ]; then + BASE_VERSION="${MAJOR}.${MINOR}.${BUILD}-${SUFFIX}" + else + BASE_VERSION="${MAJOR}.${MINOR}.${BUILD}" + fi + else + echo "Warning: Could not parse version, using defaults" + MAJOR="0" + MINOR="0" + BUILD="0" + BASE_VERSION="0.0.0-unknown" + fi echo "MAJOR=${MAJOR}" >> ${GITHUB_ENV} echo "MINOR=${MINOR}" >> ${GITHUB_ENV} @@ -88,16 +126,21 @@ jobs: - name: Build PlatformIO Project run: | - pio run + pio run -e ${{ matrix.build_type }} - name: Prepare upload run: | - mkdir -p debug + mkdir -p ${{ matrix.build_type }} + cp .pio/build/${{ matrix.build_type }}/bootloader.bin ${{ matrix.build_type }}/bootloader.bin + cp .pio/build/${{ matrix.build_type }}/partitions.bin ${{ matrix.build_type }}/partitions.bin + cp .pio/build/${{ matrix.build_type }}/ota_data_initial.bin ${{ matrix.build_type }}/ota_data_initial.bin + cp .pio/build/${{ matrix.build_type }}/firmware.bin ${{ matrix.build_type }}/firmware.bin + cp .pio/build/${{ matrix.build_type }}/firmware.elf ${{ matrix.build_type }}/firmware.elf - name: Upload Firmware uses: actions/upload-artifact@v4.3.3 with: - name: debug + name: ${{ matrix.build_type }} path: | - debug + ${{ matrix.build_type }} if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index a44760d..bdf53fc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ .vscode/ipch *.old *.lock - managed_components/ */backup/ */Font-Awesome/* diff --git a/.gitmodules b/.gitmodules index 748d293..b38dadc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "ui/assets/Font-Awesome"] path = ui/assets/Font-Awesome url = https://github.com/FortAwesome/Font-Awesome.git +[submodule "components/ESP32-Lepton"] + path = components/ESP32-Lepton + url = https://github.com/Kampi/ESP32-Lepton.git diff --git a/CMakeLists.txt b/CMakeLists.txt index e15039d..ecfa115 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,19 @@ cmake_minimum_required(VERSION 3.16.0) +# Get version from git describe +execute_process( + COMMAND git describe --always --tags --dirty + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE PROJECT_VER + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +# Fallback if git not available +if(NOT PROJECT_VER) + set(PROJECT_VER "X.Y.Z-dev") +endif() + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(PyroVision) diff --git a/components/ESP32-Lepton b/components/ESP32-Lepton index 0cafcb1..b2b6de8 160000 --- a/components/ESP32-Lepton +++ b/components/ESP32-Lepton @@ -1 +1 @@ -Subproject commit 0cafcb18a299bc3cb9daad1d7fd99501ec40cd16 +Subproject commit b2b6de80d7e34c4b8f8287e5b95ede733591ad3c diff --git a/data/settings_default.json b/data/settings_default.json index 2519d1b..52b20db 100644 --- a/data/settings_default.json +++ b/data/settings_default.json @@ -1,4 +1,5 @@ { + "version" : 1, "lepton" : { "emissivity" : [ { diff --git a/docs/DevicesTask.adoc b/docs/DevicesTask.adoc new file mode 100644 index 0000000..d3c5a56 --- /dev/null +++ b/docs/DevicesTask.adoc @@ -0,0 +1,217 @@ += PyroVision Devices Task Documentation +Daniel Kampert +v1.0, 2026-02-09 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The Devices Task monitors peripheral hardware including battery voltage (via ADC), RTC (Real-Time Clock), port expander, and other sensors. It performs periodic polling and posts events when significant changes occur. + +=== Key Features + +* *Battery Monitoring*: ADC-based voltage measurement +* *RTC Management*: Real-Time Clock synchronization +* *Port Expander*: GPIO expansion and monitoring +* *Sensor Polling*: Periodic updates of device states +* *Event Generation*: Notifications for battery low, RTC sync, etc. + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Tasks/Devices/ +├── devicesTask.h # Public API +└── devicesTask.cpp # Implementation +---- + +=== Task Architecture + +* *Task Name*: `"DevicesTask"` +* *Priority*: Low (typically `tskIDLE_PRIORITY + 1`) +* *Stack Size*: 4 KB +* *Core Affinity*: Any (typically Core 0) +* *Polling Interval*: 1 second (configurable) + +--- + +== Public API + +=== DevicesTask_Init() + +[source,c] +---- +esp_err_t DevicesTask_Init(void); +---- + +Initializes the devices task. + +**Return Values:** + +* `ESP_OK` - Initialization successful +* `ESP_ERR_NO_MEM` - Memory allocation failed +* `ESP_ERR_INVALID_STATE` - Already initialized + +--- + +=== DevicesTask_Deinit() + +[source,c] +---- +void DevicesTask_Deinit(void); +---- + +Deinitializes the devices task. + +--- + +=== DevicesTask_Start() + +[source,c] +---- +esp_err_t DevicesTask_Start(App_Context_t *p_AppContext); +---- + +Starts the devices monitoring task. + +**Parameters:** + +* `p_AppContext` - Pointer to application context + +**Return Values:** + +* `ESP_OK` - Task started +* `ESP_ERR_INVALID_ARG` - NULL pointer +* `ESP_ERR_INVALID_STATE` - Not initialized or already running + +--- + +=== DevicesTask_Stop() + +[source,c] +---- +esp_err_t DevicesTask_Stop(void); +---- + +Stops the devices task. + +--- + +=== DevicesTask_isRunning() + +[source,c] +---- +bool DevicesTask_isRunning(void); +---- + +Checks if the task is running. + +--- + +## Monitored Devices + +=== 1. Battery Monitor (ADC) + +**Functionality:** + +* Measures battery voltage via ADC +* Calculates battery percentage +* Detects low battery condition + +**Events:** + +* `DEVICE_EVENT_BATTERY_LOW` - Battery below threshold (e.g., 10%) +* `DEVICE_EVENT_BATTERY_CRITICAL` - Battery critically low (e.g., 5%) + +=== 2. RTC (Real-Time Clock) + +**Functionality:** + +* Monitors RTC synchronization status +* Checks RTC battery +* Validates time accuracy + +**Events:** + +* `DEVICE_EVENT_RTC_SYNC` - RTC synchronized with NTP +* `DEVICE_EVENT_RTC_BATTERY_LOW` - RTC backup battery low + +=== 3. Port Expander + +**Functionality:** + +* Reads GPIO states from I2C port expander +* Detects button presses +* Controls external LEDs + +--- + +== Task Operation + +=== Polling Loop + +[source,c] +---- +while (running) { + // 1. Read battery voltage + float BatteryVoltage = ADC_ReadVoltage(ADC_CHANNEL_BATTERY); + uint8_t BatteryPercent = CalculateBatteryPercent(BatteryVoltage); + + if (BatteryPercent < LOW_BATTERY_THRESHOLD) { + esp_event_post(DEVICE_EVENTS, DEVICE_EVENT_BATTERY_LOW, + &BatteryPercent, sizeof(BatteryPercent), 0); + } + + // 2. Check RTC status + if (RTC_IsTimeValid()) { + // Update system time if necessary + } + + // 3. Read port expander inputs + uint8_t GPIO_States = PortExpander_ReadAll(); + ProcessGPIOChanges(GPIO_States); + + vTaskDelay(pdMS_TO_TICKS(1000)); // 1 second interval +} +---- + +--- + +== Dependencies + +=== Required Managers + +* *Device Manager*: ADC, RTC, I2C port expander initialization +* *Settings Manager*: Device configuration (thresholds, intervals) + +--- + +## Configuration + +=== Battery Thresholds + +* Low Battery: 10% (configurable) +* Critical Battery: 5% (configurable) +* Voltage Range: 3.0V - 4.2V (Li-Po) + +=== Polling Interval + +* Default: 1000 ms +* Range: 100 ms - 10000 ms + +--- + +== Related Documentation + +* link:DeviceManager.adoc[Device Manager Documentation] + +--- + +**Last Updated**: February 9, 2026 + +**Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/docs/GUITask.adoc b/docs/GUITask.adoc new file mode 100644 index 0000000..a92b4a8 --- /dev/null +++ b/docs/GUITask.adoc @@ -0,0 +1,580 @@ += PyroVision GUI Task Documentation +Daniel Kampert +v1.0, 2026-02-09 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The GUI Task is responsible for rendering the user interface using LVGL (Light and Versatile Graphics Library) and managing user interactions with the touch display. It displays thermal camera frames, settings menus, system information, and handles touch input for ROI (Region of Interest) editing and navigation. + +=== Key Features + +* *LVGL Integration*: Hardware-accelerated graphics rendering +* *Thermal Image Display*: Real-time display of processed Lepton camera frames +* *Touch Interface*: Interactive settings and configuration screens +* *ROI Editor*: Visual overlay for adjusting spotmeter regions +* *Image Capture*: Save thermal images as BMP files to SD card +* *Multi-Screen Layout*: Main view, menu, settings, and info screens +* *Event-Driven UI*: Responsive to settings changes and system events + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Tasks/GUI/ +├── guiTask.h # Public API +├── guiTask.cpp # Main implementation +├── Export/ # Auto-generated from SquareLine Studio +│ ├── ui.h +│ ├── ui_events.h +│ ├── ui_events.cpp +│ ├── ui_helpers.h +│ └── screens/ +│ ├── ui_Info.h # Info screen +│ ├── ui_Main.h # Main thermal view +│ ├── ui_Menu.h # Settings menu +│ └── ui_Splash.h # Boot splash screen +├── UI/ # Custom UI components +│ ├── ui_Settings.h +│ ├── ui_Settings.cpp +│ └── Private/ +│ ├── ui_Settings_Events.h +│ └── ui_Settings_Events.cpp +└── Private/ + ├── guiHelper.h + └── guiHelper.cpp # Internal helper functions +---- + +=== Task Architecture + +The GUI Task runs as a FreeRTOS task with the following characteristics: + +* *Task Name*: `"GUITask"` +* *Priority*: Configurable (typically `tskIDLE_PRIORITY + 2`) +* *Stack Size*: 16 KB (to accommodate LVGL's stack requirements) +* *Core Affinity*: Typically pinned to Core 1 (APP CPU) + +=== LVGL Integration + +The task integrates LVGL with the ESP32-S3's display controller: + +* *Display Driver*: ILI9341 SPI LCD (320x240 pixels) +* *Touch Driver*: GT911 capacitive touch controller +* *Refresh Rate*: 30 FPS nominal +* *Double Buffering*: Used for smooth rendering +* *Tick Handler*: LVGL tick driven by FreeRTOS timer + +--- + +== Public API + +=== GUI_Task_Init() + +[source,c] +---- +esp_err_t GUI_Task_Init(void); +---- + +Initializes the GUI subsystem including LVGL library, display driver, touch driver, and UI screens. + +**Initialization Steps:** + +1. Initialize LVGL library +2. Configure display driver (ILI9341) +3. Initialize touch input driver (GT911) +4. Create LVGL display and input device objects +5. Load UI screens from SquareLine Studio export +6. Register event handlers for system events + +**Return Values:** + +* `ESP_OK` - GUI subsystem initialized successfully +* `ESP_ERR_NO_MEM` - Memory allocation failed +* `ESP_FAIL` - Display or touch driver initialization failed +* `ESP_ERR_INVALID_STATE` - Already initialized + +**Thread Safety:** Not thread-safe. Must be called once during system initialization. + +**Example:** +[source,c] +---- +esp_err_t Error = GUI_Task_Init(); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize GUI: %d", Error); + return Error; +} +---- + +--- + +=== GUI_Task_Deinit() + +[source,c] +---- +void GUI_Task_Deinit(void); +---- + +Deinitializes the GUI subsystem, freeing all allocated resources. + +**Actions:** + +* Stops GUI task if running +* Frees LVGL objects and screens +* Deinitializes display and touch drivers +* Releases allocated memory + +**Thread Safety:** Not thread-safe. Call only during shutdown. + +--- + +=== GUI_Task_Start() + +[source,c] +---- +esp_err_t GUI_Task_Start(App_Context_t *p_AppContext); +---- + +Starts the GUI FreeRTOS task. + +**Parameters:** + +* `p_AppContext` - Pointer to application context structure (must not be NULL) + +**Return Values:** + +* `ESP_OK` - Task started successfully +* `ESP_ERR_INVALID_ARG` - NULL pointer passed +* `ESP_ERR_INVALID_STATE` - GUI not initialized or already running +* `ESP_ERR_NO_MEM` - Task creation failed + +**Thread Safety:** Thread-safe. Can be called from any task. + +**Example:** +[source,c] +---- +App_Context_t AppContext; +esp_err_t Error = GUI_Task_Start(&AppContext); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to start GUI task: %d", Error); +} +---- + +--- + +=== GUI_Task_Stop() + +[source,c] +---- +esp_err_t GUI_Task_Stop(void); +---- + +Stops the GUI task. + +**Return Values:** + +* `ESP_OK` - Task stopped successfully +* `ESP_ERR_INVALID_STATE` - Task not running + +**Thread Safety:** Thread-safe. Can be called from any task. + +**Note:** This function blocks until the task has fully stopped. + +--- + +=== GUI_Task_isRunning() + +[source,c] +---- +bool GUI_Task_isRunning(void); +---- + +Checks if the GUI task is currently active. + +**Return Values:** + +* `true` - Task is running +* `false` - Task is not running + +**Thread Safety:** Thread-safe. + +--- + +=== GUI_Toggle_ROI_EditMode() + +[source,c] +---- +void GUI_Toggle_ROI_EditMode(void); +---- + +Toggles the ROI (Region of Interest) edit mode on the main thermal display. + +**Behavior:** + +* When enabled: Displays a draggable rectangle overlay representing the spotmeter region +* User can touch and drag to reposition the ROI +* Updates are applied to camera spotmeter settings in real-time +* Visual feedback with colored rectangle + +**Thread Safety:** Should be called from GUI context or via event system. + +**Example:** +[source,c] +---- +// Called from button press event +GUI_Toggle_ROI_EditMode(); +---- + +--- + +=== GUI_SaveThermalImage() + +[source,c] +---- +esp_err_t GUI_SaveThermalImage(void); +---- + +Captures the current thermal image and saves it to the SD card as a BMP file. + +**File Naming:** + +* Format: `THERMAL_YYYYMMDD_HHMMSS.BMP` +* Example: `THERMAL_20260209_143022.BMP` + +**Return Values:** + +* `ESP_OK` - Image saved successfully +* `ESP_ERR_INVALID_STATE` - Filesystem locked (USB MSC active) +* `ESP_ERR_NO_MEM` - No frame available or memory allocation failed +* `ESP_FAIL` - File write operation failed + +**Thread Safety:** Thread-safe. Can be called from any task. + +**Storage Location:** `/sdcard/` (SD card root directory) + +**Note:** Function checks if filesystem is locked by USB Mass Storage Class before attempting write. + +**Example:** +[source,c] +---- +esp_err_t Error = GUI_SaveThermalImage(); +if (Error == ESP_ERR_INVALID_STATE) { + ESP_LOGW(TAG, "Cannot save: USB MSC active"); +} else if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to save image: %d", Error); +} +---- + +--- + +== Event System + +=== GUI Events + +The GUI Task posts events to the system event loop: + +[source,c] +---- +ESP_EVENT_DECLARE_BASE(GUI_EVENTS); +---- + +**Event Types:** + +Currently, the GUI Task primarily *consumes* events rather than posting them: + +* `SETTINGS_EVENTS` - Updates UI when settings change +* `NETWORK_EVENTS` - Updates WiFi status indicators +* `LEPTON_EVENTS` - Receives frame updates for display + +--- + +== UI Screens + +=== 1. Splash Screen (`ui_Splash`) + +* Displayed during boot +* Shows PyroVision logo +* Duration: 2-3 seconds +* Transitions to Main screen + +=== 2. Main Screen (`ui_Main`) + +The primary thermal imaging view: + +* *Thermal Image Canvas*: Full-color rendered thermal frame +* *Spotmeter Temperature*: Large numeric display of spotmeter temp +* *Min/Max Temperatures*: Scene statistics +* *ROI Overlay*: Visual spotmeter position indicator +* *Status Bar*: WiFi, USB, SD card status icons +* *Menu Button*: Access to settings and configuration + +=== 3. Menu Screen (`ui_Menu`) + +Navigation to various settings: + +* WiFi Configuration +* Camera Settings +* Display Settings +* System Information +* Return to Main + +=== 4. Info Screen (`ui_Info`) + +System information display: + +* Firmware version +* Hardware info +* Memory usage +* Uptime +* Network status + +=== 5. Settings Screens (`ui_Settings_*`) + +Dynamic settings panels (custom implementation): + +* WiFi SSID/Password entry +* Camera ROI configuration +* AGC settings +* Emissivity presets +* Display brightness + +--- + +== Thermal Image Rendering + +=== Frame Processing Pipeline + +[source] +---- +┌──────────────────┐ +│ Lepton Task │ +│ (Raw 14-bit) │ +└────────┬─────────┘ + │ + │ Post frame via queue + ↓ +┌──────────────────┐ +│ GUI Task │ +│ Receive Frame │ +└────────┬─────────┘ + │ + │ Apply colormap + ↓ +┌──────────────────┐ +│ RGB565 Conversion│ +│ (320x240 scaled) │ +└────────┬─────────┘ + │ + │ LVGL Canvas Update + ↓ +┌──────────────────┐ +│ Display (ILI9341)│ +│ SPI DMA Transfer │ +└──────────────────┘ +---- + +**Frame Format:** + +* Input: 14-bit RAW thermal data (80x60 or 160x120 depending on Lepton model) +* Processing: Apply colormap (Iron, Rainbow, etc.) +* Output: RGB565 (16-bit color) +* Scaling: Bilinear interpolation to fit display + +**Performance:** + +* Target: 8.6 Hz frame rate (Lepton 3.5 native rate) +* Actual: ~8-10 FPS depending on UI complexity +* Latency: <100ms from capture to display + +--- + +== ROI (Region of Interest) Editor + +=== Interactive ROI Adjustment + +The GUI allows visual adjustment of the camera's spotmeter ROI: + +**Interaction:** + +1. User presses "Edit ROI" button +2. Colored rectangle overlay appears on thermal image +3. User touches and drags rectangle to reposition +4. Release updates camera spotmeter settings +5. Press "Done" to exit edit mode + +**Implementation:** + +* LVGL drag event handler +* Real-time coordinate translation (display → camera pixels) +* Boundary checking to keep ROI within frame +* Visual feedback during dragging + +**Constraints:** + +* Minimum ROI size: 4x4 pixels (camera limitation) +* ROI must be fully within frame boundaries +* Only one ROI editable at a time (typically spotmeter) + +--- + +== Image Capture (BMP Export) + +=== BMP File Format + +Saved thermal images use the following format: + +* *Format*: BMP (Windows Bitmap) +* *Color Depth*: 24-bit RGB +* *Resolution*: 320x240 pixels (native display resolution) +* *Compression*: None (uncompressed) +* *Color Space*: sRGB + +**File Structure:** + +[source] +---- +BMP Header (14 bytes) +DIB Header (40 bytes) +Pixel Data (320 x 240 x 3 bytes = 230,400 bytes) +Total: ~230 KB per image +---- + +**Memory Considerations:** + +* Temporary buffer allocated from PSRAM (if available) +* Freed immediately after file write +* SD card must have sufficient space + +--- + +== Dependencies + +=== Required Managers + +* *Device Manager*: Display and touch controller initialization +* *Settings Manager*: UI configuration (brightness, theme, etc.) +* *Memory Manager*: Buffer allocation for frame processing +* *Time Manager*: Timestamp for saved images + +=== Required Tasks + +* *Lepton Task*: Provides thermal frames for display + +=== Libraries + +* *LVGL* (v8.3+): Graphics library +* *ESP-IDF LCD/Touch*: Display and touch drivers +* *ESP-IDF VFS/FatFS*: File system for BMP export + +--- + +== Configuration + +=== Kconfig Options + +The GUI can be configured via menuconfig: + +* `GUI_TASK_PRIORITY` - Task priority +* `GUI_TASK_STACK_SIZE` - Stack size (default: 16384) +* `GUI_TASK_CORE` - CPU core affinity (0 or 1) +* `GUI_LVGL_BUFFER_SIZE` - LVGL draw buffer size + +=== Compile-Time Configuration + +Display and touch driver parameters are configured in Device Manager. + +--- + +== Threading and Synchronization + +=== Thread Safety + +* **Task-Internal**: GUI operations are thread-safe when called from GUI task context +* **External Calls**: API functions (`GUI_Task_Start()`, `GUI_SaveThermalImage()`) use mutexes for thread safety +* **Event Handlers**: GUI event handlers run in event loop context + +=== Critical Sections + +* Frame buffer access (protected by semaphore) +* Settings updates (coordinated via event system) +* File system access (checked for USB lock) + +--- + +== Troubleshooting + +=== Common Issues + +**Display not updating:** + +* Check LVGL tick handler is running +* Verify SPI bus configuration +* Ensure display backlight is enabled + +**Touch not responding:** + +* Verify GT911 I2C address (0x5D or 0x14) +* Check touch interrupt GPIO configuration +* Confirm touch calibration + +**Frame rate too low:** + +* Reduce LVGL animation complexity +* Enable SPI DMA for display +* Allocate draw buffers in PSRAM + +**Image save fails:** + +* Check SD card is mounted +* Verify filesystem not locked (USB MSC inactive) +* Ensure sufficient free space on SD card + +--- + +== Performance Optimization + +=== Tips for Smooth UI + +* Use double buffering for LVGL +* Enable SPI DMA transfers +* Minimize LVGL object count on screen +* Use cached images for static content +* Pin GUI task to dedicated core + +=== Memory Optimization + +* Allocate large buffers (frame buffers) in PSRAM +* Use LVGL built-in image cache +* Release unused screens from memory +* Monitor heap fragmentation + +--- + +== Future Enhancements + +* Multiple colormap options (Iron, Rainbow, Grayscale) +* Histogram display +* Temperature profile graphs +* Multi-ROI visual editing +* Touch gestures (pinch-to-zoom) +* Screen rotation support + +--- + +== Related Documentation + +* link:LeptonTask.adoc[Lepton Task Documentation] +* link:DeviceManager.adoc[Device Manager Documentation] +* link:SettingsManager.adoc[Settings Manager Documentation] +* link:MemoryManager.adoc[Memory Manager Documentation] + +--- + +**Last Updated**: February 9, 2026 + +**Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/docs/HTTPServer.adoc b/docs/HTTPServer.adoc new file mode 100644 index 0000000..7cd36a0 --- /dev/null +++ b/docs/HTTPServer.adoc @@ -0,0 +1,330 @@ += PyroVision HTTP Server Documentation +Daniel Kampert +v1.0, 2026-02-09 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The HTTP Server provides a web-based interface for viewing thermal imagery, configuring the device, and streaming live video via WebSocket. It serves static provisioning pages for WiFi setup and exposes a REST API for configuration and telemetry. + +=== Key Features + +* *Web Interface*: HTML provisioning and configuration pages +* *REST API*: JSON-based configuration and telemetry endpoints +* *WebSocket*: Real-time thermal image streaming +* *CORS Support*: Cross-origin resource sharing for web apps +* *Captive Portal*: WiFi provisioning without app +* *OTA Updates*: Firmware upload via HTTP POST + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Manager/Network/Server/HTTP/ +├── http_server.h # Public API +└── http_server.cpp # Implementation + +main/Application/Manager/Network/Server/WebSocket/ +├── websocket.h # WebSocket API +└── websocket.cpp # WebSocket implementation + +main/Application/Manager/Network/Server/ImageEncoder/ +├── imageEncoder.h # Image encoder +└── imageEncoder.cpp # JPEG compression +---- + +--- + +== Public API + +=== HTTP_Server_Init() + +[source,c] +---- +esp_err_t HTTP_Server_Init(const Network_HTTP_Server_Config_t *p_Config); +---- + +Initializes the HTTP server with configuration. + +**Configuration:** + +[source,c] +---- +typedef struct { + uint16_t Port; // Port number (default: 80) + uint16_t WSPingIntervalSec; // WebSocket ping interval (default: 30) + uint8_t MaxClients; // Max concurrent clients (default: 5) +} Network_HTTP_Server_Config_t; +---- + +--- + +=== HTTP_Server_Start() + +[source,c] +---- +esp_err_t HTTP_Server_Start(void); +---- + +Starts the HTTP server. + +--- + +=== HTTP_Server_Stop() + +[source,c] +---- +esp_err_t HTTP_Server_Stop(void); +---- + +Stops the HTTP server and closes all connections. + +--- + +=== HTTP_Server_SetThermalFrame() + +[source,c] +---- +void HTTP_Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame); +---- + +Updates the thermal frame available for `/api/image` endpoint. + +--- + +== REST API Endpoints + +=== GET `/api/image` + +Returns the current thermal frame as JPEG image. + +**Response:** +- Content-Type: `image/jpeg` +- Body: JPEG-compressed thermal image + +**Example:** +[source,bash] +---- +curl http://192.168.1.100/api/image > thermal.jpg +---- + +--- + +=== GET `/api/telemetry` + +Returns telemetry data in JSON format. + +**Response:** +[source,json] +---- +{ + "spotmeter": 25.3, + "min": 20.1, + "max": 30.5, + "avg": 25.0, + "frame_count": 12345 +} +---- + +--- + +=== POST `/api/time` + +Sets the system time. + +**Request Body:** +[source,json] +---- +{ + "datetime": "2026-02-09T14:30:00" +} +---- + +**Response:** +[source,json] +---- +{ + "status": "ok" +} +---- + +--- + +=== POST `/api/update` + +Uploads firmware for OTA update. + +**Request:** +- Content-Type: `application/octet-stream` +- Body: Binary firmware file + +**Response:** +[source,json] +---- +{ + "status": "ok", + "message": "Update successful, rebooting..." +} +---- + +--- + +=== OPTIONS `/api/*` + +Handles CORS preflight requests. + +**Response Headers:** +[source] +---- +Access-Control-Allow-Origin: * +Access-Control-Allow-Methods: GET, POST, OPTIONS +Access-Control-Allow-Headers: Content-Type +---- + +--- + +== WebSocket API + +=== Connection + +**Endpoint:** `ws://192.168.1.100/ws` + +**Protocol:** Binary frames (JPEG-compressed thermal images) + +--- + +=== Frame Format + +Each WebSocket message contains a JPEG-compressed thermal frame: + +[source] +---- +Message Type: Binary +Frame Rate: ~8-9 Hz +Size: 5-15 KB per frame +---- + +--- + +=== JavaScript Example + +[source,javascript] +---- +const ws = new WebSocket('ws://192.168.1.100/ws'); + +ws.binaryType = 'arraybuffer'; + +ws.onmessage = (event) => { + const blob = new Blob([event.data], {type: 'image/jpeg'}); + const url = URL.createObjectURL(blob); + + const img = document.getElementById('thermal-image'); + img.src = url; +}; + +ws.onopen = () => { + console.log('WebSocket connected'); +}; + +ws.onerror = (error) => { + console.error('WebSocket error:', error); +}; + +ws.onclose = () => { + console.log('WebSocket closed'); +}; +---- + +--- + +== Provisioning Pages + +=== GET `/` + +Serves the WiFi provisioning page. + +**Features:** +- WiFi SSID scanner +- Password entry +- Connection status +- Access to device configuration + +--- + +=== GET `/logo.png` + +Serves the PyroVision logo for provisioning page. + +--- + +=== GET `/api/provision/scan` + +Scans for available WiFi networks. + +**Response:** +[source,json] +---- +{ + "networks": [ + {"ssid": "MyWiFi", "rssi": -45, "auth": "WPA2"}, + {"ssid": "GuestNet", "rssi": -67, "auth": "Open"} + ] +} +---- + +--- + +=== POST `/api/provision` + +Submits WiFi credentials. + +**Request Body:** +[source,json] +---- +{ + "ssid": "MyWiFi", + "password": "MyPassword" +} +---- + +--- + +== Captive Portal + +When in AP mode, the device implements a captive portal that redirects all HTTP requests to the provisioning page. + +**Endpoints:** +- `/generate_204` (Android) +- `/generate204` (Alternative) + +**Behavior:** +- Redirects to provisioning page (`/`) +- Allows WiFi configuration without app installation + +--- + +## Performance + +* **Max Clients**: 5 (HTTP) + 5 (WebSocket) +* **Request Latency**: <50 ms (typical) +* **WebSocket Throughput**: ~80 KB/s per client +* **Memory Usage**: ~50 KB per active connection + +--- + +== Related Documentation + +* link:NetworkTask.adoc[Network Task Documentation] +* link:NetworkManager.adoc[Network Manager Documentation] + +--- + +**Last Updated**: February 9, 2026 + +**Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/docs/LeptonTask.adoc b/docs/LeptonTask.adoc new file mode 100644 index 0000000..0f0ab8c --- /dev/null +++ b/docs/LeptonTask.adoc @@ -0,0 +1,653 @@ += PyroVision Lepton Task Documentation +Daniel Kampert +v1.0, 2026-02-09 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The Lepton Task is responsible for interfacing with the FLIR Lepton thermal camera, acquiring thermal frames, processing temperature data, calculating ROI (Region of Interest) statistics, and distributing frame data to consumers (GUI, Network, etc.). It runs as a high-priority FreeRTOS task to ensure consistent frame acquisition. + +=== Key Features + +* *Lepton Camera Interface*: SPI communication with FLIR Lepton 3.5 +* *Frame Acquisition*: Continuous capture at camera native rate (~8.6 Hz) +* *Temperature Calculation*: Conversion from RAW values to Celsius +* *ROI Processing*: Calculate min/max/average temperatures for multiple ROIs +* *Frame Distribution*: Queue-based delivery to GUI and Network tasks +* *Telemetry Generation*: Camera status and temperature statistics +* *Error Recovery*: Automatic resync on frame corruption +* *Power Management*: Camera standby and wake-up control + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Tasks/Lepton/ +├── leptonTask.h # Public API +└── leptonTask.cpp # Implementation +---- + +**Driver Integration:** + +The task uses the ESP32-Lepton component located in `components/ESP32-Lepton/`. + +=== Task Architecture + +* *Task Name*: `"LeptonTask"` +* *Priority*: High (typically `tskIDLE_PRIORITY + 4`) +* *Stack Size*: 8 KB +* *Core Affinity*: Typically Core 1 (APP CPU) +* *Frame Rate*: 8.6 Hz (Lepton 3.5 native) + +=== Data Flow + +[source] +---- +┌────────────────┐ +│ Lepton Camera │ (160x120 RAW 14-bit thermal data) +└────────┬───────┘ + │ SPI Transfer + ↓ +┌────────────────┐ +│ Lepton Task │ +│ - Frame Sync │ +│ - RAW to Temp │ +│ - ROI Calc │ +└───────┬────────┘ + │ + ├─→ Queue → GUI Task (Display) + │ + ├─→ Queue → Network Task (WebSocket streaming) + │ + └─→ Telemetry → HTTP/VISA Server +---- + +--- + +== Public API + +=== Lepton_Task_Init() + +[source,c] +---- +esp_err_t Lepton_Task_Init(void); +---- + +Initializes the Lepton camera driver and allocates frame buffers. + +**Initialization Steps:** + +1. Initialize Lepton SPI communication +2. Configure camera settings (AGC, ROI, FFC mode) +3. Allocate frame buffers in PSRAM +4. Create frame queues for distribution +5. Verify camera connection and firmware version + +**Return Values:** + +* `ESP_OK` - Initialization successful +* `ESP_ERR_NO_MEM` - Memory allocation failed +* `ESP_FAIL` - Camera communication failed +* `ESP_ERR_INVALID_STATE` - Already initialized + +**Thread Safety:** Not thread-safe. Must be called once during system initialization. + +**Example:** +[source,c] +---- +esp_err_t Error = Lepton_Task_Init(); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize Lepton: %d", Error); + return Error; +} +---- + +--- + +=== Lepton_Task_Deinit() + +[source,c] +---- +void Lepton_Task_Deinit(void); +---- + +Deinitializes the Lepton camera and frees allocated resources. + +**Actions:** + +* Stops task if running +* Puts camera in standby mode +* Frees frame buffers +* Deletes frame queues +* Deinitializes SPI interface + +**Thread Safety:** Not thread-safe. Call only during shutdown. + +--- + +=== Lepton_Task_Start() + +[source,c] +---- +esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext); +---- + +Starts the Lepton acquisition task. + +**Parameters:** + +* `p_AppContext` - Pointer to application context (must not be NULL) + +**Return Values:** + +* `ESP_OK` - Task started successfully +* `ESP_ERR_INVALID_ARG` - NULL pointer passed +* `ESP_ERR_INVALID_STATE` - Not initialized or already running +* `ESP_ERR_NO_MEM` - Task creation failed + +**Thread Safety:** Thread-safe. + +**Example:** +[source,c] +---- +App_Context_t AppContext; +esp_err_t Error = Lepton_Task_Start(&AppContext); +---- + +--- + +=== Lepton_Task_Stop() + +[source,c] +---- +esp_err_t Lepton_Task_Stop(void); +---- + +Stops the Lepton task and puts camera in standby mode. + +**Return Values:** + +* `ESP_OK` - Task stopped successfully +* `ESP_ERR_INVALID_STATE` - Task not running + +**Thread Safety:** Thread-safe. Blocks until task has stopped. + +--- + +=== Lepton_Task_isRunning() + +[source,c] +---- +bool Lepton_Task_isRunning(void); +---- + +Checks if the Lepton task is currently active. + +**Return Values:** + +* `true` - Task is running +* `false` - Task is not running + +**Thread Safety:** Thread-safe. + +--- + +== Frame Processing + +=== Frame Acquisition Loop + +[source,c] +---- +while (running) { + // 1. Read frame from camera (SPI) + Lepton_GetFrame(&RawFrame); + + // 2. Validate frame sync + if (!Lepton_ValidateFrame(&RawFrame)) { + Lepton_Resync(); + continue; + } + + // 3. Convert RAW to temperature (Celsius) + Lepton_RawToTemp(&RawFrame, &TempFrame); + + // 4. Calculate ROI statistics + CalculateROI(&TempFrame, &ROIData); + + // 5. Distribute to consumers + SendToGUI(&TempFrame); + SendToNetwork(&TempFrame); + + // 6. Update telemetry + UpdateTelemetry(&ROIData); +} +---- + +=== RAW to Temperature Conversion + +The Lepton camera outputs 14-bit RAW values that must be converted to temperature: + +**Formula:** + +[source] +---- +Temperature (Kelvin) = RAW_Value × 0.01 K + +Temperature (Celsius) = (RAW_Value × 0.01) - 273.15 +---- + +**Considerations:** + +* RAW value 0 is invalid (indicates bad pixel or sync error) +* Lepton 3.5 range: -10°C to +140°C (typical) +* Accuracy: ±5°C (typical), ±1.5°C (with calibration) + +--- + +== ROI (Region of Interest) Processing + +=== ROI Types + +The Lepton Task calculates statistics for up to 4 ROIs: + +1. **Spotmeter ROI** - User-defined region for temperature measurement +2. **Scene ROI** - Entire frame or custom scene region +3. **AGC ROI** - Region used for Automatic Gain Control +4. **Video Focus ROI** - Region for focus optimization (future) + +=== ROI Statistics + +For each ROI, the task calculates: + +* **Minimum Temperature**: Coldest pixel in ROI +* **Maximum Temperature**: Hottest pixel in ROI +* **Average Temperature**: Mean of all pixels in ROI +* **Pixel Coordinates**: Location of min/max pixels + +**Data Structure:** + +[source,c] +---- +typedef struct { + float MinTemp; // Minimum temperature (°C) + float MaxTemp; // Maximum temperature (°C) + float AvgTemp; // Average temperature (°C) + uint16_t MinX, MinY; // Coordinates of coldest pixel + uint16_t MaxX, MaxY; // Coordinates of hottest pixel +} ROI_Stats_t; +---- + +=== ROI Configuration + +ROIs are configured via Settings Manager: + +[source,c] +---- +App_Settings_ROI_t ROI = { + .X = 70, // X position (pixels) + .Y = 50, // Y position (pixels) + .Width = 20, // Width (pixels) + .Height = 20 // Height (pixels) +}; +SettingsManager_UpdateROI(ROI_SPOTMETER, &ROI); +---- + +**Constraints:** + +* ROI must be within frame boundaries (0-159 for X, 0-119 for Y on Lepton 3.5) +* Minimum ROI size: 4x4 pixels +* ROI coordinates must be even numbers (hardware requirement) + +--- + +== Telemetry + +=== Telemetry Structure + +The task generates telemetry data for monitoring and remote access: + +[source,c] +---- +typedef struct { + float SpotmeterTemp; // Spotmeter center temperature + float MinTemp; // Scene minimum temperature + float MaxTemp; // Scene maximum temperature + float AvgTemp; // Scene average temperature + uint32_t FrameCount; // Total frames captured + uint32_t ErrorCount; // Frame sync errors + uint16_t CameraTemp; // Camera housing temperature (°C) + bool FFC_InProgress; // Flat Field Correction active +} Lepton_Telemetry_t; +---- + +=== Telemetry Access + +Telemetry is accessible via: + +* HTTP REST API: `GET /api/telemetry` +* VISA/SCPI: `MEAS:TEMP?` +* WebSocket: Real-time streaming +* GUI: Displayed on main screen + +--- + +== Flat Field Correction (FFC) + +=== What is FFC? + +Flat Field Correction is a camera calibration process that compensates for sensor non-uniformities. The Lepton camera performs FFC automatically or on-demand. + +**FFC Modes:** + +1. **Automatic FFC**: Camera decides when to perform FFC (every ~3 minutes or on temperature change) +2. **Manual FFC**: Triggered by user command +3. **External Shutter FFC**: Uses external shutter (not implemented) + +**FFC Duration**: ~1-2 seconds (camera pauses during FFC) + +### FFC Event Handling + +The task monitors FFC status: + +[source,c] +---- +if (Lepton_FFC_InProgress()) { + ESP_LOGI(TAG, "FFC in progress..."); + // Notify GUI (display "Calibrating..." message) + // Pause frame distribution +} +---- + +--- + +== Error Handling and Recovery + +=== Frame Sync Errors + +The Lepton camera transmits frames as SPI packets. Sync errors can occur due to: + +* SPI timing issues +* Electromagnetic interference +* Camera power fluctuations + +**Recovery Strategy:** + +1. Detect invalid frame (invalid ID or checksum) +2. Discard current frame +3. Perform resynchronization (discard 3 frames) +4. Resume normal operation +5. Log error for diagnostics + +**Resync Algorithm:** + +[source,c] +---- +static void Lepton_Resync(void) +{ + ESP_LOGW(TAG, "Frame sync lost, resyncing..."); + + for (int i = 0; i < 3; i++) { + Lepton_ReadPacket(NULL); // Discard packet + } + + _ErrorCount++; +} +---- + +=== Camera Reboot Detection + +If the camera reboots (power loss, overheat protection), the task detects it and reinitializes: + +[source,c] +---- +if (Lepton_DetectReboot()) { + ESP_LOGE(TAG, "Camera rebooted, reinitializing..."); + Lepton_Task_Deinit(); + vTaskDelay(pdMS_TO_TICKS(1000)); + Lepton_Task_Init(); +} +---- + +--- + +== Camera Configuration + +=== AGC (Automatic Gain Control) + +AGC adjusts image contrast for optimal visualization: + +**AGC Modes:** + +* **Linear** - Direct mapping (no contrast enhancement) +* **Histogram Equalization (HEQ)** - Adaptive contrast (recommended) + +**Configuration:** + +[source,c] +---- +Lepton_SetAGCMode(LEPTON_AGC_HEQ); +Lepton_SetAGCROI(70, 50, 20, 20); // ROI for AGC calculation +---- + +=== Emissivity Correction + +Emissivity affects temperature accuracy for different materials: + +[source,c] +---- +// Set emissivity (0.0 - 1.0, typically 0.95 for most surfaces) +Lepton_SetEmissivity(0.95f); +---- + +**Common Emissivities:** + +* Skin: 0.98 +* Concrete: 0.92 +* Aluminum (oxidized): 0.30 +* Water: 0.95 + +--- + +== Frame Distribution + +=== Frame Queues + +Frames are distributed to consumers via FreeRTOS queues: + +**GUI Queue:** + +* Queue depth: 1 (only latest frame) +* Overwrite mode: Drop old frames if GUI is slow + +**Network Queue:** + +* Queue depth: 3 (small buffer for network jitter) +* Block if full (backpressure to prevent memory exhaustion) + +**Implementation:** + +[source,c] +---- +// Send to GUI (non-blocking, drop if full) +xQueueOverwrite(GUI_FrameQueue, &Frame); + +// Send to Network (blocking with timeout) +xQueueSend(Network_FrameQueue, &Frame, pdMS_TO_TICKS(100)); +---- + +--- + +## Dependencies + +=== Required Managers + +* *Device Manager*: SPI bus initialization for camera +* *Settings Manager*: ROI configuration, AGC settings, emissivity +* *Memory Manager*: Frame buffer allocation in PSRAM + +=== Required Components + +* *ESP32-Lepton*: Lepton camera driver (in `components/`) + +--- + +== Configuration + +=== Kconfig Options + +* `LEPTON_TASK_PRIORITY` - Task priority +* `LEPTON_TASK_STACK_SIZE` - Stack size (default: 8192) +* `LEPTON_TASK_CORE` - CPU core affinity +* `LEPTON_SPI_HOST` - SPI host (HSPI or VSPI) +* `LEPTON_SPI_FREQ` - SPI clock frequency (default: 20 MHz) + +--- + +== Performance Characteristics + +=== Frame Rate + +* **Lepton 3.5 Native Rate**: 8.6 Hz +* **Typical Achieved Rate**: 8-9 Hz +* **Frame Jitter**: ±10ms + +=== CPU Usage + +* **Typical**: 15-20% of one core +* **During FFC**: Minimal (camera paused) +* **Peak**: 25% (with complex ROI calculations) + +=== Memory Usage + +* **Frame Buffer (160x120x2)**: 38.4 KB per frame +* **Total Buffers (x3)**: ~115 KB (PSRAM) +* **Stack**: 8 KB +* **Heap**: ~5 KB (misc allocations) + +--- + +== Troubleshooting + +=== Common Issues + +**No frames acquired:** + +* Check SPI wiring and configuration +* Verify camera power supply (3.3V, sufficient current) +* Ensure CS, MOSI, MISO, CLK pins correct +* Check camera is not in standby mode + +**Frame sync errors:** + +* Reduce SPI clock frequency (try 16 MHz instead of 20 MHz) +* Check for electrical noise on SPI bus +* Verify ground connection +* Add pull-up resistors to CS line + +**Incorrect temperatures:** + +* Verify RAW to temperature conversion formula +* Check emissivity setting +* Perform FFC (Flat Field Correction) +* Allow camera to warm up (30 seconds) + +**Low frame rate:** + +* Check if task priority is sufficient +* Verify other tasks are not blocking +* Monitor CPU usage +* Ensure frame queues are not full + +--- + +== Event Handling + +The Lepton Task subscribes to events from other system components to receive configuration updates and requests. + +=== Subscribed Events + +==== Settings Events (`SETTINGS_EVENTS`) + +**`SETTINGS_EVENT_LEPTON_CHANGED`:** + +Received when Lepton camera settings have been modified (e.g., emissivity). + +* **Event Data**: `Settings_Manager_Setting_t *` or NULL +* **Handler**: `on_Settings_Event_Handler()` +* **Behavior**: + - If event data is NULL, indicates a bulk settings update without specific change information + - If event data is provided, contains `ID` and `Value` of the specific setting changed + - Handler checks `ID` field to determine which setting changed (e.g., `SETTINGS_ID_LEPTON_EMISSIVITY`) + +*IMPORTANT*: Event handlers MUST check for NULL event data before dereferencing pointers, as bulk setting updates may not include specific change details. + +[source,c] +---- +static void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, + int32_t ID, void *p_Data) +{ + switch (ID) { + case SETTINGS_EVENT_LEPTON_CHANGED: { + if (p_Data != NULL) { + Settings_Manager_Setting_t *p_Setting = + (Settings_Manager_Setting_t *)p_Data; + + if (p_Setting->ID == SETTINGS_ID_LEPTON_EMISSIVITY) { + // Apply emissivity change + } + } else { + // Bulk update, reload all settings + } + break; + } + } +} +---- + +==== GUI Events (`GUI_EVENTS`) + +**`GUI_EVENT_REQUEST_ROI`:** + +Requests ROI statistics calculation for a specific region. + +* **Event Data**: `App_Settings_ROI_t *` (MUST NOT be NULL) +* **Response**: Posts `LEPTON_EVENT_ROI_DATA` with calculated statistics + +**`GUI_EVENT_REQUEST_PIXEL_TEMPERATURE`:** + +Requests temperature at a specific screen position. + +* **Event Data**: `App_GUI_Screenposition_t *` (MUST NOT be NULL) +* **Response**: Posts `LEPTON_EVENT_PIXEL_TEMPERATURE` with temperature value + +--- + +== Future Enhancements + +* Multiple colormap support (Iron, Rainbow, Grayscale) +* Advanced image processing (edge detection, filtering) +* Temperature trend recording +* Multi-point temperature tracking +* Thermal anomaly detection +* Camera firmware update via OTA + +--- + +== Related Documentation + +* link:GUITask.adoc[GUI Task Documentation] +* link:NetworkTask.adoc[Network Task Documentation] +* link:DeviceManager.adoc[Device Manager Documentation] +* link:SettingsManager.adoc[Settings Manager Documentation] + +--- + +**Last Updated**: February 9, 2026 + +**Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/docs/MemoryManager.adoc b/docs/MemoryManager.adoc new file mode 100644 index 0000000..88f5c08 --- /dev/null +++ b/docs/MemoryManager.adoc @@ -0,0 +1,1176 @@ += PyroVision Memory Manager Documentation +Daniel Kampert +v1.0, 2026-02-08 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The Memory Manager is a unified storage abstraction component for the PyroVision firmware that provides seamless access to either internal flash storage or external SD card storage. It automatically detects the available storage medium and provides a consistent API for filesystem operations, usage monitoring, and USB Mass Storage integration. + +=== Key Features + +* *Automatic Storage Detection*: Detects SD card presence and selects storage location automatically +* *Unified Interface*: Consistent API regardless of storage medium (internal flash or SD card) +* *Dual Storage Support*: Internal FAT32 with wear leveling or external SD card (SDMMC) +* *Usage Monitoring*: Real-time filesystem usage statistics +* *USB Integration*: Filesystem locking mechanism for safe USB Mass Storage Device operation +* *Partition Management*: Access to storage and coredump partition information +* *Thread-safe Operations*: Protected access to shared resources +* *Coredump Support*: Separate coredump partition management + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Manager/Memory/ +├── memoryManager.h # Public API +└── memoryManager.cpp # Implementation +---- + +=== Storage Architecture + +The Memory Manager supports two distinct storage backends: + +==== 1. Internal Flash Storage + +* *Technology*: SPI Flash with FAT32 filesystem +* *Wear Leveling*: ESP-IDF wear leveling layer for flash longevity +* *Partition*: Dedicated `storage` partition in flash +* *Mount Point*: `/storage` +* *Capacity*: Configurable via partition table (typically 1-4 MB) +* *Advantages*: Always available, no external hardware required +* *Disadvantages*: Limited capacity, wear concerns + +==== 2. SD Card Storage + +* *Technology*: SDMMC interface with FAT32 filesystem +* *Mount Point*: `/sdcard` +* *Capacity*: Up to 32 GB (FAT32 limit) +* *Advantages*: High capacity, removable, replaceable +* *Disadvantages*: Requires external SD card slot, card must be inserted +* *Detection*: Automatic on initialization + +=== Storage Selection Logic + +The Memory Manager follows this priority: + +1. *SD Card Detection*: On initialization, check if SD card is present and mounted +2. *SD Card Priority*: If SD card available, use it as primary storage +3. *Flash Fallback*: If no SD card, use internal flash storage +4. *Static Selection*: Selection persists until reinitialization + +[source] +---- ++-----------------------------+ +| MemoryManager_Init() | ++-------------+---------------+ + | + v + +--------------+ + | SD Card | YES +------------------+ + | Present? +------>| Use /sdcard | + +------+-------+ | (SD Card) | + | NO +------------------+ + v + +------------------+ + | Use /storage | + | (Internal Flash) | + +------------------+ +---- + +=== Internal State Management + +The manager maintains its state in the `MemoryManager_State_t` structure: + +[source,cpp] +---- +typedef struct { + bool isInitialized; // Initialization status + bool hasSDCard; // SD card detected + bool filesystemLocked; // Filesystem locked for USB access + MemoryManager_Location_t location; // Active storage location + wl_handle_t wl_handle; // Wear leveling handle (internal flash) + sdmmc_card_t *p_SDCard; // SD card handle (SD card storage) +} MemoryManager_State_t; +---- + +=== Filesystem Locking Mechanism + +The Memory Manager provides a locking mechanism to prevent concurrent access conflicts when USB Mass Storage Device (MSC) mode is active. This is critical because: + +* *USB Host Control*: When USB MSC is active, the PC has direct block-level access to the storage +* *Data Corruption Risk*: Simultaneous access from firmware and PC can corrupt filesystem structures +* *FAT32 Limitation*: FAT32 has no built-in locking or journaling +* *Safe USB Mode*: Locking prevents firmware writes during USB MSC operation + +==== Lock/Unlock Flow + +[source] +---- +USB Activation: + 1. Application calls MemoryManager_LockFilesystem() + 2. Memory Manager sets filesystemLocked = true + 3. USB Manager exposes storage to PC + 4. Firmware must not write to filesystem + +USB Deactivation: + 1. USB Manager safely disconnects from PC + 2. Application calls MemoryManager_UnlockFilesystem() + 3. Memory Manager sets filesystemLocked = false + 4. Firmware can safely write to filesystem again +---- + +--- + +== Data Structures + +=== Storage Location Enum + +[source,cpp] +---- +typedef enum { + MEMORY_LOCATION_INTERNAL, // Internal flash storage partition + MEMORY_LOCATION_SD_CARD, // External SD card +} MemoryManager_Location_t; +---- + +=== Memory Usage Structure + +[source,cpp] +---- +typedef struct { + size_t TotalBytes; // Total partition/storage size in bytes + size_t UsedBytes; // Used space in bytes + size_t FreeBytes; // Free space in bytes + uint8_t UsedPercent; // Used space percentage (0-100) +} MemoryManager_Usage_t; +---- + +* *TotalBytes*: Total capacity of storage or partition +* *UsedBytes*: Space occupied by files and filesystem metadata +* *FreeBytes*: Available space for new files +* *UsedPercent*: Calculated usage percentage for UI display + +--- + +== API Reference + +=== Initialization and Lifecycle + +==== MemoryManager_Init() + +[source,cpp] +---- +esp_err_t MemoryManager_Init(void); +---- + +Initialize the Memory Manager and mount the storage filesystem. + +**Behavior:** + +1. Detects SD card presence via SDMMC interface +2. If SD card present and mountable, selects SD card storage +3. Otherwise, selects internal flash storage with wear leveling +4. Mounts the filesystem at appropriate mount point +5. Posts MEMORY_EVENT_INITIALIZED event + +**Return Values:** + +* `ESP_OK` - Storage successfully initialized and mounted +* `ESP_ERR_INVALID_STATE` - Already initialized +* `ESP_FAIL` - Failed to mount storage + +**Thread Safety:** Not thread-safe during initialization. Call once from main task. + +**Example:** + +[source,cpp] +---- +esp_err_t Error = MemoryManager_Init(); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize Memory Manager: %d", Error); + return Error; +} + +// Check which storage is active +if (MemoryManager_HasSDCard()) { + ESP_LOGI(TAG, "Using SD card storage"); +} else { + ESP_LOGI(TAG, "Using internal flash storage"); +} +---- + +==== MemoryManager_Deinit() + +[source,cpp] +---- +esp_err_t MemoryManager_Deinit(void); +---- + +Deinitialize the Memory Manager and unmount the storage filesystem. + +**Behavior:** + +1. Unmounts the active filesystem +2. Releases wear leveling handle (if internal flash) +3. Releases SD card handle (if SD card) +4. Resets internal state + +**Return Values:** + +* `ESP_OK` - Successfully deinitialized +* `ESP_ERR_INVALID_STATE` - Not initialized + +**Warning:** Ensure no files are open and filesystem is not locked before calling this function. + +--- + +=== Storage Information + +==== MemoryManager_HasSDCard() + +[source,cpp] +---- +bool MemoryManager_HasSDCard(void); +---- + +Check if SD card is present and successfully mounted. + +**Return Values:** + +* `true` - SD card is available and active +* `false` - Using internal flash storage + +**Example:** + +[source,cpp] +---- +if (MemoryManager_HasSDCard()) { + ESP_LOGI(TAG, "SD card detected: %s", MemoryManager_GetStoragePath()); + + // Display SD card icon in UI + lv_obj_clear_flag(ui_Icon_SDCard, LV_OBJ_FLAG_HIDDEN); +} else { + ESP_LOGI(TAG, "Using internal storage: %s", MemoryManager_GetStoragePath()); + + // Hide SD card icon + lv_obj_add_flag(ui_Icon_SDCard, LV_OBJ_FLAG_HIDDEN); +} +---- + +==== MemoryManager_GetStorageLocation() + +[source,cpp] +---- +MemoryManager_Location_t MemoryManager_GetStorageLocation(void); +---- + +Get the currently active storage location type. + +**Return Values:** + +* `MEMORY_LOCATION_INTERNAL` - Internal flash storage +* `MEMORY_LOCATION_SD_CARD` - SD card storage + +**Example:** + +[source,cpp] +---- +MemoryManager_Location_t Location = MemoryManager_GetStorageLocation(); + +switch (Location) { + case MEMORY_LOCATION_INTERNAL: + ESP_LOGI(TAG, "Storage: Internal Flash (FAT32 with Wear Leveling)"); + break; + + case MEMORY_LOCATION_SD_CARD: + ESP_LOGI(TAG, "Storage: SD Card (SDMMC)"); + break; +} +---- + +==== MemoryManager_GetStoragePath() + +[source,cpp] +---- +const char *MemoryManager_GetStoragePath(void); +---- + +Get the base mount point path for the current storage location. + +**Return Values:** + +* `"/storage"` - Internal flash storage mount point +* `"/sdcard"` - SD card storage mount point +* `NULL` - Not initialized + +**Thread Safety:** Thread-safe (returns pointer to static string). + +**Example:** + +[source,cpp] +---- +const char *p_Path = MemoryManager_GetStoragePath(); +if (p_Path == NULL) { + ESP_LOGE(TAG, "Memory Manager not initialized!"); + return ESP_ERR_INVALID_STATE; +} + +// Construct full file path +char FilePath[256]; +snprintf(FilePath, sizeof(FilePath), "%s/thermal_image_%d.jpg", p_Path, ImageCounter); + +// Open file +FILE *fp = fopen(FilePath, "wb"); +if (fp != NULL) { + // Write image data + fwrite(p_ImageData, 1, ImageSize, fp); + fclose(fp); + + ESP_LOGI(TAG, "Image saved: %s", FilePath); +} +---- + +--- + +=== Usage Monitoring + +==== MemoryManager_GetStorageUsage() + +[source,cpp] +---- +esp_err_t MemoryManager_GetStorageUsage(MemoryManager_Usage_t *p_Usage); +---- + +Get filesystem usage statistics for the current storage location. + +**Parameters:** + +* `p_Usage` - Pointer to usage structure to populate + +**Return Values:** + +* `ESP_OK` - Usage information retrieved successfully +* `ESP_ERR_INVALID_ARG` - p_Usage is NULL +* `ESP_ERR_NOT_FOUND` - Storage not found +* `ESP_FAIL` - Filesystem not mounted + +**Note:** Storage must be mounted to get usage information. + +**Example:** + +[source,cpp] +---- +MemoryManager_Usage_t Usage; +esp_err_t Error = MemoryManager_GetStorageUsage(&Usage); +if (Error == ESP_OK) { + ESP_LOGI(TAG, "Storage Usage:"); + ESP_LOGI(TAG, " Total: %zu bytes (%.2f MB)", + Usage.TotalBytes, Usage.TotalBytes / (1024.0 * 1024.0)); + ESP_LOGI(TAG, " Used: %zu bytes (%.2f MB)", + Usage.UsedBytes, Usage.UsedBytes / (1024.0 * 1024.0)); + ESP_LOGI(TAG, " Free: %zu bytes (%.2f MB)", + Usage.FreeBytes, Usage.FreeBytes / (1024.0 * 1024.0)); + ESP_LOGI(TAG, " Usage: %u%%", Usage.UsedPercent); + + // Update UI progress bar + lv_bar_set_value(ui_Bar_StorageUsage, Usage.UsedPercent, LV_ANIM_ON); + lv_label_set_text_fmt(ui_Label_StorageUsage, "%u%% Used", Usage.UsedPercent); +} else { + ESP_LOGE(TAG, "Failed to get storage usage: %d", Error); +} +---- + +==== MemoryManager_GetCoredumpUsage() + +[source,cpp] +---- +esp_err_t MemoryManager_GetCoredumpUsage(MemoryManager_Usage_t *p_Usage); +---- + +Get usage information for the coredump partition. + +**Parameters:** + +* `p_Usage` - Pointer to usage structure to populate + +**Return Values:** + +* `ESP_OK` - Coredump usage retrieved successfully +* `ESP_ERR_INVALID_ARG` - p_Usage is NULL +* `ESP_ERR_NOT_FOUND` - Coredump partition not found + +**Note:** Returns size of stored coredump data. If no crash has occurred, UsedBytes will be 0. + +**Example:** + +[source,cpp] +---- +MemoryManager_Usage_t CoredumpUsage; +esp_err_t Error = MemoryManager_GetCoredumpUsage(&CoredumpUsage); +if (Error == ESP_OK) { + if (CoredumpUsage.UsedBytes > 0) { + ESP_LOGW(TAG, "Coredump found: %zu bytes", CoredumpUsage.UsedBytes); + ESP_LOGW(TAG, "A previous crash was detected!"); + + // Show warning in UI + lv_obj_clear_flag(ui_Icon_CoredumpWarning, LV_OBJ_FLAG_HIDDEN); + } else { + ESP_LOGI(TAG, "No coredump stored"); + } +} else { + ESP_LOGE(TAG, "Failed to get coredump usage: %d", Error); +} +---- + +--- + +=== USB Integration + +==== MemoryManager_LockFilesystem() + +[source,cpp] +---- +esp_err_t MemoryManager_LockFilesystem(void); +---- + +Lock the filesystem for USB Mass Storage access. Prevents the application from writing to the filesystem while USB MSC is active. + +**Return Values:** + +* `ESP_OK` - Filesystem successfully locked +* `ESP_ERR_INVALID_STATE` - Already locked + +**Warning:** Application must not write to filesystem after locking. Data corruption will occur if both USB host and firmware access the filesystem simultaneously. + +**Thread Safety:** Thread-safe. + +**Example:** + +[source,cpp] +---- +// Before activating USB Mass Storage +esp_err_t Error = MemoryManager_LockFilesystem(); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to lock filesystem: %d", Error); + return Error; +} + +ESP_LOGW(TAG, "Filesystem locked - Application CANNOT write!"); + +// Now safe to activate USB MSC +Error = USBManager_Init(&USB_Config); +if (Error != ESP_OK) { + // Unlock on failure + MemoryManager_UnlockFilesystem(); + return Error; +} +---- + +==== MemoryManager_UnlockFilesystem() + +[source,cpp] +---- +esp_err_t MemoryManager_UnlockFilesystem(void); +---- + +Unlock the filesystem for application access. Re-enables filesystem write operations after USB Mass Storage is deactivated. + +**Return Values:** + +* `ESP_OK` - Filesystem successfully unlocked +* `ESP_ERR_INVALID_STATE` - Not locked + +**Note:** Call this function only after USB MSC has been safely deactivated and the host has ejected the device. + +**Thread Safety:** Thread-safe. + +**Example:** + +[source,cpp] +---- +// After USB Mass Storage deactivated +esp_err_t Error = MemoryManager_UnlockFilesystem(); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to unlock filesystem: %d", Error); + return Error; +} + +ESP_LOGI(TAG, "Filesystem unlocked - Application can write again!"); + +// Safe to write files now +FILE *fp = fopen("/storage/test.txt", "w"); +if (fp != NULL) { + fprintf(fp, "USB MSC deactivated, filesystem accessible again\n"); + fclose(fp); +} +---- + +==== MemoryManager_IsFilesystemLocked() + +[source,cpp] +---- +bool MemoryManager_IsFilesystemLocked(void); +---- + +Check if the filesystem is currently locked for USB access. + +**Return Values:** + +* `true` - Filesystem locked (USB active, application must not write) +* `false` - Filesystem unlocked (application can write safely) + +**Thread Safety:** Thread-safe. + +**Example:** + +[source,cpp] +---- +void SaveImage(uint8_t *p_ImageData, size_t ImageSize) +{ + // Check if filesystem is accessible + if (MemoryManager_IsFilesystemLocked()) { + ESP_LOGW(TAG, "Cannot save image - USB mode is active!"); + + // Show error message in UI + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "USB Active"); + lv_msgbox_add_text(msgbox, "Cannot save - USB mode is active!\nDisable USB first."); + + return; + } + + // Safe to write + const char *p_Path = MemoryManager_GetStoragePath(); + char FilePath[256]; + snprintf(FilePath, sizeof(FilePath), "%s/image_%d.jpg", p_Path, ImageCounter++); + + FILE *fp = fopen(FilePath, "wb"); + if (fp != NULL) { + fwrite(p_ImageData, 1, ImageSize, fp); + fclose(fp); + ESP_LOGI(TAG, "Image saved: %s", FilePath); + } +} +---- + +--- + +=== Partition Management + +==== MemoryManager_EraseStorage() + +[source,cpp] +---- +esp_err_t MemoryManager_EraseStorage(void); +---- + +Erase the current storage location completely and reformat it. + +**Warning:** This will delete ALL files in the active storage filesystem. Operation is irreversible. + +**Behavior:** + +1. Unmounts the filesystem +2. Erases the partition (internal flash) or reformats SD card +3. Remounts the filesystem (clean/empty) + +**Return Values:** + +* `ESP_OK` - Storage successfully erased and reformatted +* `ESP_ERR_NOT_FOUND` - Storage not found +* `ESP_FAIL` - Erase or mount operation failed + +**Note:** Filesystem will be automatically reformatted after erase. + +**Example:** + +[source,cpp] +---- +void FactoryReset_Storage(void) +{ + ESP_LOGW(TAG, "Erasing storage partition..."); + + esp_err_t Error = MemoryManager_EraseStorage(); + if (Error == ESP_OK) { + ESP_LOGI(TAG, "Storage partition erased and reformatted"); + + // Show success message + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "Storage Erased"); + lv_msgbox_add_text(msgbox, "All files have been deleted."); + } else { + ESP_LOGE(TAG, "Failed to erase storage: %d", Error); + } +} +---- + +==== MemoryManager_EraseCoredump() + +[source,cpp] +---- +esp_err_t MemoryManager_EraseCoredump(void); +---- + +Erase the coredump partition completely. + +**Warning:** This will delete any stored crash dumps. Use cautiously if debugging. + +**Behavior:** + +1. Finds the coredump partition +2. Erases the entire partition +3. Partition is ready for new coredumps + +**Return Values:** + +* `ESP_OK` - Coredump partition successfully erased +* `ESP_ERR_NOT_FOUND` - Coredump partition not found +* `ESP_FAIL` - Erase operation failed + +**Example:** + +[source,cpp] +---- +void ClearCoredump(void) +{ + ESP_LOGW(TAG, "Erasing coredump partition..."); + + esp_err_t Error = MemoryManager_EraseCoredump(); + if (Error == ESP_OK) { + ESP_LOGI(TAG, "Coredump partition cleared"); + + // Hide coredump warning icon + lv_obj_add_flag(ui_Icon_CoredumpWarning, LV_OBJ_FLAG_HIDDEN); + } else { + ESP_LOGE(TAG, "Failed to erase coredump: %d", Error); + } +} +---- + +--- + +=== Advanced Access + +==== MemoryManager_GetWearLevelingHandle() + +[source,cpp] +---- +esp_err_t MemoryManager_GetWearLevelingHandle(wl_handle_t *p_Handle); +---- + +Get the wear leveling handle for internal flash storage. + +**Parameters:** + +* `p_Handle` - Pointer to receive the wear leveling handle + +**Return Values:** + +* `ESP_OK` - Handle retrieved successfully +* `ESP_ERR_INVALID_ARG` - p_Handle is NULL +* `ESP_ERR_INVALID_STATE` - Not using internal storage or not mounted + +**Note:** Only valid for internal flash storage (not SD card). Required for USB MSC TinyUSB integration. + +**Example:** + +[source,cpp] +---- +wl_handle_t WL_Handle; +esp_err_t Error = MemoryManager_GetWearLevelingHandle(&WL_Handle); +if (Error == ESP_OK) { + ESP_LOGD(TAG, "Wear leveling handle: %d", WL_Handle); + + // Use with TinyUSB MSC + tinyusb_msc_storage_config_t msc_cfg; + memset(&msc_cfg, 0, sizeof(tinyusb_msc_storage_config_t)); + msc_cfg.medium.wl_handle = WL_Handle; + + Error = tinyusb_msc_new_storage_spiflash(&msc_cfg, &Storage); +} else { + ESP_LOGE(TAG, "Not using internal storage or not mounted"); +} +---- + +==== MemoryManager_GetSDCardHandle() + +[source,cpp] +---- +esp_err_t MemoryManager_GetSDCardHandle(sdmmc_card_t **pp_Card); +---- + +Get the SD card handle for direct SDMMC access. + +**Parameters:** + +* `pp_Card` - Pointer to receive the SD card handle pointer + +**Return Values:** + +* `ESP_OK` - Handle retrieved successfully +* `ESP_ERR_INVALID_ARG` - pp_Card is NULL +* `ESP_ERR_INVALID_STATE` - SD card not mounted + +**Note:** Only valid when SD card storage is active. Required for USB MSC TinyUSB integration. + +**Example:** + +[source,cpp] +---- +sdmmc_card_t *p_Card = NULL; +esp_err_t Error = MemoryManager_GetSDCardHandle(&p_Card); +if (Error == ESP_OK) { + ESP_LOGD(TAG, "SD card name: %s", p_Card->cid.name); + ESP_LOGD(TAG, "SD card sectors: %llu", p_Card->csd.capacity); + + // Use with TinyUSB MSC + tinyusb_msc_storage_config_t msc_cfg; + memset(&msc_cfg, 0, sizeof(tinyusb_msc_storage_config_t)); + msc_cfg.medium.card = p_Card; + + Error = tinyusb_msc_new_storage_sdmmc(&msc_cfg, &Storage); +} else { + ESP_LOGE(TAG, "SD card not mounted or not in use"); +} +---- + +--- + +== Common Use Cases + +=== Use Case 1: Application Startup + +[source,cpp] +---- +void app_main(void) +{ + // Initialize NVS + esp_err_t Error = nvs_flash_init(); + ESP_ERROR_CHECK(Error); + + // Initialize Memory Manager + Error = MemoryManager_Init(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize storage: %d", Error); + esp_restart(); + } + + // Log storage information + if (MemoryManager_HasSDCard()) { + ESP_LOGI(TAG, "Storage: SD Card at %s", MemoryManager_GetStoragePath()); + } else { + ESP_LOGI(TAG, "Storage: Internal Flash at %s", MemoryManager_GetStoragePath()); + } + + // Check available space + MemoryManager_Usage_t Usage; + if (MemoryManager_GetStorageUsage(&Usage) == ESP_OK) { + ESP_LOGI(TAG, "Free space: %zu bytes (%.2f MB)", + Usage.FreeBytes, Usage.FreeBytes / (1024.0 * 1024.0)); + } + + // Continue with other initialization... +} +---- + +=== Use Case 2: Saving Files + +[source,cpp] +---- +esp_err_t SaveThermalImage(uint8_t *p_ImageData, size_t ImageSize) +{ + // Check if filesystem is accessible + if (MemoryManager_IsFilesystemLocked()) { + ESP_LOGW(TAG, "Cannot save - USB mode active!"); + return ESP_ERR_INVALID_STATE; + } + + // Check available space + MemoryManager_Usage_t Usage; + if (MemoryManager_GetStorageUsage(&Usage) == ESP_OK) { + if (Usage.FreeBytes < ImageSize) { + ESP_LOGE(TAG, "Insufficient space: need %zu, have %zu", ImageSize, Usage.FreeBytes); + return ESP_ERR_NO_MEM; + } + } + + // Build file path + const char *p_BasePath = MemoryManager_GetStoragePath(); + char FilePath[256]; + time_t now; + time(&now); + struct tm timeinfo; + localtime_r(&now, &timeinfo); + + snprintf(FilePath, sizeof(FilePath), "%s/thermal_%04d%02d%02d_%02d%02d%02d.jpg", + p_BasePath, + timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, + timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); + + // Save file + FILE *fp = fopen(FilePath, "wb"); + if (fp == NULL) { + ESP_LOGE(TAG, "Failed to open file: %s", FilePath); + return ESP_FAIL; + } + + size_t Written = fwrite(p_ImageData, 1, ImageSize, fp); + fclose(fp); + + if (Written != ImageSize) { + ESP_LOGE(TAG, "Write error: expected %zu, wrote %zu", ImageSize, Written); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "Image saved: %s (%zu bytes)", FilePath, ImageSize); + return ESP_OK; +} +---- + +=== Use Case 3: USB Mass Storage Activation + +[source,cpp] +---- +esp_err_t EnableUSB_MassStorage(void) +{ + // Lock filesystem for USB access + esp_err_t Error = MemoryManager_LockFilesystem(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to lock filesystem: %d", Error); + return Error; + } + + ESP_LOGW(TAG, "Filesystem locked - Application cannot write!"); + + // Configure USB MSC + const USB_Manager_Config_t USB_Config = { + .p_MountPoint = MemoryManager_GetStoragePath(), + .p_VendorID = "PyroVis", + .p_ProductID = "ThermalCam", + .p_ProductRevision = "1.0", + }; + + // Initialize USB Manager + Error = USBManager_Init(&USB_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize USB Manager: %d", Error); + + // Unlock on failure + MemoryManager_UnlockFilesystem(); + return Error; + } + + ESP_LOGI(TAG, "USB Mass Storage Device active!"); + return ESP_OK; +} + +void DisableUSB_MassStorage_Callback(void *p_HandlerArgs, esp_event_base_t Base, + int32_t ID, void *p_Data) +{ + if (ID == USB_EVENT_UNINITIALIZED) { + // USB has been safely deactivated + esp_err_t Error = MemoryManager_UnlockFilesystem(); + if (Error == ESP_OK) { + ESP_LOGI(TAG, "Filesystem unlocked - Application can write again!"); + } else { + ESP_LOGE(TAG, "Failed to unlock filesystem: %d", Error); + } + } +} +---- + +=== Use Case 4: Storage Diagnostics + +[source,cpp] +---- +void PrintStorageDiagnostics(void) +{ + ESP_LOGI(TAG, "=== Storage Diagnostics ==="); + + // Storage location + if (MemoryManager_HasSDCard()) { + ESP_LOGI(TAG, "Location: SD Card (External)"); + } else { + ESP_LOGI(TAG, "Location: Internal Flash (SPI)"); + } + + // Mount point + ESP_LOGI(TAG, "Path: %s", MemoryManager_GetStoragePath()); + + // Storage usage + MemoryManager_Usage_t StorageUsage; + if (MemoryManager_GetStorageUsage(&StorageUsage) == ESP_OK) { + ESP_LOGI(TAG, "Storage Usage:"); + ESP_LOGI(TAG, " Total: %.2f MB", StorageUsage.TotalBytes / (1024.0 * 1024.0)); + ESP_LOGI(TAG, " Used: %.2f MB (%u%%)", + StorageUsage.UsedBytes / (1024.0 * 1024.0), StorageUsage.UsedPercent); + ESP_LOGI(TAG, " Free: %.2f MB", StorageUsage.FreeBytes / (1024.0 * 1024.0)); + } + + // Coredump status + MemoryManager_Usage_t CoredumpUsage; + if (MemoryManager_GetCoredumpUsage(&CoredumpUsage) == ESP_OK) { + if (CoredumpUsage.UsedBytes > 0) { + ESP_LOGW(TAG, "Coredump: %zu bytes (crash detected!)", CoredumpUsage.UsedBytes); + } else { + ESP_LOGI(TAG, "Coredump: Empty (no crashes)"); + } + } + + // Filesystem lock status + if (MemoryManager_IsFilesystemLocked()) { + ESP_LOGW(TAG, "Filesystem: LOCKED (USB active)"); + } else { + ESP_LOGI(TAG, "Filesystem: Unlocked (app can write)"); + } + + ESP_LOGI(TAG, "========================="); +} +---- + +--- + +== Best Practices + +=== Storage Selection + +* *Automatic Detection*: Let Memory Manager auto-detect storage - do not hardcode assumptions +* *Check Availability*: Always check `MemoryManager_HasSDCard()` if behavior depends on storage type +* *Path Usage*: Always use `MemoryManager_GetStoragePath()` for base path - never hardcode "/storage" or "/sdcard" + +=== File Operations + +* *Check Lock State*: Always call `MemoryManager_IsFilesystemLocked()` before writing files +* *Error Handling*: Always check return values from file operations +* *Space Checks*: Check available space before writing large files with `MemoryManager_GetStorageUsage()` +* *Sync After Write*: Call `fsync()` or `fclose()` to ensure data is written to storage + +=== USB Integration + +* *Lock Before USB*: Always lock filesystem with `MemoryManager_LockFilesystem()` before activating USB MSC +* *Unlock After USB*: Always unlock filesystem with `MemoryManager_UnlockFilesystem()` after deactivating USB MSC +* *Safe Ejection*: Ensure PC has ejected/unmounted the USB drive before deactivating USB MSC +* *No Writes During USB*: Never write to filesystem while USB MSC is active + +=== SD Card Handling + +* *Removable Media*: SD card can be removed at runtime - implement error handling for file operations +* *Power Cycling*: SD card mount may fail after deep sleep - add retry logic +* *Format Requirements*: SD card must be formatted as FAT32 before use + +=== Partition Management + +* *Coredump Preservation*: Do not erase coredump partition unless you've extracted the crash logs +* *Factory Reset*: Use `MemoryManager_EraseStorage()` for complete data wipe in factory reset scenarios +* *User Confirmation*: Always require user confirmation before erasing storage + +--- + +== Troubleshooting + +=== SD Card Not Detected + +**Symptoms:** +* `MemoryManager_HasSDCard()` returns false +* Using internal flash despite SD card being inserted + +**Possible Causes:** +* SD card not inserted or not properly seated +* SD card not formatted or corrupted filesystem +* SD card not FAT32 formatted +* SDMMC interface initialization failed + +**Solutions:** +* Check SD card is properly inserted +* Format SD card as FAT32 on PC +* Check ESP32 GPIO connections for SDMMC +* Enable debug logging: `idf.py menuconfig → Component config → Log output` + +=== Filesystem Lock Issues + +**Symptoms:** +* Cannot save files even after USB MSC deactivation +* `MemoryManager_IsFilesystemLocked()` returns true unexpectedly + +**Possible Causes:** +* `MemoryManager_UnlockFilesystem()` not called after USB deactivation +* USB Manager crashed during deinitialization + +**Solutions:** +* Ensure `MemoryManager_UnlockFilesystem()` is called in USB_EVENT_UNINITIALIZED handler +* Restart device to reset filesystem lock state + +=== Out of Space Errors + +**Symptoms:** +* File writes fail with no error message +* `fopen()` returns NULL +* `MemoryManager_GetStorageUsage()` shows 100% usage + +**Possible Causes:** +* Storage partition full +* Many small files (FAT32 cluster overhead) +* Corrupted filesystem + +**Solutions:** +* Delete old files to free space +* Erase storage partition: `MemoryManager_EraseStorage()` +* Use SD card for larger capacity +* Implement automatic old file cleanup + +=== Wear Leveling Warnings + +**Symptoms:** +* ESP_LOGW messages about wear leveling +* Reduced write performance on internal flash + +**Possible Causes:** +* High write frequency to internal flash +* Flash nearing end of life + +**Solutions:** +* Use SD card for high-frequency writes +* Reduce write frequency (batch writes, use RAM buffer) +* Monitor flash health with wear leveling statistics + +--- + +== Configuration + +=== PlatformIO / ESP-IDF + +Memory Manager requires the following components: + +[source,ini] +---- +[env] +platform = espressif32 +framework = espidf +board = esp32-s3-devkitc-1 + +lib_deps = + espressif/esp_tinyusb # For USB MSC integration + joltwallet/littlefs # If using LittleFS (optional) +---- + +=== Partition Table + +Define storage and coredump partitions in `partitions.csv`: + +[source] +---- +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 0x300000, +storage, data, fat, 0x310000,0x100000, # 1 MB internal storage +coredump, data, coredump, 0x410000,0x10000, # 64 KB coredump +---- + +Adjust `storage` partition size based on your requirements. + +=== SDMMC Configuration + +Configure SDMMC pins in `sdkconfig`: + +[source] +---- +CONFIG_SDMMC_HOST_MAX_FREQ_HIGHSPEED=40000000 +CONFIG_SDMMC_HOST_SLOT_AUTO_DETECT_EN=y +---- + +GPIO pin assignment is typically done in `DeviceManager` (I2C bus, SDMMC pins, etc.). + +--- + +== Advanced Topics + +=== Custom Mount Points + +While Memory Manager uses `/storage` and `/sdcard`, you can mount additional partitions: + +[source,cpp] +---- +// Mount additional partition +const esp_vfs_fat_mount_config_t mount_config = { + .max_files = 5, + .format_if_mount_failed = true, +}; + +wl_handle_t wl_handle; +esp_err_t Error = esp_vfs_fat_spiflash_mount("/data", "data_partition", + &mount_config, &wl_handle); +if (Error == ESP_OK) { + ESP_LOGI(TAG, "Custom partition mounted at /data"); +} +---- + +=== LittleFS Integration + +Memory Manager currently uses FAT32, but LittleFS can be integrated: + +[source,cpp] +---- +const esp_vfs_littlefs_conf_t lfs_conf = { + .base_path = "/lfs", + .partition_label = "littlefs", + .format_if_mount_failed = true, +}; + +esp_err_t Error = esp_vfs_littlefs_register(&lfs_conf); +if (Error == ESP_OK) { + ESP_LOGI(TAG, "LittleFS mounted at /lfs"); +} +---- + +Note: LittleFS is not supported by USB MSC (requires FAT filesystem). + +=== SPIFFS Alternative + +SPIFFS is deprecated but still available: + +[source,cpp] +---- +esp_vfs_spiffs_conf_t spiffs_conf = { + .base_path = "/spiffs", + .partition_label = "spiffs", + .max_files = 5, + .format_if_mount_failed = true, +}; + +esp_err_t Error = esp_vfs_spiffs_register(&spiffs_conf); +if (Error == ESP_OK) { + ESP_LOGI(TAG, "SPIFFS mounted at /spiffs"); +} +---- + +Note: SPIFFS does not support wear leveling and is not recommended for new projects. + +--- + +== Related Documentation + +* link:USBManager.adoc[USB Manager Documentation] - USB Mass Storage Device integration +* link:SettingsManager.adoc[Settings Manager Documentation] - Persistent settings storage +* link:DeviceManager.adoc[Device Manager Documentation] - Hardware initialization (I2C, SDMMC) + +== References + +* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/wear-levelling.html[ESP-IDF Wear Levelling] +* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/fatfs.html[ESP-IDF FAT Filesystem] +* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdmmc_host.html[ESP-IDF SDMMC Host Driver] +* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html[ESP-IDF Partition Tables] + +--- + +**Last Updated:** February 8, 2026 + +**Maintainer:** Daniel Kampert (DanielKampert@kampis-elektroecke.de) + +**License:** GNU General Public License v3.0 diff --git a/docs/NetworkTask.adoc b/docs/NetworkTask.adoc new file mode 100644 index 0000000..e207c16 --- /dev/null +++ b/docs/NetworkTask.adoc @@ -0,0 +1,347 @@ += PyroVision Network Task Documentation +Daniel Kampert +v1.0, 2026-02-09 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The Network Task manages all network-related operations including WiFi connectivity, HTTP/WebSocket server management, VISA/SCPI server, and network event handling. It acts as the coordination layer between the Network Manager and other system components. + +=== Key Features + +* *WiFi Connection Management*: Monitors and maintains WiFi connectivity +* *HTTP/WebSocket Server*: Serves web interface and streams thermal data +* *VISA/SCPI Server*: Provides instrumentation protocol (port 5025) +* *Network Event Handling*: Responds to connection state changes +* *Automatic Reconnection*: Retry logic for lost connections +* *WebSocket Frame Streaming*: Real-time thermal image distribution + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Tasks/Network/ +├── networkTask.h # Public API +└── networkTask.cpp # Implementation +---- + +=== Task Architecture + +* *Task Name*: `"NetworkTask"` +* *Priority*: Medium (typically `tskIDLE_PRIORITY + 2`) +* *Stack Size*: 6 KB +* *Core Affinity*: Typically Core 0 (PRO CPU) + +--- + +== Public API + +=== Network_Task_Init() + +[source,c] +---- +esp_err_t Network_Task_Init(App_Context_t *p_AppContext); +---- + +Initializes the network task and sets up event handlers. + +**Parameters:** + +* `p_AppContext` - Pointer to application context (must not be NULL) + +**Return Values:** + +* `ESP_OK` - Initialization successful +* `ESP_ERR_INVALID_ARG` - NULL pointer passed +* `ESP_ERR_NO_MEM` - Memory allocation failed +* `ESP_ERR_INVALID_STATE` - Already initialized + +**Thread Safety:** Not thread-safe. Call once during system initialization. + +--- + +=== Network_Task_Deinit() + +[source,c] +---- +void Network_Task_Deinit(void); +---- + +Deinitializes the network task and cleans up resources. + +--- + +=== Network_Task_Start() + +[source,c] +---- +esp_err_t Network_Task_Start(void); +---- + +Starts the network task. + +**Return Values:** + +* `ESP_OK` - Task started successfully +* `ESP_ERR_INVALID_STATE` - Not initialized or already running +* `ESP_ERR_NO_MEM` - Task creation failed + +--- + +=== Network_Task_Stop() + +[source,c] +---- +esp_err_t Network_Task_Stop(void); +---- + +Stops the network task. + +**Return Values:** + +* `ESP_OK` - Task stopped +* `ESP_ERR_INVALID_STATE` - Not running + +--- + +=== Network_Task_isRunning() + +[source,c] +---- +bool Network_Task_isRunning(void); +---- + +Checks if the task is running. + +**Return Values:** + +* `true` - Task is running +* `false` - Task is stopped + +--- + +== Task Operation + +=== Main Event Loop + +[source,c] +---- +while (running) { + // 1. Monitor WiFi connection state + if (NetworkManager_GetState() == NETWORK_STATE_CONNECTED) { + // Ensure servers are running + if (!HTTP_Server_isRunning()) { + HTTP_Server_Start(); + } + if (!VISA_Server_isRunning()) { + VISA_Server_Start(); + } + } + + // 2. Handle WebSocket frame streaming + if (HasWebSocketClients()) { + Frame_t Frame; + if (xQueueReceive(FrameQueue, &Frame, 0) == pdTRUE) { + WebSocket_BroadcastFrame(&Frame); + } + } + + // 3. Process network events + ProcessNetworkEvents(); + + vTaskDelay(pdMS_TO_TICKS(100)); +} +---- + +--- + +== WebSocket Frame Streaming + +=== Frame Distribution + +The task receives thermal frames from Lepton Task and distributes them to WebSocket clients: + +**Flow:** + +[source] +---- +Lepton Task → Queue → Network Task → WebSocket → Browser Clients +---- + +**Frame Format:** + +* Binary format: JPEG-compressed thermal image +* Frame rate: ~8-9 Hz (camera native rate) +* Size: 5-15 KB per frame (depending on compression) + +**Implementation:** + +[source,c] +---- +// Receive frame from Lepton Task +Frame_t Frame; +if (xQueueReceive(Network_FrameQueue, &Frame, 0) == pdTRUE) { + // Compress to JPEG + uint8_t *JpegBuffer; + size_t JpegSize; + ImageEncoder_EncodeJPEG(&Frame, &JpegBuffer, &JpegSize); + + // Broadcast to all connected WebSocket clients + WebSocket_BroadcastBinary(JpegBuffer, JpegSize); + + free(JpegBuffer); +} +---- + +--- + +== Server Management + +=== HTTP/WebSocket Server + +The task ensures the HTTP server (which handles WebSocket connections) is running when WiFi is connected: + +**Startup:** + +1. Wait for WiFi connection (NETWORK_STATE_CONNECTED) +2. Start HTTP server +3. Register WebSocket upgrade handler +4. Begin streaming frames + +**Shutdown:** + +* Gracefully closes all client connections +* Stops HTTP server +* Frees resources + +=== VISA/SCPI Server + +The VISA server runs independently on port 5025: + +**Management:** + +* Started when WiFi connects +* Handles concurrent clients (max 5) +* Provides SCPI command interface +* Automatic client timeout (30 seconds idle) + +--- + +== Event Handling + +=== Network Events + +The task listens to Network Manager events: + +**Event Types:** + +* `NETWORK_EVENT_WIFI_CONNECTED` - WiFi connection established +* `NETWORK_EVENT_WIFI_DISCONNECTED` - WiFi connection lost +* `NETWORK_EVENT_IP_ACQUIRED` - IP address obtained +* `NETWORK_EVENT_AP_STARTED` - Access Point mode active + +**Event Handlers:** + +[source,c] +---- +static void on_WiFi_Connected(void *p_Arg, esp_event_base_t EventBase, + int32_t EventID, void *p_EventData) +{ + ESP_LOGI(TAG, "WiFi connected, starting servers..."); + + HTTP_Server_Start(&HTTPConfig); + VISA_Server_Start(&VISAConfig); + + // Notify GUI (update WiFi icon) + esp_event_post(GUI_EVENTS, GUI_EVENT_WIFI_CONNECTED, NULL, 0, 0); +} +---- + +--- + +== Dependencies + +=== Required Managers + +* *Network Manager*: WiFi and connection management +* *Settings Manager*: Server configuration (ports, credentials) + +=== Required Tasks + +* *Lepton Task*: Provides thermal frames for streaming + +=== Server Components + +* *HTTP Server*: Web interface and REST API +* *WebSocket*: Real-time frame streaming +* *VISA Server*: SCPI instrumentation protocol +* *DNS Server*: Captive portal for provisioning + +--- + +== Configuration + +=== Server Ports + +* HTTP: 80 (default) +* WebSocket: 80 (HTTP upgrade) +* VISA/SCPI: 5025 (standard) + +--- + +## Performance + +=== CPU Usage + +* **Typical**: 10-15% (during streaming) +* **Idle**: <5% (no clients connected) +* **Peak**: 20% (multiple WebSocket clients) + +=== Network Bandwidth + +* **Per WebSocket Client**: ~80-120 KB/s +* **Max Clients**: 5 simultaneous +* **Total Bandwidth**: ~600 KB/s (all clients) + +--- + +== Troubleshooting + +**WebSocket disconnects frequently:** + +* Check WiFi signal strength +* Verify ping interval (30 seconds recommended) +* Monitor memory usage (may be low) + +**VISA server not responding:** + +* Verify port 5025 is not blocked +* Check firewall settings +* Ensure WiFi is connected + +**High CPU usage:** + +* Reduce number of WebSocket clients +* Lower frame compression quality +* Increase task delay interval + +--- + +== Related Documentation + +* link:NetworkManager.adoc[Network Manager Documentation] +* link:LeptonTask.adoc[Lepton Task Documentation] +* link:VISAServer.adoc[VISA Server Documentation] +* link:HTTPServer.adoc[HTTP Server Documentation] + +--- + +**Last Updated**: February 9, 2026 + +**Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/docs/SettingsManager.adoc b/docs/SettingsManager.adoc index f5f4f19..93be84f 100644 --- a/docs/SettingsManager.adoc +++ b/docs/SettingsManager.adoc @@ -169,7 +169,7 @@ ESP_EVENT_DECLARE_BASE(SETTINGS_EVENTS); |`SETTINGS_EVENT_LEPTON_CHANGED` |Lepton settings changed -|`App_Settings_Lepton_t` +|`Settings_Manager_Setting_t` or NULL (see note below) |`SETTINGS_EVENT_WIFI_CHANGED` |WiFi settings changed @@ -208,6 +208,8 @@ ESP_EVENT_DECLARE_BASE(SETTINGS_EVENTS); |NULL |=== +*NOTE*: For `SETTINGS_EVENT_LEPTON_CHANGED` events, the event data may be NULL if the update was called without specifying which particular setting changed (i.e., when `SettingsManager_UpdateLepton()` is called without the optional `p_ChangedSetting` parameter). Event handlers MUST check for NULL before accessing event data. + == API Reference === Initialization and Lifecycle diff --git a/docs/USBManager.adoc b/docs/USBManager.adoc new file mode 100644 index 0000000..3e07248 --- /dev/null +++ b/docs/USBManager.adoc @@ -0,0 +1,1040 @@ += PyroVision USB Manager Documentation +Daniel Kampert +v1.0, 2026-02-08 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The USB Manager implements USB Mass Storage Device (MSC) functionality for the PyroVision firmware, allowing the device's storage (internal flash or SD card) to be exposed as a USB drive to a PC. This enables convenient file transfer, firmware updates, and data backup without requiring network connectivity or special software. + +=== Key Features + +* *USB Mass Storage Class (MSC)*: Standard USB drive functionality compatible with all operating systems +* *Automatic Storage Detection*: Works with both internal flash and SD card storage +* *TinyUSB Integration*: Based on Espressif's esp_tinyusb component +* *Asynchronous Deinitialization*: Non-blocking USB disconnect with background task +* *Event-driven Architecture*: Notification of USB state changes via ESP Event System +* *Windows Compatibility*: Proper USB enumeration and ejection support +* *Re-initialization Support*: Reliable activate → deactivate → activate cycles +* *Filesystem Locking*: Integrates with Memory Manager to prevent data corruption + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Manager/USB/ +├── usbManager.h # Public API +├── usbManager.cpp # Implementation +└── usbTypes.h # Event types and configuration +---- + +=== TinyUSB Stack Integration + +The USB Manager is built on top of the TinyUSB stack provided by Espressif: + +[source] +---- +┌─────────────────────────────────────────┐ +│ Application Layer │ +│ (GUI, Settings, File Operations) │ +└──────────────┬──────────────────────────┘ + │ +┌──────────────▼──────────────────────────┐ +│ USB Manager │ +│ - Init/Deinit Lifecycle │ +│ - Storage Configuration │ +│ - Event Posting │ +└──────────────┬──────────────────────────┘ + │ +┌──────────────▼──────────────────────────┐ +│ TinyUSB MSC Layer │ +│ - tinyusb_msc_new_storage_sdmmc() │ +│ - tinyusb_msc_new_storage_spiflash() │ +│ - tinyusb_msc_delete_storage() │ +└──────────────┬──────────────────────────┘ + │ +┌──────────────▼──────────────────────────┐ +│ TinyUSB Core │ +│ - USB Stack Implementation │ +│ - tud_connect() / tud_disconnect() │ +│ - tud_mounted() Status │ +└──────────────┬──────────────────────────┘ + │ +┌──────────────▼──────────────────────────┐ +│ USB Hardware (ESP32-S3) │ +│ - Native USB OTG Interface │ +└─────────────────────────────────────────┘ +---- + +=== Storage Backend Selection + +USB Manager automatically detects and configures the appropriate storage backend: + +[source] +---- +MemoryManager_GetStorageLocation() + │ + ├─► SD Card Detected + │ └─► tinyusb_msc_new_storage_sdmmc() + │ └─► Uses sdmmc_card_t handle + │ + └─► Internal Flash + └─► tinyusb_msc_new_storage_spiflash() + └─► Uses wl_handle_t (Wear Leveling) +---- + +=== USB Lifecycle State Machine + +[source] +---- +┌─────────────┐ +│ NOT_INIT │ Initial state +└──────┬──────┘ + │ USBManager_Init() + ▼ +┌─────────────┐ +│ INITIALIZED │ USB MSC Active, Device Visible +│ │ Posts: USB_EVENT_INITIALIZED +└──────┬──────┘ + │ USBManager_Deinit() + ▼ +┌─────────────┐ +│DEINITIALIZING│ Background Task Running +│ │ Waiting for USB Disconnect +└──────┬──────┘ + │ tud_mounted() == false + │ Timeout or Disconnect Confirmed + ▼ +┌─────────────┐ +│ NOT_INIT │ Posts: USB_EVENT_UNINITIALIZED +│ │ Ready for Re-initialization +└─────────────┘ +---- + +=== Internal State Management + +The manager maintains its state in the `USBManager_State_t` structure: + +[source,cpp] +---- +typedef struct { + bool isInitialized; // USB MSC active + bool isDeinitializing; // Deinitialization in progress + bool isUSBMounted; // USB host has mounted device + USB_Manager_Config_t Config; // Current configuration + tinyusb_msc_storage_handle_t Storage; // Storage handle + TaskHandle_t DeinitTask; // Deinit task handle + SemaphoreHandle_t DisconnectSemaphore; // Disconnect detection +} USBManager_State_t; +---- + +--- + +== Data Structures + +=== USB Manager Configuration + +[source,cpp] +---- +typedef struct { + const char *p_MountPoint; // Mount point (from MemoryManager) + const char *p_VendorID; // USB vendor ID string + const char *p_ProductID; // USB product ID string + const char *p_ProductRevision; // USB product revision string +} USB_Manager_Config_t; +---- + +* *p_MountPoint*: Must match MemoryManager mount point (`/storage` or `/sdcard`) +* *p_VendorID*: Vendor identifier shown on PC (max 8 characters) +* *p_ProductID*: Product name shown on PC (max 16 characters) +* *p_ProductRevision*: Product revision string (max 4 characters) + +**Example:** + +[source,cpp] +---- +const USB_Manager_Config_t USB_Config = { + .p_MountPoint = MemoryManager_GetStoragePath(), + .p_VendorID = "PyroVis", // Shows as "PyroVis" in device manager + .p_ProductID = "ThermalCam", // Shows as "ThermalCam" drive name + .p_ProductRevision = "1.0", // Firmware version +}; +---- + +=== Event System + +==== Event Base + +[source,cpp] +---- +ESP_EVENT_DECLARE_BASE(USB_EVENTS); +---- + +==== Event IDs + +[cols="2,3,2"] +|=== +|Event |Description |Data Payload + +|`USB_EVENT_INITIALIZED` +|USB MSC initialized and ready + +Device is visible to PC +|NULL + +|`USB_EVENT_UNINITIALIZED` +|USB MSC deinitialized + +Filesystem unlocked, app can write +|NULL +|=== + +**Event Handler Example:** + +[source,cpp] +---- +void on_USB_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, + int32_t ID, void *p_Data) +{ + switch (ID) { + case USB_EVENT_INITIALIZED: + ESP_LOGI(TAG, "USB MSC Active - Device visible to PC"); + + // Update UI: Show USB icon + lv_obj_clear_flag(ui_Icon_USB, LV_OBJ_FLAG_HIDDEN); + + // Disable save buttons (filesystem locked) + lv_obj_add_state(ui_Button_Save, LV_STATE_DISABLED); + break; + + case USB_EVENT_UNINITIALIZED: + ESP_LOGI(TAG, "USB MSC Deactivated - Filesystem accessible"); + + // Update UI: Hide USB icon + lv_obj_add_flag(ui_Icon_USB, LV_OBJ_FLAG_HIDDEN); + + // Enable save buttons again + lv_obj_clear_state(ui_Button_Save, LV_STATE_DISABLED); + break; + } +} +---- + +**Registration:** + +[source,cpp] +---- +esp_event_handler_register(USB_EVENTS, ESP_EVENT_ANY_ID, + on_USB_Event_Handler, NULL); +---- + +--- + +== API Reference + +=== Initialization and Lifecycle + +==== USBManager_Init() + +[source,cpp] +---- +esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config); +---- + +Initialize the USB Manager and expose storage as USB Mass Storage Device. + +**Behavior:** + +1. Validates configuration parameters +2. Waits for any pending deinitialization to complete (max 10 seconds) +3. Locks filesystem via `MemoryManager_LockFilesystem()` +4. Detects storage type from Memory Manager (SD card or internal flash) +5. Cleans up old storage handles from previous sessions +6. Installs TinyUSB driver (reuses if already installed) +7. Creates MSC storage backend (SDMMC or SPI flash) +8. Connects to USB bus via `tud_connect()` to trigger PC enumeration +9. Posts `USB_EVENT_INITIALIZED` event + +**Parameters:** + +* `p_Config` - Pointer to USB manager configuration structure + +**Return Values:** + +* `ESP_OK` - USB MSC successfully initialized and active +* `ESP_ERR_INVALID_ARG` - p_Config is NULL or invalid parameters +* `ESP_ERR_INVALID_STATE` - Already initialized or deinitialization timeout +* `ESP_ERR_NO_MEM` - Failed to allocate memory (increase DMA pool) +* `ESP_FAIL` - USB initialization failed + +**Thread Safety:** Not thread-safe during initialization. Call once from main task. + +**Critical Requirements:** + +* Memory Manager must be initialized first +* DMA memory pool must be adequate (CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL ≥ 160 KB) +* Filesystem must not be accessed by application during USB MSC operation + +**Example:** + +[source,cpp] +---- +void EnableUSB_Mode(void) +{ + // Lock filesystem first + esp_err_t Error = MemoryManager_LockFilesystem(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to lock filesystem: %d", Error); + return; + } + + // Configure USB Mass Storage + const USB_Manager_Config_t USB_Config = { + .p_MountPoint = MemoryManager_GetStoragePath(), + .p_VendorID = "PyroVis", + .p_ProductID = "ThermalCam", + .p_ProductRevision = "1.0", + }; + + // Initialize USB MSC + Error = USBManager_Init(&USB_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize USB: %d", Error); + + // Unlock filesystem on failure + MemoryManager_UnlockFilesystem(); + return; + } + + ESP_LOGI(TAG, "✓ USB Mass Storage Device active!"); + ESP_LOGW(TAG, "⚠️ Application CANNOT write to storage while USB is active!"); + + // Wait for USB_EVENT_INITIALIZED event... +} +---- + +==== USBManager_Deinit() + +[source,cpp] +---- +esp_err_t USBManager_Deinit(void); +---- + +Deinitialize the USB Manager and stop USB Mass Storage Device asynchronously. + +**Behavior:** + +1. Validates USB Manager is initialized +2. Validates not already deinitializing +3. Sets `isInitialized = false` to prevent new operations +4. Sets `isDeinitializing = true` to signal deinitialization in progress +5. Creates background task `Task_USB_Deinit` (priority 1) to handle the lengthy disconnect process +6. Returns immediately (non-blocking) + +**Background Task Operations:** + +1. Calls `tud_disconnect()` to actively disconnect from USB bus +2. Waits 500 ms for Windows to process disconnect +3. Polls `tud_mounted()` every 100 ms until false (max 5 seconds) +4. Unlocks filesystem via `MemoryManager_UnlockFilesystem()` +5. Posts `USB_EVENT_UNINITIALIZED` event +6. Self-deletes task via `vTaskDelete(NULL)` + +**Return Values:** + +* `ESP_OK` - Deinitialization started successfully (async operation) +* `ESP_ERR_INVALID_STATE` - Not initialized or already deinitializing + +**Thread Safety:** Thread-safe. Can be called from any task. + +**Important Notes:** + +* Function returns immediately; actual deinitialization happens in background +* Storage handle is NOT deleted to prevent TinyUSB callback crashes +* Old handle is cleaned up on next `USBManager_Init()` call +* Application should wait for `USB_EVENT_UNINITIALIZED` before writing to filesystem + +**Example:** + +[source,cpp] +---- +void DisableUSB_Mode(void) +{ + if (!USBManager_IsInitialized()) { + ESP_LOGW(TAG, "USB not active!"); + return; + } + + ESP_LOGI(TAG, "Disabling USB Mass Storage..."); + + // Start asynchronous deinitialization + esp_err_t Error = USBManager_Deinit(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to deinitialize USB: %d", Error); + return; + } + + ESP_LOGI(TAG, "USB deinitialization started - waiting for completion..."); + + // Show loading message box + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "USB Deinitialization"); + lv_msgbox_add_text(msgbox, "Waiting for USB device to disconnect...\nPlease wait."); + lv_obj_center(msgbox); + + // Message box will be closed by USB_EVENT_UNINITIALIZED handler +} +---- + +==== USBManager_IsInitialized() + +[source,cpp] +---- +bool USBManager_IsInitialized(void); +---- + +Check if USB Manager is initialized and USB MSC is active. + +**Return Values:** + +* `true` - USB MSC is active, device is exposed to PC +* `false` - USB MSC not initialized + +**Thread Safety:** Thread-safe. + +**Example:** + +[source,cpp] +---- +void SaveImage(uint8_t *p_Data, size_t Size) +{ + // Check if USB is active + if (USBManager_IsInitialized()) { + ESP_LOGW(TAG, "Cannot save image - USB mode is active!"); + + // Show error message + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "USB Active"); + lv_msgbox_add_text(msgbox, "Cannot save - USB mode is active!\nDisable USB first."); + + return; + } + + // Safe to write file + const char *p_Path = MemoryManager_GetStoragePath(); + char FilePath[256]; + snprintf(FilePath, sizeof(FilePath), "%s/image_%d.jpg", p_Path, ImageCounter++); + + FILE *fp = fopen(FilePath, "wb"); + if (fp != NULL) { + fwrite(p_Data, 1, Size, fp); + fclose(fp); + ESP_LOGI(TAG, "Image saved: %s", FilePath); + } +} +---- + +--- + +== Common Use Cases + +=== Use Case 1: Basic USB Activation + +[source,cpp] +---- +void ActivateUSB_Button_Callback(lv_event_t *e) +{ + ESP_LOGI(TAG, "USB activation requested by user"); + + // Check if already active + if (USBManager_IsInitialized()) { + ESP_LOGW(TAG, "USB already active!"); + return; + } + + // Lock filesystem + esp_err_t Error = MemoryManager_LockFilesystem(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to lock filesystem!"); + return; + } + + // Configure USB MSC + const USB_Manager_Config_t USB_Config = { + .p_MountPoint = MemoryManager_GetStoragePath(), + .p_VendorID = "PyroVis", + .p_ProductID = "ThermalCam", + .p_ProductRevision = "1.0", + }; + + // Initialize USB + Error = USBManager_Init(&USB_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "USB initialization failed: %d", Error); + MemoryManager_UnlockFilesystem(); + + // Show error message + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "USB Error"); + lv_msgbox_add_text(msgbox, "Failed to activate USB mode!"); + return; + } + + ESP_LOGI(TAG, "✓ USB Mass Storage Device active!"); +} +---- + +=== Use Case 2: Event-Driven UI Updates + +[source,cpp] +---- +void on_USB_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, + int32_t ID, void *p_Data) +{ + switch (ID) { + case USB_EVENT_INITIALIZED: { + ESP_LOGI(TAG, "USB initialized - updating UI"); + + // Set switch to ON state + lv_obj_add_state(ui_Switch_USB, LV_STATE_CHECKED); + + // Show USB icon in status bar + lv_obj_clear_flag(ui_Icon_USB_Active, LV_OBJ_FLAG_HIDDEN); + + // Hide save buttons (filesystem locked) + lv_obj_add_flag(ui_Button_Save, LV_OBJ_FLAG_HIDDEN); + + // Update status label + lv_label_set_text(ui_Label_Status, "USB Mode Active"); + + // Show success message + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "USB Active"); + lv_msgbox_add_text(msgbox, "Device connected to PC\nDo not disconnect during file transfer!"); + + break; + } + + case USB_EVENT_UNINITIALIZED: { + ESP_LOGI(TAG, "USB deinitialized - updating UI"); + + // Set switch to OFF state + lv_obj_clear_state(ui_Switch_USB, LV_STATE_CHECKED); + + // Hide USB icon + lv_obj_add_flag(ui_Icon_USB_Active, LV_OBJ_FLAG_HIDDEN); + + // Show save buttons again + lv_obj_clear_flag(ui_Button_Save, LV_OBJ_FLAG_HIDDEN); + + // Update status label + lv_label_set_text(ui_Label_Status, "USB Mode Disabled"); + + // Close loading message box if visible + if (usb_msgbox != NULL) { + lv_obj_del(usb_msgbox); + usb_msgbox = NULL; + } + + // Show completion message + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "USB Deactivated"); + lv_msgbox_add_text(msgbox, "USB safely disconnected\nYou can save files again."); + + break; + } + } +} + +// Register event handler in initialization +void app_main(void) +{ + // ... other initialization ... + + esp_event_handler_register(USB_EVENTS, ESP_EVENT_ANY_ID, + on_USB_Event_Handler, NULL); +} +---- + +=== Use Case 3: Toggle Switch with Animation Fix + +[source,cpp] +---- +void on_USB_Mode_Switch_Callback(lv_event_t *e) +{ + lv_obj_t *switch_obj = lv_event_get_target(e); + + if (lv_obj_has_state(switch_obj, LV_STATE_CHECKED)) { + // Switch turned ON - Activate USB + ESP_LOGI(TAG, "Enabling USB Mass Storage..."); + + if (USBManager_IsInitialized()) { + ESP_LOGW(TAG, "USB already active!"); + return; + } + + // Configure and initialize + const USB_Manager_Config_t USB_Config = { + .p_MountPoint = MemoryManager_GetStoragePath(), + .p_VendorID = "PyroVis", + .p_ProductID = "ThermalCam", + .p_ProductRevision = "1.0", + }; + + esp_err_t Error = USBManager_Init(&USB_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize USB: %d", Error); + + // Revert switch on error + lv_obj_clear_state(switch_obj, LV_STATE_CHECKED); + } + } else { + // Switch turned OFF - Deactivate USB + ESP_LOGI(TAG, "Disabling USB Mass Storage..."); + + if (!USBManager_IsInitialized()) { + ESP_LOGW(TAG, "USB not active!"); + return; + } + + // Start asynchronous deinitialization + esp_err_t Error = USBManager_Deinit(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to deinitialize USB: %d", Error); + return; + } + + // Show waiting message + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "USB Deinitialization"); + lv_msgbox_add_text(msgbox, "Waiting for USB device to disconnect...\nPlease wait."); + lv_obj_center(msgbox); + + // Switch will be updated to OFF by USB_EVENT_UNINITIALIZED handler + } +} +---- + +=== Use Case 4: Re-initialization Cycle + +[source,cpp] +---- +void TestUSB_Reinitialization(void) +{ + ESP_LOGI(TAG, "=== USB Re-initialization Test ==="); + + // First activation + ESP_LOGI(TAG, "Activation #1"); + const USB_Manager_Config_t USB_Config = { + .p_MountPoint = MemoryManager_GetStoragePath(), + .p_VendorID = "PyroVis", + .p_ProductID = "Test", + .p_ProductRevision = "1.0", + }; + + esp_err_t Error = USBManager_Init(&USB_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Init #1 failed: %d", Error); + return; + } + + ESP_LOGI(TAG, "Init #1 successful, waiting 5 seconds..."); + vTaskDelay(pdMS_TO_TICKS(5000)); + + // First deactivation + ESP_LOGI(TAG, "Deactivation #1"); + Error = USBManager_Deinit(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Deinit #1 failed: %d", Error); + return; + } + + ESP_LOGI(TAG, "Deinit #1 started, waiting for completion..."); + + // Wait for USB_EVENT_UNINITIALIZED (in real code, use event handler) + uint32_t WaitCount = 0; + while (USBManager_IsInitialized() && WaitCount < 100) { + vTaskDelay(pdMS_TO_TICKS(100)); + WaitCount++; + } + + if (WaitCount >= 100) { + ESP_LOGE(TAG, "Deinit #1 timeout!"); + return; + } + + ESP_LOGI(TAG, "Deinit #1 completed after %u ms", WaitCount * 100); + + // Additional delay to ensure cleanup + vTaskDelay(pdMS_TO_TICKS(1000)); + + // Second activation (re-initialization) + ESP_LOGI(TAG, "Activation #2 (Re-initialization)"); + Error = USBManager_Init(&USB_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Init #2 failed: %d", Error); + return; + } + + ESP_LOGI(TAG, "Init #2 successful!"); + ESP_LOGI(TAG, "=== Re-initialization Test PASSED ==="); +} +---- + +--- + +== Best Practices + +=== Initialization + +* *Order Matters*: Initialize Memory Manager before USB Manager +* *Lock Filesystem*: Always lock filesystem before activating USB MSC +* *Event Registration*: Register USB event handlers before initialization +* *Configuration Validation*: Validate mount point matches Memory Manager + +=== Deinitialization + +* *Async Operation*: Understand that `USBManager_Deinit()` returns immediately +* *Wait for Event*: Always wait for `USB_EVENT_UNINITIALIZED` before writing files +* *Safe Ejection*: Ensure PC has ejected/unmounted drive before deactivating +* *No Forced Disconnect*: Never unplug cable without proper deactivation + +=== Filesystem Access + +* *Check Lock State*: Always check `MemoryManager_IsFilesystemLocked()` before writing +* *No Concurrent Access*: Never write to filesystem while USB MSC is active +* *UI Feedback*: Disable file save buttons during USB mode +* *Error Handling*: Show clear error messages if user tries to save during USB mode + +=== Error Recovery + +* *Unlock on Failure*: Always unlock filesystem if USB initialization fails +* *Timeout Handling*: Implement timeouts for deinitialization (max 10 seconds recommended) +* *State Validation*: Check `USBManager_IsInitialized()` before operations +* *Restart as Last Resort*: If USB state is corrupted, restart device + +=== UI/UX Considerations + +* *Visual Feedback*: Show USB icon in status bar when active +* *Loading Indicators*: Show progress during async deinitialization +* *Clear Warnings*: Warn users not to disconnect during file transfer +* *Disable Controls*: Disable conflicting operations during USB mode + +--- + +== Troubleshooting + +=== USB Device Not Visible on PC + +**Symptoms:** +* Device plugged in, but no drive letter appears +* Device manager shows unknown device or error code + +**Possible Causes:** +* `tud_connect()` not called or failed +* DMA memory insufficient (heap_caps_aligned_calloc failure) +* TinyUSB callbacks conflicting with library +* USB cable is charge-only (no data lines) + +**Solutions:** +* Ensure CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL ≥ 160 KB +* Use proper USB data cable, not charge-only cable +* Check ESP32-S3 USB port (not UART USB port) +* Enable debug logging: `ESP_LOG_LEVEL(TAG, ESP_LOG_DEBUG)` + +=== USB Deinitialization Timeout + +**Symptoms:** +* `USBManager_Deinit()` never posts `USB_EVENT_UNINITIALIZED` +* `tud_mounted()` remains true after deinitialization +* PC still shows device after deactivation + +**Possible Causes:** +* PC has not ejected the drive +* Background deinit task crashed +* `tud_disconnect()` not called + +**Solutions:** +* Eject drive from PC before calling `USBManager_Deinit()` +* Add explicit `tud_disconnect()` call in deinit task +* Increase polling timeout (currently 5 seconds) +* Restart device if timeout occurs + +=== Re-initialization Failure + +**Symptoms:** +* Cannot activate USB after deactivating it +* `USBManager_Init()` returns ESP_ERR_INVALID_STATE +* Error: "Previous deinit still running" + +**Possible Causes:** +* `USBManager_Init()` called too soon after `USBManager_Deinit()` +* Background deinit task still running +* Storage handle not cleaned up + +**Solutions:** +* Wait for `USB_EVENT_UNINITIALIZED` before re-initialization +* Implement wait loop for `isDeinitializing` flag (max 10 seconds) +* Add delay (500-1000 ms) after deinitialization completes +* Check for pending deinitialization in `USBManager_Init()` + +=== Display Artifacts During USB Operations + +**Symptoms:** +* Screen shows stripes or corruption when activating/deactivating USB +* Display freezes momentarily + +**Possible Causes:** +* High-priority USB deinit task starving display task +* SPI bus contention (display and flash on same bus) +* Display refresh interrupted + +**Solutions:** +* Lower USB deinit task priority to 1 (below display task) +* Avoid display invalidation pause (not necessary for internal flash) +* Ensure display task priority is higher (e.g., 5) +* Use Core 1 for USB operations, Core 0 for display + +=== Windows Drive Remains After Deactivation + +**Symptoms:** +* Windows shows drive letter even after USB deactivation +* "Device not responding" error when accessing drive + +**Possible Causes:** +* `tud_disconnect()` not called explicitly +* Windows cached driver state +* PC has files open on the drive + +**Solutions:** +* Add explicit `tud_disconnect()` in deinit task +* Ensure all files closed before deactivation +* Manually eject drive in Windows before deactivation +* Wait 500 ms after `tud_disconnect()` for OS processing + +=== Memory Allocation Failures + +**Symptoms:** +* `USBManager_Init()` returns ESP_ERR_NO_MEM +* Log: "Failed to allocate memory for MSC storage" + +**Possible Causes:** +* Insufficient DMA memory pool +* Memory fragmentation +* Large allocations by other components + +**Solutions:** +* Increase CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL to 160 KB or higher +* Initialize USB Manager early in boot sequence +* Free unused memory before USB initialization +* Check memory usage: `heap_caps_get_free_size(MALLOC_CAP_DMA)` + +--- + +== Configuration + +=== PlatformIO / ESP-IDF + +USB Manager requires the following components: + +[source,ini] +---- +[env] +platform = espressif32 +framework = espidf +board = esp32-s3-devkitc-1 + +lib_deps = + espressif/esp_tinyusb@^2.1.0 +---- + +=== sdkconfig Settings + +==== DMA Memory Pool (Critical) + +[source] +---- +# Increase DMA-capable memory pool for TinyUSB MSC +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=163840 # 160 KB +---- + +**Why:** TinyUSB MSC storage allocation requires substantial DMA memory via `heap_caps_aligned_calloc()`. Default 32 KB is insufficient. + +**Calculation:** +- TinyUSB MSC buffer: ~64 KB +- WiFi/Bluetooth: ~32 KB +- Lepton VoSPI: ~32 KB +- Safety margin: ~32 KB +- Total: 160 KB + +==== USB OTG Configuration + +[source] +---- +CONFIG_TINYUSB_ENABLED=y +CONFIG_TINYUSB_MSC_ENABLED=y +---- + +==== PSRAM Configuration + +[source] +---- +CONFIG_SPIRAM_MODE_OCT=y # Octal SPI for 8 MB PSRAM +CONFIG_SPIRAM_SIZE=8388608 # 8 MB +---- + +=== Partition Table + +No special partition requirements. USB Manager uses existing storage partition defined in [MemoryManager](MemoryManager.adoc). + +--- + +== Advanced Topics + +=== Custom USB Descriptors + +To customize USB device descriptors, modify TinyUSB configuration: + +[source,cpp] +---- +// In your component config or before tinyusb_driver_install() + +#define USB_DEVICE_VID 0x303A // Espressif VID +#define USB_DEVICE_PID 0x4002 // Custom PID +#define USB_MANUFACTURER "PyroVision" +#define USB_PRODUCT "Thermal Camera" +---- + +Note: USB Manager currently uses runtime configuration via `USB_Manager_Config_t`, not compile-time descriptors. + +=== TinyUSB Callbacks + +USB Manager does NOT override TinyUSB callbacks to avoid linker conflicts: + +[source,cpp] +---- +// Do NOT implement these in your code if using USB Manager: +void tud_mount_cb(void); // Already defined in esp_tinyusb +void tud_umount_cb(void); // Already defined in esp_tinyusb +---- + +**Polling Instead:** USB Manager uses `tud_mounted()` polling for disconnect detection. + +=== Storage Handle Lifetime + +**Critical Implementation Detail:** + +Storage handle is NOT deleted during deinitialization to prevent crashes: + +[source,cpp] +---- +// In Task_USB_Deinit(): +// DO NOT: tinyusb_msc_delete_storage(_State.Storage); +// Reason: TinyUSB callbacks may still access storage for up to 5 seconds + +// Instead: Keep storage alive, clean up on next USBManager_Init() +---- + +**Why:** TinyUSB MSC callbacks (`tud_msc_read10_cb`, `tud_msc_write10_cb`) may still be active for several seconds after disconnect, even after `tud_mounted()` returns false. + +**Cleanup Strategy:** Old storage handle is deleted in next `USBManager_Init()` call, when we know no callbacks are active. + +=== Multi-Device Support + +Current implementation supports single USB MSC device. For multiple drives: + +[source,cpp] +---- +// Not currently supported, would require: +// 1. Multiple tinyusb_msc_storage_handle_t instances +// 2. Separate LUN (Logical Unit Number) configuration +// 3. Modified TinyUSB descriptors + +// Future enhancement possibility +---- + +--- + +== Performance Considerations + +=== USB Transfer Speed + +* *SD Card*: ~10-20 MB/s read, ~5-10 MB/s write +* *Internal Flash*: ~2-5 MB/s read/write (limited by wear leveling) + +**Optimization:** +* Use SD card for large file transfers +* Format as FAT32 with 4 KB cluster size +* Use high-speed SD card (UHS-I or better) + +=== Deinitialization Time + +* *Typical*: 0.5-2 seconds +* *Maximum*: 5 seconds (timeout) + +**Factors:** +* PC operating system (Windows slower than Linux) +* Open file handles on PC +* USB bus congestion +* Number of files in filesystem + +=== Task Priority Impact + +USB deinit task priority affects GUI responsiveness: + +* *Priority 1*: Minimal GUI impact, slower deinitialization +* *Priority 3*: Moderate GUI impact, faster deinitialization +* *Priority 5+*: Significant GUI impact (not recommended) + +**Current Setting:** Priority 1 (lowest impact) + +--- + +== Security Considerations + +=== Data Exposure + +* USB MSC exposes ALL files in storage partition +* No file-level access control +* PC has full read/write access + +**Mitigation:** +* Store sensitive data in separate partition +* Encrypt sensitive files before storage +* Implement USB authorization (future enhancement) + +=== Filesystem Corruption Risk + +* Concurrent access can corrupt FAT32 filesystem +* No journaling or crash recovery in FAT32 + +**Mitigation:** +* Strict filesystem locking via Memory Manager +* Always check lock state before writing +* Regular filesystem backups (if critical data) + +--- + +== Related Documentation + +* link:MemoryManager.adoc[Memory Manager Documentation] - Storage abstraction and filesystem locking +* link:DeviceManager.adoc[Device Manager Documentation] - Hardware initialization and I2C/SPI configuration +* link:SettingsManager.adoc[Settings Manager Documentation] - Persistent settings storage + +== References + +* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/usb_device.html[ESP-IDF USB Device Driver] +* https://github.com/hathach/tinyusb[TinyUSB GitHub Repository] +* https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/usb_otg.html[ESP32-S3 USB OTG Documentation] +* https://www.usb.org/documents[USB Mass Storage Class Specification] + +--- + +**Last Updated:** February 8, 2026 + +**Maintainer:** Daniel Kampert (DanielKampert@kampis-elektroecke.de) + +**License:** GNU General Public License v3.0 diff --git a/docs/VISAServer.adoc b/docs/VISAServer.adoc new file mode 100644 index 0000000..0429b47 --- /dev/null +++ b/docs/VISAServer.adoc @@ -0,0 +1,564 @@ += PyroVision VISA/SCPI Server Documentation +Daniel Kampert +v1.0, 2026-02-09 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +The VISA Server provides a standard SCPI (Standard Commands for Programmable Instruments) interface over TCP/IP on port 5025. This allows remote control and data acquisition using standard instrumentation software like MATLAB, LabVIEW, or Python's PyVISA. + +=== Key Features + +* *Standard Port*: 5025 (VISA/SCPI standard) +* *TCP/IP Socket*: Multi-client support (up to 4 clients) +* *SCPI Commands*: Standard command syntax +* *Remote Control*: Configure camera, acquire data, save images +* *Error Reporting*: Standard SCPI error queue +* *Timeout Handling*: Automatic client disconnection on inactivity + +--- + +== Architecture + +=== Component Structure + +[source] +---- +main/Application/Manager/Network/Server/VISA/ +├── visaServer.h # Public API +├── visaServer.cpp # Server implementation +└── Private/ + ├── visaCommands.h # Command parser + └── visaCommands.cpp # Command handlers +---- + +--- + +== Public API + +=== VISAServer_Init() + +[source,c] +---- +esp_err_t VISAServer_Init(const Network_VISA_Server_Config_t *p_Config); +---- + +Initializes the VISA server with configuration. + +**Configuration:** + +[source,c] +---- +typedef struct { + uint16_t Port; // Port number (default: 5025) + uint8_t MaxClients; // Max concurrent clients (default: 4) + uint32_t TimeoutMS; // Client timeout (default: 30000 ms) +} Network_VISA_Server_Config_t; +---- + +**Return Values:** + +* `ESP_OK` - Initialization successful +* `ESP_ERR_INVALID_ARG` - Invalid configuration +* `ESP_ERR_NO_MEM` - Memory allocation failed +* `ESP_ERR_INVALID_STATE` - Already initialized + +--- + +=== VISAServer_Start() + +[source,c] +---- +esp_err_t VISAServer_Start(void); +---- + +Starts the VISA server and begins listening for client connections. + +**Return Values:** + +* `ESP_OK` - Server started successfully +* `ESP_FAIL` - Socket creation or binding failed +* `ESP_ERR_INVALID_STATE` - Not initialized + +--- + +=== VISAServer_Stop() + +[source,c] +---- +esp_err_t VISAServer_Stop(void); +---- + +Stops the VISA server and closes all client connections. + +--- + +=== VISAServer_isRunning() + +[source,c] +---- +bool VISAServer_isRunning(void); +---- + +Checks if the VISA server is running. + +--- + +== SCPI Command Reference + +=== IEEE 488.2 Common Commands + +==== `*IDN?` - Identification Query + +Returns device identification string. + +**Syntax:** +[source] +---- +*IDN? +---- + +**Response:** +[source] +---- +PyroVision,Thermal Camera,, +---- + +**Example:** +[source] +---- +VISA>> *IDN? +PyroVision,Thermal Camera,000001,1.0.0 +---- + +--- + +==== `*RST` - Reset + +Resets the device to default settings. + +**Syntax:** +[source] +---- +*RST +---- + +--- + +==== `*CLS` - Clear Status + +Clears the error queue and status registers. + +**Syntax:** +[source] +---- +*CLS +---- + +--- + +==== `*OPC?` - Operation Complete Query + +Returns `1` when all pending operations are complete. + +**Syntax:** +[source] +---- +*OPC? +---- + +**Response:** +[source] +---- +1 +---- + +--- + +=== Measurement Commands + +==== `MEASure:TEMPerature?` - Read Spotmeter Temperature + +Reads the current spotmeter temperature. + +**Syntax:** +[source] +---- +MEAS:TEMP? +---- + +**Response:** +[source] +---- + +---- + +**Example:** +[source] +---- +VISA>> MEAS:TEMP? +25.3 +---- + +--- + +==== `MEASure:TEMPerature:MINimum?` - Scene Minimum + +Reads the minimum temperature in the scene. + +**Syntax:** +[source] +---- +MEAS:TEMP:MIN? +---- + +**Response:** +[source] +---- + +---- + +--- + +==== `MEASure:TEMPerature:MAXimum?` - Scene Maximum + +Reads the maximum temperature in the scene. + +**Syntax:** +[source] +---- +MEAS:TEMP:MAX? +---- + +--- + +==== `MEASure:TEMPerature:AVERage?` - Scene Average + +Reads the average temperature in the scene. + +**Syntax:** +[source] +---- +MEAS:TEMP:AVER? +---- + +--- + +=== Configuration Commands + +==== `CONFigure:ROI` - Set ROI Position + +Sets the position and size of a Region of Interest. + +**Syntax:** +[source] +---- +CONF:ROI ,,,, +---- + +**Parameters:** + +* `` - ROI identifier (0=Spotmeter, 1=Scene, 2=AGC, 3=Video) +* ``, `` - Top-left coordinates (pixels) +* ``, `` - ROI dimensions (pixels) + +**Example:** +[source] +---- +VISA>> CONF:ROI 0,70,50,20,20 +OK +---- + +--- + +==== `CONFigure:EMISSivity` - Set Emissivity + +Sets the emissivity correction factor. + +**Syntax:** +[source] +---- +CONF:EMIS +---- + +**Parameters:** + +* `` - Emissivity (0.1 - 1.0) + +**Example:** +[source] +---- +VISA>> CONF:EMIS 0.95 +OK +---- + +--- + +==== `CONFigure:AGC` - AGC Mode + +Sets the Automatic Gain Control mode. + +**Syntax:** +[source] +---- +CONF:AGC +---- + +**Parameters:** + +* `` - AGC mode: `0` = Linear, `1` = HEQ (Histogram Equalization) + +**Example:** +[source] +---- +VISA>> CONF:AGC 1 +OK +---- + +--- + +=== Data Acquisition Commands + +==== `DATA:IMAGe?` - Get Thermal Image + +Requests the current thermal frame as binary data. + +**Syntax:** +[source] +---- +DATA:IMAG? +---- + +**Response:** + +Binary data block in IEEE 488.2 format: + +[source] +---- +# +---- + +**Example:** +[source] +---- +VISA>> DATA:IMAG? +#512345 +---- + +--- + +==== `DATA:TELEMetry?` - Get Telemetry + +Returns comprehensive telemetry data in JSON format. + +**Syntax:** +[source] +---- +DATA:TELE? +---- + +**Response:** +[source,json] +---- +{ + "spotmeter": 25.3, + "min": 20.1, + "max": 30.5, + "avg": 25.0, + "frame_count": 12345, + "error_count": 2 +} +---- + +--- + +=== System Commands + +==== `SYSTem:SAVE` - Save Settings + +Saves current settings to NVS. + +**Syntax:** +[source] +---- +SYST:SAVE +---- + +--- + +==== `SYSTem:RESTore` - Restore Factory Defaults + +Restores factory default settings. + +**Syntax:** +[source] +---- +SYST:REST +---- + +--- + +==== `SYSTem:TIME` - Set System Time + +Sets the system date and time. + +**Syntax:** +[source] +---- +SYST:TIME , +---- + +**Example:** +[source] +---- +VISA>> SYST:TIME 2026-02-09,14:30:00 +OK +---- + +--- + +==== `SYSTem:ERRor?` - Query Error Queue + +Retrieves the oldest error from the error queue. + +**Syntax:** +[source] +---- +SYST:ERR? +---- + +**Response:** +[source] +---- +,"" +---- + +**Example:** +[source] +---- +VISA>> SYST:ERR? +-200,"Execution error" +---- + +--- + +== Error Codes + +Standard SCPI error codes are returned: + +* `0` - No error +* `-100` - Command error (syntax error) +* `-200` - Execution error (cannot execute) +* `-300` - Device-specific error +* `-400` - Query error (data not available) +* `-410` - Query interrupted +* `-420` - Query unterminated + +--- + +== Usage Examples + +=== Python (PyVISA) + +[source,python] +---- +import pyvisa + +rm = pyvisa.ResourceManager() +inst = rm.open_resource('TCPIP::192.168.1.100::5025::SOCKET') +inst.read_termination = '\n' +inst.write_termination = '\n' + +# Query identification +print(inst.query('*IDN?')) + +# Read temperature +temp = float(inst.query('MEAS:TEMP?')) +print(f"Temperature: {temp} °C") + +# Set ROI +inst.write('CONF:ROI 0,70,50,20,20') + +# Get telemetry +telemetry = inst.query('DATA:TELE?') +print(telemetry) + +inst.close() +---- + +--- + +=== MATLAB + +[source,matlab] +---- +% Create VISA-TCPIP object +t = tcpip('192.168.1.100', 5025); +fopen(t); + +% Query identification +fprintf(t, '*IDN?'); +idn = fscanf(t); +disp(idn); + +% Read temperature +fprintf(t, 'MEAS:TEMP?'); +temp = fscanf(t, '%f'); +fprintf('Temperature: %.2f °C\n', temp); + +% Close connection +fclose(t); +delete(t); +---- + +--- + +== Protocol Details + +=== Connection Flow + +[source] +---- +Client Server + | | + |-- TCP Connect (5025) -->| + |<-- Accept Connection ---| + | | + |-- Send Command -------->| + | | (Parse & Execute) + |<-- Send Response -------| + | | + |-- Close Connection ---->| +---- + +=== Command Termination + +Commands must be terminated with newline (`\n` or `\r\n`). + +=== Response Termination + +Responses are terminated with newline (`\n`). + +--- + +== Performance + +* **Max Clients**: 4 concurrent connections +* **Command Processing**: <10 ms (typical) +* **Data Transfer**: ~500 KB/s (image data) +* **Timeout**: 30 seconds idle disconnect + +--- + +== Related Documentation + +* link:NetworkTask.adoc[Network Task Documentation] +* link:NetworkManager.adoc[Network Manager Documentation] + +--- + +**Last Updated**: February 9, 2026 + +**Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/docs/index.adoc b/docs/index.adoc new file mode 100644 index 0000000..f272ab7 --- /dev/null +++ b/docs/index.adoc @@ -0,0 +1,347 @@ += PyroVision Firmware Documentation +Daniel Kampert +v1.0, 2026-02-09 +:toc: left +:toclevels: 3 +:sectnums: +:source-highlighter: coderay + +== Overview + +PyroVision is an advanced ESP32-S3 based thermal imaging camera system featuring a FLIR Lepton 3.5 thermal sensor, touch display interface, WiFi connectivity, and comprehensive remote control capabilities. This documentation provides a complete reference for the firmware architecture, APIs, and usage. + +=== Key Features + +* *Thermal Imaging*: FLIR Lepton 3.5 (160x120, 14-bit, 8.6 Hz) +* *Display*: 320x240 ILI9341 TFT with GT911 capacitive touch +* *WiFi*: Station and Access Point modes with provisioning +* *Web Interface*: Live thermal streaming via WebSocket +* *SCPI/VISA*: Standard instrumentation protocol (port 5025) +* *Storage*: SD card for image capture and logging +* *USB*: Mass Storage Class for SD card access +* *RTOS*: FreeRTOS-based multi-tasking architecture + +--- + +== System Architecture + +=== High-Level Overview + +[source] +---- +┌─────────────────────────────────────────────────────────┐ +│ Application Layer │ +├────────────┬───────────────┬─────────────┬──────────────┤ +│ GUI Task │ Lepton Task │ Network Task│ Devices Task │ +├────────────┴───────────────┴─────────────┴──────────────┤ +│ Manager Layer │ +├──────────┬────────────┬────────────┬───────────┬────────┤ +│ Settings │ Network │ Device │ Time │ Memory │ +│ Manager │ Manager │ Manager │ Manager │ Manager│ +├──────────┴────────────┴────────────┴───────────┴────────┤ +│ Hardware Abstraction Layer │ +├──────────┬────────────┬────────────┬───────────┬────────┤ +│ SPI/I2C │ Display │ Camera │ RTC │ SD Card│ +├──────────┴────────────┴────────────┴───────────┴────────┤ +│ ESP-IDF / FreeRTOS │ +└─────────────────────────────────────────────────────────┘ +---- + +== Documentation Index + +=== Managers + +Managers provide stateful APIs for major subsystems: + +* link:SettingsManager.adoc[*Settings Manager*] - Configuration and NVS storage +* link:NetworkManager.adoc[*Network Manager*] - WiFi, servers, and connectivity +* link:DeviceManager.adoc[*Device Manager*] - Peripheral initialization (I2C, SPI, display, etc.) +* link:TimeManager.adoc[*Time Manager*] - RTC and NTP time synchronization +* link:MemoryManager.adoc[*Memory Manager*] - Heap and PSRAM management +* link:USBManager.adoc[*USB Manager*] - USB device (MSC) functionality + +=== Tasks + +FreeRTOS tasks implement the main application logic: + +* link:GUITask.adoc[*GUI Task*] - LVGL-based touch interface +* link:LeptonTask.adoc[*Lepton Task*] - Thermal camera acquisition and processing +* link:NetworkTask.adoc[*Network Task*] - Network connectivity and streaming +* link:DevicesTask.adoc[*Devices Task*] - Peripheral monitoring (battery, sensors) + +=== Network Servers + +Server implementations for remote access: + +* link:HTTPServer.adoc[*HTTP Server*] - Web interface and REST API +* link:VISAServer.adoc[*VISA Server*] - SCPI instrumentation protocol + +== Getting Started + +=== Building the Firmware + +**Prerequisites:** + +* PlatformIO (recommended) or ESP-IDF 5.5+ +* Python 3.8+ +* AStyle (for code formatting) + +**Build Commands:** + +[source,bash] +---- +# Debug build +pio run -e debug + +# Release build +pio run -e release + +# Upload to device +pio run -t upload + +# Monitor serial output +pio device monitor +---- + +== First Boot + +**Initial Configuration:** + +1. Device boots into Access Point mode (`PyroVision-XXXXXX`) +2. Connect to the AP with your phone/computer +3. Captive portal automatically opens (or navigate to `http://192.168.4.1`) +4. Scan for WiFi networks and enter credentials +5. Device connects to your WiFi network +6. Access web interface at device's IP address + +== Configuration + +=== Kconfig Options + +Key configuration options (via `menuconfig`): + +* **WiFi Settings**: Default SSID, password, max retries +* **Display Settings**: Orientation, backlight, color depth +* **Lepton Settings**: SPI frequency, AGC mode, emissivity +* **Task Priorities**: Configure FreeRTOS task priorities +* **Memory Allocation**: PSRAM usage, heap sizes + +=== Settings Structure + +Settings are organized hierarchically: + +[source] +---- +App_Settings_t +├── WiFi (SSID, password, auto-connect) +├── Display (brightness, orientation, timeout) +├── Lepton (ROIs, emissivity presets, AGC) +├── Network (HTTP port, VISA port, WebSocket config) +├── System (timezone, hostname, log level) +└── USB (MSC mode, vendor/product strings) +---- + +**Persistent Storage:** All settings stored in NVS (Non-Volatile Storage). + +== API Quick Reference + +=== Common Patterns + +**Manager Initialization:** + +[source,c] +---- +// Standard manager initialization pattern +esp_err_t Error = ManagerName_Init(); +if (Error != ESP_OK) { + ESP_LOGE(TAG, "Init failed: %d", Error); + return Error; +} +---- + +**Getting Settings:** + +[source,c] +---- +App_Settings_WiFi_t WiFiSettings; +esp_err_t Error = SettingsManager_GetWiFi(&WiFiSettings); +---- + +**Updating Settings:** + +[source,c] +---- +App_Settings_WiFi_t WiFiSettings = { + .SSID = "MyNetwork", + .Password = "MyPassword", + .AutoConnect = true +}; +SettingsManager_UpdateWiFi(&WiFiSettings); +SettingsManager_Save(); // Persist to NVS +---- + +**Event Subscription:** + +[source,c] +---- +esp_event_handler_register(SETTINGS_EVENTS, + SETTINGS_EVENT_WIFI_CHANGED, + &on_WiFi_Changed, NULL); +---- + +== Development Guidelines + +=== Code Style + +* **Style**: K&R with 4-space indentation +* **Line Length**: Maximum 120 characters +* **Naming**: PascalCase for functions, lowercase/PascalCase for variables +* **Documentation**: Complete Doxygen comments for all public functions +* **License**: GNU GPL v3.0 header in all files + +**Format Code:** + +[source,bash] +---- +pio run -t format +---- + +== Troubleshooting + +**Checklist:** + +1. Create module in appropriate directory (Manager/Task) +2. Define public API in header file with complete Doxygen documentation +3. Implement functionality in `.cpp` file +4. Add GPL v3 license header to all files +5. Register events if module posts events +6. Update relevant AsciiDoc documentation +7. Add configuration options to Settings if needed +8. Format code with AStyle +9. Test thoroughly (debug and release builds) + +== Troubleshooting + +=== Build Issues + +**"WebSocket support not enabled":** + +* Enable `CONFIG_HTTPD_WS_SUPPORT` in sdkconfig +* Ensure both debug and release sdkconfig have WS support + +**"Guru Meditation Error":** + +* Check stack sizes (increase if needed) +* Verify all pointers are valid before dereferencing +* Enable debug build for stack traces + +=== Runtime Issues + +**WiFi won't connect:** + +* Verify SSID and password in settings +* Check signal strength (RSSI) +* Ensure router supports 2.4 GHz (ESP32 doesn't support 5 GHz) +* Check max retry count and retry interval + +**Display not updating:** + +* Verify LVGL tick handler is running +* Check SPI bus configuration +* Ensure display backlight GPIO is correct + +**Thermal image frozen:** + +* Check Lepton Task is running +* Verify SPI communication with camera +* Perform camera FFC (Flat Field Correction) + +**WebSocket disconnects frequently:** + +* Increase ping interval +* Check WiFi stability +* Monitor memory usage (may be low) + +== Performance Optimization + +=== Memory Management + +* **PSRAM Usage**: Allocate large buffers (frame buffers, JSON parsing) in PSRAM +* **Heap Monitoring**: Use `heap_caps_get_free_size()` to monitor available memory +* **Stack Sizes**: Tune task stack sizes (too large wastes RAM, too small causes crashes) + +=== Frame Rate Optimization + +* **Camera**: Lepton 3.5 native rate is 8.6 Hz (cannot be increased) +* **Display**: Reduce LVGL animation complexity, enable DMA +* **Network**: Adjust JPEG compression quality vs. size tradeoff + +== Hardware Pinout + +=== ESP32-S3 Pin Assignment + +**Lepton Camera (SPI):** + +* CS: GPIO 10 +* MOSI: GPIO 11 +* MISO: GPIO 13 +* CLK: GPIO 12 + +**Display (SPI):** + +* CS: GPIO 15 +* DC: GPIO 21 +* RST: GPIO 48 +* Backlight: GPIO 45 + +**Touch (I2C):** + +* SDA: GPIO 18 +* SCL: GPIO 17 +* INT: GPIO 16 + +**SD Card (SPI):** + +* CS: GPIO 9 +* MOSI: GPIO 35 +* MISO: GPIO 37 +* CLK: GPIO 36 + +**RTC (I2C):** + +* SDA: GPIO 18 (shared with touch) +* SCL: GPIO 17 (shared with touch) + +== License and Copyright + +**License:** GNU General Public License v3.0 + +**Copyright:** © 2026 Daniel Kampert + +**Website:** www.kampis-elektroecke.de + +**Contact:** DanielKampert@kampis-elektroecke.de + +== Contributing + +Contributions are welcome! Please: + +1. Follow the code style guidelines +2. Add complete documentation for new APIs +3. Update AsciiDoc documentation when changing functionality +4. Test both debug and release builds +5. Format code with AStyle before committing + +== Version History + +* **v1.0.0** (2026-02-09) - Initial release + - Lepton 3.5 support + - Touch GUI with LVGL + - WiFi provisioning + - HTTP/WebSocket server + - VISA/SCPI server + - USB MSC support + - SD card image storage + +**Last Updated**: February 9, 2026 + +**Maintainer**: Daniel Kampert (DanielKampert@kampis-elektroecke.de) diff --git a/main/Application/Manager/Devices/ADC/adc.cpp b/main/Application/Manager/Devices/ADC/adc.cpp index 7e63b24..c38cc5c 100644 --- a/main/Application/Manager/Devices/ADC/adc.cpp +++ b/main/Application/Manager/Devices/ADC/adc.cpp @@ -34,23 +34,23 @@ #include #ifdef CONFIG_BATTERY_ADC_1 - #define ADC_UNIT ADC_UNIT_1 +#define ADC_UNIT ADC_UNIT_1 #elif CONFIG_BATTERY_ADC_2 - #define ADC_UNIT ADC_UNIT_2 +#define ADC_UNIT ADC_UNIT_2 #else - #error "No ADC channel configured for battery measurement" +#error "No ADC channel configured for battery measurement" #endif #ifdef CONFIG_BATTERY_ADC_ATT_0 - #define ADC_ATTEN ADC_ATTEN_DB_0 +#define ADC_ATTEN ADC_ATTEN_DB_0 #elif CONFIG_BATTERY_ADC_ATT_2_5 - #define ADC_ATTEN ADC_ATTEN_DB_2_5 +#define ADC_ATTEN ADC_ATTEN_DB_2_5 #elif CONFIG_BATTERY_ADC_ATT_6 - #define ADC_ATTEN ADC_ATTEN_DB_6 +#define ADC_ATTEN ADC_ATTEN_DB_6 #elif CONFIG_BATTERY_ADC_ATT_12 - #define ADC_ATTEN ADC_ATTEN_DB_12 +#define ADC_ATTEN ADC_ATTEN_DB_12 #else - #error "No ADC attenuation configured for battery measurement" +#error "No ADC attenuation configured for battery measurement" #endif static bool _ADC_Calib_Done = false; @@ -64,7 +64,7 @@ static adc_oneshot_unit_init_cfg_t _ADC_Init_Config = { .ulp_mode = ADC_ULP_MODE_DISABLE, }; -static adc_oneshot_chan_cfg_t ADC_Config = { +static adc_oneshot_chan_cfg_t _ADC_Config = { .atten = static_cast(ADC_ATTEN), .bitwidth = ADC_BITWIDTH_DEFAULT, }; @@ -76,17 +76,17 @@ esp_err_t ADC_Init(void) esp_err_t Error; ESP_ERROR_CHECK(adc_oneshot_new_unit(&_ADC_Init_Config, &_ADC_Handle)); - ESP_ERROR_CHECK(adc_oneshot_config_channel(_ADC_Handle, _ADC_Channel, &ADC_Config)); + ESP_ERROR_CHECK(adc_oneshot_config_channel(_ADC_Handle, _ADC_Channel, &_ADC_Config)); Error = ESP_OK; _ADC_Calib_Done = false; if (_ADC_Calib_Done == false) { - ESP_LOGD(TAG, "calibration scheme version is %s", "Curve Fitting"); + ESP_LOGD(TAG, "Calibration scheme version is %s", "Curve Fitting"); adc_cali_curve_fitting_config_t CaliConfig = { .unit_id = _ADC_Init_Config.unit_id, .chan = _ADC_Channel, - .atten = ADC_Config.atten, + .atten = _ADC_Config.atten, .bitwidth = ADC_BITWIDTH_DEFAULT, }; @@ -146,7 +146,8 @@ esp_err_t ADC_ReadBattery(int *p_Voltage, uint8_t *p_Percentage) } else if (*p_Voltage >= CONFIG_BATTERY_ADC_MAX_MV) { *p_Percentage = 100; } else { - *p_Percentage = (uint8_t)((*p_Voltage - CONFIG_BATTERY_ADC_MIN_MV) * 100 / (CONFIG_BATTERY_ADC_MAX_MV - CONFIG_BATTERY_ADC_MIN_MV)); + *p_Percentage = (uint8_t)((*p_Voltage - CONFIG_BATTERY_ADC_MIN_MV) * 100 / (CONFIG_BATTERY_ADC_MAX_MV - + CONFIG_BATTERY_ADC_MIN_MV)); } ESP_LOGD(TAG, "ADC%d Channel%d raw data: %d", ADC_UNIT_1, _ADC_Channel, Raw); diff --git a/main/Application/Manager/Devices/ADC/adc.h b/main/Application/Manager/Devices/ADC/adc.h index 8dc7e41..b640f27 100644 --- a/main/Application/Manager/Devices/ADC/adc.h +++ b/main/Application/Manager/Devices/ADC/adc.h @@ -29,20 +29,38 @@ #include -/** @brief Initializes the ADC driver. - * @return ESP_OK on success, error code otherwise +/** @brief Initializes the ADC driver for battery monitoring. + * Configures ADC channel for battery voltage measurement with + * calibration from eFuse. Uses internal voltage divider. + * @note ADC is calibrated using factory eFuse values. + * Battery voltage is measured through voltage divider. + * Call this after GPIO initialization. + * @return ESP_OK on success + * ESP_ERR_NO_MEM if memory allocation fails + * ESP_FAIL if ADC initialization fails */ esp_err_t ADC_Init(void); -/** @brief Deinitializes the ADC driver. - * @return ESP_OK on success, error code otherwise +/** @brief Deinitializes the ADC driver. + * Frees ADC resources and disables battery voltage monitoring. + * @note ADC readings become unavailable after this. + * @return ESP_OK on success + * ESP_FAIL if ADC cleanup fails */ esp_err_t ADC_Deinit(void); -/** @brief Read battery voltage and calculate percentage - * @param p_Voltage Pointer to store battery voltage in mV +/** @brief Read battery voltage and calculate percentage. + * Performs ADC reading, applies calibration, and calculates remaining + * battery percentage based on voltage curve for Li-Ion batteries. + * @note Voltage range: typically 3000mV (0%) to 4200mV (100%). + * Percentage uses standard Li-Ion discharge curve. + * Multiple samples are averaged for stability. + * @param p_Voltage Pointer to store battery voltage in millivolts (mV) * @param p_Percentage Pointer to store battery percentage (0-100%) - * @return ESP_OK on success, error code otherwise + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_ERR_INVALID_STATE if ADC not initialized + * ESP_FAIL if ADC read fails */ esp_err_t ADC_ReadBattery(int *p_Voltage, uint8_t *p_Percentage); diff --git a/main/Application/Manager/Devices/I2C/i2c.cpp b/main/Application/Manager/Devices/I2C/i2c.cpp index ecae397..0a8d1aa 100644 --- a/main/Application/Manager/Devices/I2C/i2c.cpp +++ b/main/Application/Manager/Devices/I2C/i2c.cpp @@ -51,6 +51,7 @@ int32_t I2CM_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_ if (_I2C_Mutex == NULL) { ESP_LOGE(TAG, "Failed to create I2C mutex!"); + return ESP_ERR_NO_MEM; } @@ -80,6 +81,7 @@ int32_t I2CM_Write(i2c_master_dev_handle_t *p_Dev_Handle, const uint8_t *p_Data, if ((p_Dev_Handle == NULL) || (*p_Dev_Handle == NULL) || (p_Data == NULL)) { ESP_LOGE(TAG, "I2C Write: Invalid handle or data pointer"); + return ESP_ERR_INVALID_ARG; } else if (Length == 0) { return ESP_OK; @@ -94,7 +96,9 @@ int32_t I2CM_Write(i2c_master_dev_handle_t *p_Dev_Handle, const uint8_t *p_Data, if (xSemaphoreTake(_I2C_Mutex, portMAX_DELAY) == pdTRUE) { Error = i2c_master_transmit(*p_Dev_Handle, p_Data, Length, I2C_WAIT); + xSemaphoreGive(_I2C_Mutex); + if (Error != ESP_OK) { ESP_LOGW(TAG, "I2C transmit failed: %d", Error); } @@ -115,6 +119,7 @@ int32_t I2CM_Read(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t *p_Data, uint32 if ((p_Dev_Handle == NULL) || (*p_Dev_Handle == NULL) || (p_Data == NULL)) { ESP_LOGE(TAG, "I2C Read: Invalid handle or data pointer"); + return ESP_ERR_INVALID_ARG; } else if (Length == 0) { return ESP_OK; @@ -130,9 +135,11 @@ int32_t I2CM_Read(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t *p_Data, uint32 if (xSemaphoreTake(_I2C_Mutex, portMAX_DELAY) == pdTRUE) { Error = i2c_master_receive(*p_Dev_Handle, p_Data, Length, I2C_WAIT); + xSemaphoreGive(_I2C_Mutex); + if (Error != ESP_OK) { - ESP_LOGW(TAG, "I2C receive failed: %d", Error); + ESP_LOGW(TAG, "I2C receive failed: %d!", Error); } } diff --git a/main/Application/Manager/Devices/I2C/i2c.h b/main/Application/Manager/Devices/I2C/i2c.h index 93bc158..6812076 100644 --- a/main/Application/Manager/Devices/I2C/i2c.h +++ b/main/Application/Manager/Devices/I2C/i2c.h @@ -31,26 +31,44 @@ #include -/** @brief Initialize the I2C driver. - * @param p_Config Pointer to configuration options +/** @brief Initialize the I2C master bus. + * Creates an I2C master bus with specified configuration (GPIO pins, + * clock speed, pullups, etc.). Bus can be shared by multiple devices. + * @note Configure GPIO pullups in p_Config if not hardware-pulled. + * Typical clock speeds: 100kHz (standard), 400kHz (fast). + * @param p_Config Pointer to i2c_master_bus_config_t configuration * @param p_Bus_Handle Pointer to store the created bus handle - * @return ESP_OK when successful + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL or config invalid + * ESP_ERR_NO_MEM if bus handle allocation fails + * ESP_FAIL if bus initialization fails */ int32_t I2CM_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_Bus_Handle); -/** @brief Deinitialize the I2C driver. - * @param Bus_Handle I2C bus handle - * @return ESP_OK when successful +/** @brief Deinitialize the I2C master bus. + * Removes the I2C bus and frees all associated resources. All device + * handles on this bus must be removed first. + * @note Remove all devices with i2c_master_bus_rm_device() first. + * @warning Bus handle becomes invalid after this call. + * @param Bus_Handle I2C bus handle to deinitialize + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if devices still attached + * ESP_FAIL if bus removal fails */ int32_t I2CM_Deinit(i2c_master_bus_handle_t Bus_Handle); /** @brief Transmit data over the I2C interface. + * Sends data to an I2C device. Uses blocking transmission with timeout. + * @note Default timeout: 1000ms. + * Device must be added to bus before calling this. * @param p_Dev_Handle Pointer to I2C device handle - * @param p_Data Pointer to data - * @param Length Length of data in bytes - * @return ESP_OK when successful - * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function - * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized + * @param p_Data Pointer to data buffer to transmit + * @param Length Number of bytes to transmit + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Dev_Handle or p_Data is NULL + * ESP_ERR_INVALID_STATE if I2C bus not initialized + * ESP_ERR_TIMEOUT if transaction times out + * ESP_FAIL if transmission fails (NACK, bus error) */ int32_t I2CM_Write(i2c_master_dev_handle_t *p_Dev_Handle, const uint8_t *p_Data, uint32_t Length); diff --git a/main/Application/Manager/Devices/PCA9633DP1/pca9633dp1.cpp b/main/Application/Manager/Devices/PCA9633DP1/pca9633dp1.cpp new file mode 100644 index 0000000..c52a084 --- /dev/null +++ b/main/Application/Manager/Devices/PCA9633DP1/pca9633dp1.cpp @@ -0,0 +1,456 @@ +/* + * pca9633dp1.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: PCA9633DP1 LED Driver implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include +#include + +#include "pca9633dp1.h" + +#include + +static const char *TAG = "PCA9633DP1"; + +/** @brief PCA9633 I2C address (ALLCALLADR pin configuration). + */ +#define PCA9633_I2C_ADDR 0x62 + +/** @brief PCA9633 register addresses. + */ +#define PCA9633_REG_MODE1 0x00 +#define PCA9633_REG_MODE2 0x01 +#define PCA9633_REG_PWM0 0x02 +#define PCA9633_REG_PWM1 0x03 +#define PCA9633_REG_PWM2 0x04 +#define PCA9633_REG_PWM3 0x05 +#define PCA9633_REG_GRPPWM 0x06 +#define PCA9633_REG_GRPFREQ 0x07 +#define PCA9633_REG_LEDOUT 0x08 +#define PCA9633_REG_SUBADR1 0x09 +#define PCA9633_REG_SUBADR2 0x0A +#define PCA9633_REG_SUBADR3 0x0B +#define PCA9633_REG_ALLCALLADR 0x0C + +/** @brief MODE1 register bit masks. + */ +#define PCA9633_MODE1_AI2 0x80 /**< Auto-Increment: All registers. */ +#define PCA9633_MODE1_AI1 0x40 /**< Auto-Increment: Individual brightness only. */ +#define PCA9633_MODE1_AI0 0x20 /**< Auto-Increment: Global control only. */ +#define PCA9633_MODE1_SLEEP 0x10 /**< Low power mode (oscillator off). */ +#define PCA9633_MODE1_SUB1 0x08 /**< Respond to subaddress 1. */ +#define PCA9633_MODE1_SUB2 0x04 /**< Respond to subaddress 2. */ +#define PCA9633_MODE1_SUB3 0x02 /**< Respond to subaddress 3. */ +#define PCA9633_MODE1_ALLCALL 0x01 /**< Respond to All Call I2C-bus address. */ + +/** @brief MODE2 register bit masks. + */ +#define PCA9633_MODE2_DMBLNK 0x20 /**< Group control: blinking (1) or dimming (0). */ +#define PCA9633_MODE2_INVRT 0x10 /**< Output logic state inverted. */ +#define PCA9633_MODE2_OCH 0x08 /**< Outputs change on ACK (0) or STOP (1). */ +#define PCA9633_MODE2_OUTDRV 0x04 /**< Output driver: totem pole (1) or open-drain (0). */ +#define PCA9633_MODE2_OUTNE1 0x02 /**< Output state when OE=1 (bit 1). */ +#define PCA9633_MODE2_OUTNE0 0x01 /**< Output state when OE=1 (bit 0). */ + +/** @brief LEDOUT register - LED driver output state. + */ +#define PCA9633_LEDOUT_OFF 0x00 /**< LED driver off. */ +#define PCA9633_LEDOUT_ON 0x01 /**< LED driver fully on (not PWM controlled). */ +#define PCA9633_LEDOUT_PWM 0x02 /**< LED driver individual PWM control. */ +#define PCA9633_LEDOUT_GRPPWM 0x03 /**< LED driver group PWM control. */ + +/** @brief Auto-Increment flag for register access. + */ +#define PCA9633_AUTO_INCREMENT 0x80 + +/** @brief Write a single register to PCA9633. + * @param p_Dev_Handle Device handle + * @param RegAddr Register address + * @param Value 8-bit value to write + * @return ESP_OK on success + */ +static esp_err_t pca9633_write_register(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t RegAddr, uint8_t Value) +{ + uint8_t Buffer[2]; + + Buffer[0] = RegAddr; + Buffer[1] = Value; + + return i2c_master_transmit(*p_Dev_Handle, Buffer, sizeof(Buffer), pdMS_TO_TICKS(1000)); +} + +/** @brief Read a single register from PCA9633. + * @param p_Dev_Handle Device handle + * @param RegAddr Register address + * @param p_Value Pointer to store the read value + * @return ESP_OK on success + */ +static esp_err_t pca9633_read_register(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t RegAddr, uint8_t *p_Value) +{ + esp_err_t Error; + + Error = i2c_master_transmit_receive(*p_Dev_Handle, &RegAddr, 1, p_Value, 1, pdMS_TO_TICKS(1000)); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read register 0x%02X: %d!", RegAddr, Error); + + return Error; + } + + return ESP_OK; +} + +/** @brief Write multiple registers to PCA9633 using auto-increment. + * @param p_Dev_Handle Device handle + * @param RegAddr Starting register address + * @param p_Data Pointer to data buffer + * @param Length Number of bytes to write + * @return ESP_OK on success + */ +static esp_err_t pca9633_write_registers(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t RegAddr, const uint8_t *p_Data, uint8_t Length) +{ + uint8_t Buffer[16]; + + if (Length > 15) { + ESP_LOGE(TAG, "Write length exceeds buffer size!"); + + return ESP_ERR_INVALID_ARG; + } + + /* Set auto-increment flag */ + Buffer[0] = RegAddr | PCA9633_AUTO_INCREMENT; + for (uint8_t i = 0; i < Length; i++) { + Buffer[i + 1] = p_Data[i]; + } + + return i2c_master_transmit(*p_Dev_Handle, Buffer, Length + 1, pdMS_TO_TICKS(1000)); +} + +esp_err_t PCA9633DP1_Init(i2c_master_bus_handle_t *p_Bus_Handle, i2c_master_dev_handle_t *p_Dev_Handle) +{ + esp_err_t Error; + i2c_device_config_t DevConfig; + + if ((p_Bus_Handle == NULL) || (p_Dev_Handle == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Configure I2C device */ + DevConfig.dev_addr_length = I2C_ADDR_BIT_LEN_7; + DevConfig.device_address = PCA9633_I2C_ADDR; + DevConfig.scl_speed_hz = 400000; + + /* Add device to bus */ + Error = i2c_master_bus_add_device(*p_Bus_Handle, &DevConfig, p_Dev_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to add I2C device: %d!", Error); + + return Error; + } + + /* Configure MODE1: Normal mode, enable All Call address */ + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_MODE1, PCA9633_MODE1_ALLCALL); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to configure MODE1: %d!", Error); + + i2c_master_bus_rm_device(*p_Dev_Handle); + + return Error; + } + + /* Wait for oscillator to start (500μs typical) */ + vTaskDelay(1 / portTICK_PERIOD_MS); + + /* Configure MODE2: Totem pole outputs, change on STOP command */ + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_MODE2, PCA9633_MODE2_OUTDRV); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to configure MODE2: %d!", Error); + + i2c_master_bus_rm_device(*p_Dev_Handle); + + return Error; + } + + /* Set all LEDs to off state */ + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_LEDOUT, 0x00); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set LEDOUT: %d!", Error); + + i2c_master_bus_rm_device(*p_Dev_Handle); + + return Error; + } + + /* Set all PWM registers to 0 (LEDs off) */ + uint8_t PWM_Values[4] = {0, 0, 0, 0}; + Error = pca9633_write_registers(p_Dev_Handle, PCA9633_REG_PWM0, PWM_Values, 4); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize PWM values: %d!", Error); + + i2c_master_bus_rm_device(*p_Dev_Handle); + + return Error; + } + + ESP_LOGI(TAG, "PCA9633DP1 initialized successfully"); + + return ESP_OK; +} + +esp_err_t PCA9633DP1_Deinit(i2c_master_dev_handle_t *p_Dev_Handle) +{ + esp_err_t Error; + + if (p_Dev_Handle == NULL) { + ESP_LOGE(TAG, "Invalid device handle!"); + + return ESP_ERR_INVALID_ARG; + } + + /* Turn off all LEDs before deinit */ + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_LEDOUT, 0x00); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to turn off LEDs: %d", Error); + } + + /* Remove device from bus */ + Error = i2c_master_bus_rm_device(*p_Dev_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to remove I2C device: %d!", Error); + + return Error; + } + + ESP_LOGI(TAG, "PCA9633DP1 deinitialized"); + + return ESP_OK; +} + +esp_err_t PCA9633DP1_SetLED(i2c_master_dev_handle_t *p_Dev_Handle, PCA9633_LED_t LED, uint8_t Brightness) +{ + uint8_t RegAddr; + uint8_t LEDOUT_Value; + esp_err_t Error; + + if (p_Dev_Handle == NULL) { + ESP_LOGE(TAG, "Invalid device handle!"); + + return ESP_ERR_INVALID_ARG; + } else if (LED > PCA9633_LED3) { + ESP_LOGE(TAG, "Invalid LED index!"); + + return ESP_ERR_INVALID_ARG; + } + + /* Determine PWM register address */ + RegAddr = PCA9633_REG_PWM0 + static_cast(LED); + + /* Write brightness value (0-255) */ + Error = pca9633_write_register(p_Dev_Handle, RegAddr, Brightness); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set LED%d brightness: %d!", LED, Error); + + return Error; + } + + /* Read current LEDOUT configuration */ + Error = pca9633_read_register(p_Dev_Handle, PCA9633_REG_LEDOUT, &LEDOUT_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read LEDOUT: %d!", Error); + + return Error; + } + + /* Set LED to PWM control mode */ + LEDOUT_Value &= ~(0x03 << (LED * 2)); /* Clear bits for this LED */ + LEDOUT_Value |= (PCA9633_LEDOUT_PWM << (LED * 2)); /* Set to PWM mode */ + + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_LEDOUT, LEDOUT_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to update LEDOUT: %d!", Error); + + return Error; + } + + return ESP_OK; +} + +esp_err_t PCA9633DP1_SetAllLEDs(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t LED0, uint8_t LED1, uint8_t LED2, uint8_t LED3) +{ + uint8_t PWM_Values[4]; + uint8_t LEDOUT_Value; + esp_err_t Error; + + if (p_Dev_Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Prepare PWM values */ + PWM_Values[0] = LED0; + PWM_Values[1] = LED1; + PWM_Values[2] = LED2; + PWM_Values[3] = LED3; + + /* Write all PWM values using auto-increment */ + Error = pca9633_write_registers(p_Dev_Handle, PCA9633_REG_PWM0, PWM_Values, 4); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set all LED brightness: %d!", Error); + + return Error; + } + + /* Set all LEDs to PWM control mode */ + LEDOUT_Value = (PCA9633_LEDOUT_PWM << 0) | /* LED0 */ + (PCA9633_LEDOUT_PWM << 2) | /* LED1 */ + (PCA9633_LEDOUT_PWM << 4) | /* LED2 */ + (PCA9633_LEDOUT_PWM << 6); /* LED3 */ + + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_LEDOUT, LEDOUT_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to update LEDOUT: %d!", Error); + + return Error; + } + + return ESP_OK; +} + +esp_err_t PCA9633DP1_SetLEDState(i2c_master_dev_handle_t *p_Dev_Handle, PCA9633_LED_t LED, PCA9633_LED_State_t State) +{ + uint8_t LEDOUT_Value; + esp_err_t Error; + + if (p_Dev_Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } else if (LED > PCA9633_LED3) { + return ESP_ERR_INVALID_ARG; + } + + /* Read current LEDOUT configuration */ + Error = pca9633_read_register(p_Dev_Handle, PCA9633_REG_LEDOUT, &LEDOUT_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read LEDOUT: %d!", Error); + + return Error; + } + + /* Update LED state */ + LEDOUT_Value &= ~(0x03 << (LED * 2)); /* Clear bits for this LED */ + LEDOUT_Value |= (State << (LED * 2)); /* Set new state */ + + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_LEDOUT, LEDOUT_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to update LEDOUT: %d!", Error); + + return Error; + } + + return ESP_OK; +} + +esp_err_t PCA9633DP1_SetGroupControl(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t GroupPWM, uint8_t GroupFreq, bool Blinking) +{ + esp_err_t Error; + uint8_t MODE2_Value; + + if (p_Dev_Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Set group PWM value (0-255 for dimming, or duty cycle for blinking) */ + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_GRPPWM, GroupPWM); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set GRPPWM: %d!", Error); + + return Error; + } + + /* Set group frequency (only used in blinking mode) */ + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_GRPFREQ, GroupFreq); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set GRPFREQ: %d!", Error); + + return Error; + } + + /* Configure MODE2 for blinking or dimming */ + Error = pca9633_read_register(p_Dev_Handle, PCA9633_REG_MODE2, &MODE2_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read MODE2: %d!", Error); + + return Error; + } + + if (Blinking) { + MODE2_Value |= PCA9633_MODE2_DMBLNK; + } else { + MODE2_Value &= ~PCA9633_MODE2_DMBLNK; + } + + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_MODE2, MODE2_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to update MODE2: %d!", Error); + + return Error; + } + + return ESP_OK; +} + +esp_err_t PCA9633DP1_SetSleepMode(i2c_master_dev_handle_t *p_Dev_Handle, bool Sleep) +{ + uint8_t MODE1_Value; + esp_err_t Error; + + if (p_Dev_Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Read current MODE1 value */ + Error = pca9633_read_register(p_Dev_Handle, PCA9633_REG_MODE1, &MODE1_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read MODE1: %d!", Error); + + return Error; + } + + /* Update sleep bit */ + if (Sleep) { + MODE1_Value |= PCA9633_MODE1_SLEEP; + } else { + MODE1_Value &= ~PCA9633_MODE1_SLEEP; + } + + Error = pca9633_write_register(p_Dev_Handle, PCA9633_REG_MODE1, MODE1_Value); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to update MODE1: %d!", Error); + + return Error; + } + + /* Wait for oscillator to stabilize when waking up */ + if (Sleep == false) { + vTaskDelay(1 / portTICK_PERIOD_MS); + } + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/Devices/PCA9633DP1/pca9633dp1.h b/main/Application/Manager/Devices/PCA9633DP1/pca9633dp1.h new file mode 100644 index 0000000..3373902 --- /dev/null +++ b/main/Application/Manager/Devices/PCA9633DP1/pca9633dp1.h @@ -0,0 +1,148 @@ +/* + * pca9633dp1.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: PCA9633DP1 LED Driver definition. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef PCA9633DP1_H_ +#define PCA9633DP1_H_ + +#include + +#include "../I2C/i2c.h" + +/** @brief LED channel identifier. + */ +typedef enum { + PCA9633_LED0 = 0, /**< LED channel 0. */ + PCA9633_LED1 = 1, /**< LED channel 1. */ + PCA9633_LED2 = 2, /**< LED channel 2. */ + PCA9633_LED3 = 3, /**< LED channel 3. */ +} PCA9633_LED_t; + +/** @brief LED output state. + */ +typedef enum { + PCA9633_LED_OFF = 0, /**< LED driver off (default power-up state). */ + PCA9633_LED_FULLY_ON = 1, /**< LED driver fully on (not PWM controlled). */ + PCA9633_LED_PWM = 2, /**< LED driver individual PWM + group PWM/dimming. */ + PCA9633_LED_PWM_GRPPWM = 3, /**< LED driver individual PWM + group blinking. */ +} PCA9633_LED_State_t; + +/** @brief Initializes the PCA9633DP1 LED driver. + * Creates I2C device handle and configures the PCA9633 for PWM LED control. + * Default configuration sets all LEDs to off state. + * @note I2C address: 0x62 (default for PCA9633). + * Supports 4 independent PWM channels. + * @param p_Bus_Handle Pointer to I2C bus handle + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_ERR_NO_MEM if device handle allocation fails + * ESP_FAIL if I2C communication fails + */ +esp_err_t PCA9633DP1_Init(i2c_master_bus_handle_t *p_Bus_Handle, i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Deinitializes the PCA9633DP1 LED driver. + * Removes I2C device handle and frees resources. LEDs are left in + * their current state. + * @note Device handle becomes invalid after this call. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Dev_Handle is NULL + * ESP_FAIL if I2C device removal fails + */ +esp_err_t PCA9633DP1_Deinit(i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Set brightness of a single LED channel. + * Sets the PWM duty cycle for the specified LED channel and enables + * PWM control mode. + * @note LED is automatically enabled in PWM control mode. + * Brightness range: 0 (off) to 255 (full brightness). + * @param p_Dev_Handle Pointer to I2C device handle + * @param LED LED channel (PCA9633_LED0 to PCA9633_LED3) + * @param Brightness PWM duty cycle (0-255) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if device handle NULL or invalid LED + * ESP_FAIL if I2C communication fails + */ +esp_err_t PCA9633DP1_SetLED(i2c_master_dev_handle_t *p_Dev_Handle, PCA9633_LED_t LED, uint8_t Brightness); + +/** @brief Set brightness of all LED channels simultaneously. + * Sets PWM duty cycle for all 4 LED channels using auto-increment + * and enables PWM control mode for all channels. + * @note More efficient than calling PCA9633DP1_SetLED() four times. + * All LEDs are automatically enabled in PWM control mode. + * @param p_Dev_Handle Pointer to I2C device handle + * @param LED0 Brightness for LED channel 0 (0-255) + * @param LED1 Brightness for LED channel 1 (0-255) + * @param LED2 Brightness for LED channel 2 (0-255) + * @param LED3 Brightness for LED channel 3 (0-255) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if device handle is NULL + * ESP_FAIL if I2C communication fails + */ +esp_err_t PCA9633DP1_SetAllLEDs(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t LED0, uint8_t LED1, uint8_t LED2, uint8_t LED3); + +/** @brief Set output state of an LED channel. + * Controls LED driver output state: off, fully on, PWM controlled, + * or PWM with group control. + * @note Use this to turn LED fully on/off without changing PWM value. + * PWM value is preserved when switching states. + * @param p_Dev_Handle Pointer to I2C device handle + * @param LED LED channel (PCA9633_LED0 to PCA9633_LED3) + * @param State Output state (see PCA9633_LED_State_t) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if device handle NULL or invalid LED + * ESP_FAIL if I2C communication fails + */ +esp_err_t PCA9633DP1_SetLEDState(i2c_master_dev_handle_t *p_Dev_Handle, PCA9633_LED_t LED, PCA9633_LED_State_t State); + +/** @brief Configure group PWM and blinking control. + * Sets up group control for global dimming or synchronized blinking + * of all LEDs set to group control mode. + * @note Only affects LEDs set to PCA9633_LED_PWM_GRPPWM state. + * Blinking frequency = GroupFreq / 24 Hz (e.g., 255 = 0.17 Hz). + * GroupPWM defines duty cycle in dimming mode or on-time in blink mode. + * @param p_Dev_Handle Pointer to I2C device handle + * @param GroupPWM Group PWM duty cycle (0-255) + * @param GroupFreq Group frequency for blinking (0-255), only used when Blinking=true + * @param Blinking true for blinking mode, false for dimming mode + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if device handle is NULL + * ESP_FAIL if I2C communication fails + */ +esp_err_t PCA9633DP1_SetGroupControl(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t GroupPWM, uint8_t GroupFreq, bool Blinking); + +/** @brief Enable or disable sleep mode (low power mode). + * In sleep mode, the internal oscillator is turned off and PWM + * generation stops. All register contents are preserved. + * @note Sleep mode reduces power consumption significantly. + * Wake-up time: ~500μs for oscillator to stabilize. + * LED outputs are held at their last state during sleep. + * @param p_Dev_Handle Pointer to I2C device handle + * @param Sleep true to enter sleep mode, false to wake up + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if device handle is NULL + * ESP_FAIL if I2C communication fails + */ +esp_err_t PCA9633DP1_SetSleepMode(i2c_master_dev_handle_t *p_Dev_Handle, bool Sleep); + +#endif /* PCA9633DP1_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/PortExpander/portexpander.cpp b/main/Application/Manager/Devices/PCAL6416AHF/pcal6416ahf.cpp similarity index 66% rename from main/Application/Manager/Devices/PortExpander/portexpander.cpp rename to main/Application/Manager/Devices/PCAL6416AHF/pcal6416ahf.cpp index 357e133..32d0aa4 100644 --- a/main/Application/Manager/Devices/PortExpander/portexpander.cpp +++ b/main/Application/Manager/Devices/PCAL6416AHF/pcal6416ahf.cpp @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Port Expander driver implementation. + * File info: PCAL6416AHF Port Expander driver implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ #include #include -#include "portexpander.h" +#include "pcal6416ahf.h" #include @@ -175,24 +175,25 @@ static i2c_device_config_t _Expander_I2C_Config = { }, }; -static i2c_master_dev_handle_t _Expander_Dev_Handle; - static const char *TAG = "PortExpander"; -/** @brief Set the pin level of the pins of a given port. - * @param Port Target port - * @param Mask Pin mask - * @param Level Pin level - * @return ESP_OK when successful - * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function - * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized +/** @brief Set the pin level of the pins of a given port. + * @param p_Dev_Handle Pointer to device handle + * @param Port Target port + * @param Mask Pin mask + * @param Level Pin level + * @return ESP_OK when successful + * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function + * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized */ -static esp_err_t PortExpander_SetPinLevel(PortDefinition_t Port, uint8_t Mask, uint8_t Level) +static esp_err_t PortExpander_SetPinLevel(i2c_master_dev_handle_t *p_Dev_Handle, PortDefinition_t Port, uint8_t Mask, + uint8_t Level) { - return I2CM_ModifyRegister(&_Expander_Dev_Handle, PORT_EXPANDER_REG_OUTPUT0 + static_cast(Port), Mask, Level); + return I2CM_ModifyRegister(p_Dev_Handle, PORT_EXPANDER_REG_OUTPUT0 + static_cast(Port), Mask, Level); } /** @brief Enable the interrupts for given pins. + * @param p_Dev_Handle Pointer to device handle * @param Port Target port * @param Mask Pin mask * @param EnableMask Interrupt enable mask @@ -200,78 +201,60 @@ static esp_err_t PortExpander_SetPinLevel(PortDefinition_t Port, uint8_t Mask, u * ESP_ERR_INVALID_ARG when an invalid argument is passed into the function * ESP_ERR_INVALID_STATE when the I2C interface isn´t initialized */ -static esp_err_t PortExpander_SetInterruptMask(PortDefinition_t Port, uint8_t Mask, uint8_t EnableMask) +static esp_err_t PortExpander_SetInterruptMask(i2c_master_dev_handle_t *p_Dev_Handle, PortDefinition_t Port, + uint8_t Mask, uint8_t EnableMask) { - return I2CM_ModifyRegister(&_Expander_Dev_Handle, PORT_EXPANDER_REG_INT_MASK0 + static_cast(Port), Mask, + return I2CM_ModifyRegister(p_Dev_Handle, PORT_EXPANDER_REG_INT_MASK0 + static_cast(Port), Mask, ~EnableMask); } -#ifdef DEBUG -void PortExpander_DumpRegister(void) -{ - uint8_t Data; - - ESP_LOGI(TAG, "Register dump:"); - - for (uint8_t i = 0x00; i < 0x08; i++) { - I2CM_Write(&_Expander_Dev_Handle, &i, sizeof(i)); - I2CM_Read(&_Expander_Dev_Handle, &Data, sizeof(Data)); - ESP_LOGI(TAG, " Register 0x%X: 0x%X", i, Data); - } - - for (uint8_t i = 0x40; i < 0x4F; i++) { - I2CM_Write(&_Expander_Dev_Handle, &i, sizeof(i)); - I2CM_Read(&_Expander_Dev_Handle, &Data, sizeof(Data)); - ESP_LOGI(TAG, " Register 0x%X: 0x%X", i, Data); - } -} -#endif - -esp_err_t PortExpander_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *Bus_Handle) +esp_err_t PortExpander_Init(i2c_master_bus_handle_t *p_Bus_Handle, i2c_master_dev_handle_t *p_Dev_Handle) { esp_err_t Error; - Error = i2c_master_bus_add_device(*Bus_Handle, &_Expander_I2C_Config, &_Expander_Dev_Handle); + Error = i2c_master_bus_add_device(*p_Bus_Handle, &_Expander_I2C_Config, p_Dev_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to add I2C device: %d!", Error); + return Error; } ESP_LOGI(TAG, "Configure Port Expander..."); - return I2CM_Write(&_Expander_Dev_Handle, DefaultPortConfiguration, sizeof(DefaultPortConfiguration)) || - I2CM_Write(&_Expander_Dev_Handle, DefaultPinConfiguration, sizeof(DefaultPinConfiguration)) || - I2CM_Write(&_Expander_Dev_Handle, DefaultPullConfig, sizeof(DefaultPullConfig)) || - I2CM_Write(&_Expander_Dev_Handle, DefaultLatchConfig, sizeof(DefaultLatchConfig)) || - I2CM_Write(&_Expander_Dev_Handle, DefaultPolarityConfig, sizeof(DefaultPolarityConfig)); + return I2CM_Write(p_Dev_Handle, DefaultPortConfiguration, sizeof(DefaultPortConfiguration)) || + I2CM_Write(p_Dev_Handle, DefaultPinConfiguration, sizeof(DefaultPinConfiguration)) || + I2CM_Write(p_Dev_Handle, DefaultPullConfig, sizeof(DefaultPullConfig)) || + I2CM_Write(p_Dev_Handle, DefaultLatchConfig, sizeof(DefaultLatchConfig)) || + I2CM_Write(p_Dev_Handle, DefaultPolarityConfig, sizeof(DefaultPolarityConfig)); } -esp_err_t PortExpander_Deinit(void) +esp_err_t PortExpander_Deinit(i2c_master_dev_handle_t *p_Dev_Handle) { - if (_Expander_Dev_Handle != NULL) { - esp_err_t Error = i2c_master_bus_rm_device(_Expander_Dev_Handle); + if (*p_Dev_Handle != NULL) { + esp_err_t Error = i2c_master_bus_rm_device(*p_Dev_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to remove I2C device: %d!", Error); return Error; } - _Expander_Dev_Handle = NULL; + *p_Dev_Handle = NULL; } return ESP_OK; } -esp_err_t PortExpander_EnableCamera(bool Enable) +esp_err_t PortExpander_EnableCamera(i2c_master_dev_handle_t *p_Dev_Handle, bool Enable) { - return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_CAMERA), (!Enable << PIN_CAMERA)); + return PortExpander_SetPinLevel(p_Dev_Handle, PORT_0, (0x01 << PIN_CAMERA), (!Enable << PIN_CAMERA)); } -esp_err_t PortExpander_EnableLED(bool Enable) +esp_err_t PortExpander_EnableLED(i2c_master_dev_handle_t *p_Dev_Handle, bool Enable) { - return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_LED), (Enable << PIN_LED)); + return PortExpander_SetPinLevel(p_Dev_Handle, PORT_0, (0x01 << PIN_LED), (Enable << PIN_LED)); } -esp_err_t PortExpander_EnableBatteryVoltage(bool Enable) +esp_err_t PortExpander_EnableBatteryVoltage(i2c_master_dev_handle_t *p_Dev_Handle, bool Enable) { - return PortExpander_SetPinLevel(PORT_0, (0x01 << PIN_BATTERY_VOLTAGE_ENABLE), (!Enable << PIN_BATTERY_VOLTAGE_ENABLE)); + return PortExpander_SetPinLevel(p_Dev_Handle, PORT_0, (0x01 << PIN_BATTERY_VOLTAGE_ENABLE), + (!Enable << PIN_BATTERY_VOLTAGE_ENABLE)); } diff --git a/main/Application/Manager/Devices/PCAL6416AHF/pcal6416ahf.h b/main/Application/Manager/Devices/PCAL6416AHF/pcal6416ahf.h new file mode 100644 index 0000000..1fba4f2 --- /dev/null +++ b/main/Application/Manager/Devices/PCAL6416AHF/pcal6416ahf.h @@ -0,0 +1,58 @@ +/* + * pcal6416ahf.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: PCAL6416AHF Port Expander driver definition. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef PCAL6416AHF_H_ +#define PCAL6416AHF_H_ + +#include + +#include "../I2C/i2c.h" + +/** @brief Initializes the port expander driver. + * @param p_Bus_Handle Pointer to I2C bus handle + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK on success, error code otherwise + */ +esp_err_t PortExpander_Init(i2c_master_bus_handle_t *p_Bus_Handle, i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Deinitializes the port expander driver. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK on success, error code otherwise + */ +esp_err_t PortExpander_Deinit(i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Enables or disables the LED (active high). + * @param p_Dev_Handle Pointer to device handle + * @param Enable true to enable the LED, false to disable it + * @return ESP_OK on success, error code otherwise + */ +esp_err_t PortExpander_EnableLED(i2c_master_dev_handle_t *p_Dev_Handle, bool Enable); + +/** @brief Enables or disables the battery voltage measurement (active low). + * @param p_Dev_Handle Pointer to device handle + * @param Enable true to enable battery voltage measurement, false to disable it + * @return ESP_OK on success, error code otherwise + */ +esp_err_t PortExpander_EnableBatteryVoltage(i2c_master_dev_handle_t *p_Dev_Handle, bool Enable); + +#endif /* PCAL6416AHF_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/PortExpander/portexpander.h b/main/Application/Manager/Devices/PortExpander/portexpander.h deleted file mode 100644 index 0128c1b..0000000 --- a/main/Application/Manager/Devices/PortExpander/portexpander.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * portexpander.h - * - * Copyright (C) Daniel Kampert, 2026 - * Website: www.kampis-elektroecke.de - * File info: GPIO port expander driver interface. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de - */ - -#ifndef PORTEXPANDER_H_ -#define PORTEXPANDER_H_ - -#include - -#include "../I2C/i2c.h" - -/** @brief Initializes the port expander driver. - * @param p_Config Pointer to the I2C master bus configuration. - * @param Bus_Handle Pointer to the I2C master bus handle. - * @return ESP_OK on success, error code otherwise - */ -esp_err_t PortExpander_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *Bus_Handle); - -/** @brief Deinitializes the port expander driver. - * @return ESP_OK on success, error code otherwise - */ -esp_err_t PortExpander_Deinit(void); - -#ifdef DEBUG -/** @brief Dump the content of the registers from the Port Expander. - */ -void PortExpander_DumpRegister(void); -#endif - -/** @brief Sets the port expander to its default configuration. - * @return ESP_OK on success, error code otherwise - */ -esp_err_t PortExpander_DefaultConfig(void); - -/** @brief Enables or disables the LED. - * @param Enable true to enable the LED, false to disable it. - * @return ESP_OK on success, error code otherwise - */ -esp_err_t PortExpander_EnableLED(bool Enable); - -/** @brief - * @param Enable true to enable battery voltage measurement, false to disable it. - * @return ESP_OK on success, error code otherwise - */ -esp_err_t PortExpander_EnableBatteryVoltage(bool Enable); - -#endif /* PORTEXPANDER_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/RTC/rtc.h b/main/Application/Manager/Devices/RTC/rtc.h deleted file mode 100644 index a84ad9b..0000000 --- a/main/Application/Manager/Devices/RTC/rtc.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * rtc.h - * - * Copyright (C) Daniel Kampert, 2026 - * Website: www.kampis-elektroecke.de - * File info: RV8263-C8 Real-Time Clock driver header. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de - */ - -#ifndef RTC_H_ -#define RTC_H_ - -#include -#include -#include - -#include - -#include "../I2C/i2c.h" - -/** @brief Alarm configuration structure. - */ -typedef struct { - uint8_t Seconds; /**< Alarm seconds (0-59) */ - uint8_t Minutes; /**< Alarm minutes (0-59) */ - uint8_t Hours; /**< Alarm hours (0-23) */ - uint8_t Day; /**< Alarm day of month (1-31) */ - uint8_t Weekday; /**< Alarm weekday (0-6) */ - bool EnableSeconds; /**< Enable seconds matching */ - bool EnableMinutes; /**< Enable minutes matching */ - bool EnableHours; /**< Enable hours matching */ - bool EnableDay; /**< Enable day matching */ - bool EnableWeekday; /**< Enable weekday matching */ -} RTC_Alarm_t; - -/** @brief Timer frequency options. - */ -typedef enum { - RTC_TIMER_FREQ_4096HZ = 0, /**< 4096 Hz (244 µs resolution) */ - RTC_TIMER_FREQ_64HZ = 1, /**< 64 Hz (15.625 ms resolution) */ - RTC_TIMER_FREQ_1HZ = 2, /**< 1 Hz (1 second resolution) */ - RTC_TIMER_FREQ_1_60HZ = 3, /**< 1/60 Hz (1 minute resolution) */ -} RTC_TimerFreq_t; - -/** @brief Initialize the RV8263-C8 RTC. - * @param p_Config Pointer to I2C bus configuration - * @param p_Bus_Handle Pointer to I2C bus handle - * @param p_Dev_Handle Pointer to store the created device handle - * @return ESP_OK when successful - */ -esp_err_t RTC_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_Bus_Handle, - i2c_master_dev_handle_t *p_Dev_Handle); - -/** @brief Deinitialize the RTC driver. - * @return ESP_OK when successful - */ -esp_err_t RTC_Deinit(void); - -/** @brief Get the current time from the RTC. - * @param p_Time Pointer to store the time - * @return ESP_OK when successful - */ -esp_err_t RTC_GetTime(struct tm *p_Time); - -/** @brief Set the time on the RTC. - * @param p_Time Pointer to the time to set - * @return ESP_OK when successful - */ -esp_err_t RTC_SetTime(const struct tm *p_Time); - -/** @brief Configure the alarm. - * @param p_Alarm Pointer to alarm configuration - * @return ESP_OK when successful - */ -esp_err_t RTC_SetAlarm(const RTC_Alarm_t *p_Alarm); - -/** @brief Enable or disable the alarm interrupt. - * @param Enable true to enable, false to disable - * @return ESP_OK when successful - */ -esp_err_t RTC_EnableAlarmInterrupt(bool Enable); - -/** @brief Clear the alarm flag. - * @return ESP_OK when successful - */ -esp_err_t RTC_ClearAlarmFlag(void); - -/** @brief Check if the alarm has been triggered. - * @return true if alarm flag is set - */ -bool RTC_IsAlarmTriggered(void); - -/** @brief Configure and start the countdown timer. - * @param Value Timer countdown value (0-255) - * @param Frequency Timer clock frequency - * @param InterruptEnable Enable timer interrupt - * @return ESP_OK when successful - */ -esp_err_t RTC_SetTimer(uint8_t Value, RTC_TimerFreq_t Frequency, bool InterruptEnable); - -/** @brief Stop the countdown timer. - * @return ESP_OK when successful - */ -esp_err_t RTC_StopTimer(void); - -/** @brief Perform a software reset of the RTC. - * @return ESP_OK when successful - */ -esp_err_t RTC_SoftwareReset(void); - -/** @brief Write a byte to the RAM register. - * @param Data Byte to write - * @return ESP_OK when successful - */ -esp_err_t RTC_WriteRAM(uint8_t Data); - -/** @brief Read a byte from the RAM register. - * @param p_Data Pointer to store the read byte - * @return ESP_OK when successful - */ -esp_err_t RTC_ReadRAM(uint8_t *p_Data); - -#ifdef DEBUG -/** @brief Dump all RTC registers for debugging. - */ -void RTC_DumpRegisters(void); -#endif - -#endif /* RTC_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/RTC/rtc.cpp b/main/Application/Manager/Devices/RV8263-C8/rv8263c8.cpp similarity index 69% rename from main/Application/Manager/Devices/RTC/rtc.cpp rename to main/Application/Manager/Devices/RV8263-C8/rv8263c8.cpp index 7f96a86..8907311 100644 --- a/main/Application/Manager/Devices/RTC/rtc.cpp +++ b/main/Application/Manager/Devices/RV8263-C8/rv8263c8.cpp @@ -1,5 +1,5 @@ /* - * rtc.cpp + * rv8263c8.cpp * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de @@ -27,7 +27,7 @@ #include #include -#include "rtc.h" +#include "rv8263c8.h" #include @@ -100,8 +100,6 @@ static i2c_device_config_t _RTC_I2C_Config = { }, }; -static i2c_master_dev_handle_t *_RTC_Dev_Handle = NULL; - static const char *TAG = "RTC"; /** @brief Convert BCD to binary. @@ -122,60 +120,66 @@ static uint8_t RTC_Bin2BCD(uint8_t Bin) return ((Bin / 10) << 4) | (Bin % 10); } -/** @brief Read a single register from the RTC. - * @param Register Register address - * @param p_Data Pointer to store the read value - * @return ESP_OK when successful +/** @brief Read a single register from the RTC. + * @param Register Register address + * @param p_Data Pointer to store the read value + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK when successful */ -static esp_err_t RTC_ReadRegister(uint8_t Register, uint8_t *p_Data) +static esp_err_t RTC_ReadRegister(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Register, uint8_t *p_Data) { esp_err_t Error; - Error = I2CM_Write(_RTC_Dev_Handle, &Register, 1); + Error = I2CM_Write(p_Dev_Handle, &Register, 1); if (Error != ESP_OK) { return Error; } - return I2CM_Read(_RTC_Dev_Handle, p_Data, 1); + return I2CM_Read(p_Dev_Handle, p_Data, 1); } -/** @brief Write a single register to the RTC. - * @param Register Register address - * @param Data Data to write - * @return ESP_OK when successful +/** @brief Write a single register to the RTC. + * @param Register Register address + * @param Data Data to write + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK when successful */ -static esp_err_t RTC_WriteRegister(uint8_t Register, uint8_t Data) +static esp_err_t RTC_WriteRegister(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Register, uint8_t Data) { uint8_t Buffer[2] = {Register, Data}; - return I2CM_Write(_RTC_Dev_Handle, Buffer, sizeof(Buffer)); + return I2CM_Write(p_Dev_Handle, Buffer, sizeof(Buffer)); } -/** @brief Read multiple consecutive registers from the RTC. - * @param Register Starting register address - * @param p_Data Pointer to store the read values - * @param Length Number of bytes to read - * @return ESP_OK when successful +/** @brief Read multiple consecutive registers from the RTC. + * @param Register Starting register address + * @param p_Data Pointer to store the read values + * @param Length Number of bytes to read + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK when successful */ -static esp_err_t RTC_ReadRegisters(uint8_t Register, uint8_t *p_Data, uint8_t Length) +static esp_err_t RTC_ReadRegisters(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Register, uint8_t *p_Data, + uint8_t Length) { esp_err_t Error; - Error = I2CM_Write(_RTC_Dev_Handle, &Register, 1); + Error = I2CM_Write(p_Dev_Handle, &Register, 1); if (Error != ESP_OK) { return Error; } - return I2CM_Read(_RTC_Dev_Handle, p_Data, Length); + return I2CM_Read(p_Dev_Handle, p_Data, Length); } -/** @brief Write multiple consecutive registers to the RTC. - * @param Register Starting register address - * @param p_Data Pointer to data to write - * @param Length Number of bytes to write - * @return ESP_OK when successful +/** @brief Write multiple consecutive registers to the RTC. + * @param Register Starting register address + * @param p_Data Pointer to data to write + * @param Length Number of bytes to write + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK when successful */ -static esp_err_t RTC_WriteRegisters(uint8_t Register, const uint8_t *p_Data, uint8_t Length) +static esp_err_t RTC_WriteRegisters(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Register, const uint8_t *p_Data, + uint8_t Length) { uint8_t Buffer[MAX_RTC_REGS + 1]; @@ -186,14 +190,11 @@ static esp_err_t RTC_WriteRegisters(uint8_t Register, const uint8_t *p_Data, uin Buffer[0] = Register; memcpy(&Buffer[1], p_Data, Length); - return I2CM_Write(_RTC_Dev_Handle, Buffer, Length + 1); + return I2CM_Write(p_Dev_Handle, Buffer, Length + 1); } -esp_err_t RTC_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p_Bus_Handle, - i2c_master_dev_handle_t *p_Dev_Handle) +esp_err_t RTC_Init(i2c_master_bus_handle_t *p_Bus_Handle, i2c_master_dev_handle_t *p_Dev_Handle) { - (void)p_Config; - esp_err_t Error; uint8_t Control1; uint8_t Seconds; @@ -204,38 +205,40 @@ esp_err_t RTC_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p return Error; } - _RTC_Dev_Handle = p_Dev_Handle; - ESP_LOGD(TAG, "Initialize RV8263-C8 RTC..."); /* Check oscillator stop flag */ - Error = RTC_ReadRegister(RV8263_REG_SECONDS, &Seconds); + Error = RTC_ReadRegister(p_Dev_Handle, RV8263_REG_SECONDS, &Seconds); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to read seconds register: %d", Error); + return Error; } if (Seconds & RV8263_SECONDS_OS) { ESP_LOGW(TAG, "Oscillator was stopped - time may be invalid!"); + /* Clear OS flag by writing seconds register */ - Error = RTC_WriteRegister(RV8263_REG_SECONDS, Seconds & ~RV8263_SECONDS_OS); + Error = RTC_WriteRegister(p_Dev_Handle, RV8263_REG_SECONDS, Seconds & ~RV8263_SECONDS_OS); if (Error != ESP_OK) { return Error; } } /* Read Control1 register */ - Error = RTC_ReadRegister(RV8263_REG_CONTROL1, &Control1); + Error = RTC_ReadRegister(p_Dev_Handle, RV8263_REG_CONTROL1, &Control1); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to read control register: %d", Error); + return Error; } /* Ensure oscillator is running */ if (Control1 & RV8263_CTRL1_STOP) { ESP_LOGD(TAG, "Starting RTC oscillator..."); + Control1 &= ~RV8263_CTRL1_STOP; - Error = RTC_WriteRegister(RV8263_REG_CONTROL1, Control1); + Error = RTC_WriteRegister(p_Dev_Handle, RV8263_REG_CONTROL1, Control1); if (Error != ESP_OK) { return Error; } @@ -246,36 +249,38 @@ esp_err_t RTC_Init(i2c_master_bus_config_t *p_Config, i2c_master_bus_handle_t *p return ESP_OK; } -esp_err_t RTC_Deinit(void) +esp_err_t RTC_Deinit(i2c_master_dev_handle_t *p_Dev_Handle) { - if (_RTC_Dev_Handle != NULL) { + if (p_Dev_Handle != NULL) { esp_err_t Error; - Error = i2c_master_bus_rm_device(*_RTC_Dev_Handle); + Error = i2c_master_bus_rm_device(*p_Dev_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to remove I2C device: %d!", Error); + return Error; } - _RTC_Dev_Handle = NULL; + p_Dev_Handle = NULL; } return ESP_OK; } -esp_err_t RTC_GetTime(struct tm *p_Time) +esp_err_t RTC_GetTime(i2c_master_dev_handle_t *p_Dev_Handle, struct tm *p_Time) { esp_err_t Error; uint8_t Buffer[7]; - if ((p_Time == NULL) || (_RTC_Dev_Handle == NULL)) { + if ((p_Time == NULL) || (p_Dev_Handle == NULL)) { return ESP_ERR_INVALID_ARG; } /* Read time registers (Seconds to Year) */ - Error = RTC_ReadRegisters(RV8263_REG_SECONDS, Buffer, sizeof(Buffer)); + Error = RTC_ReadRegisters(p_Dev_Handle, RV8263_REG_SECONDS, Buffer, sizeof(Buffer)); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to read time: %d!", Error); + return Error; } @@ -302,13 +307,13 @@ esp_err_t RTC_GetTime(struct tm *p_Time) return ESP_OK; } -esp_err_t RTC_SetTime(const struct tm *p_Time) +esp_err_t RTC_SetTime(i2c_master_dev_handle_t *p_Dev_Handle, const struct tm *p_Time) { uint8_t Buffer[7]; int Year; int Month; - if ((p_Time == NULL) || (_RTC_Dev_Handle == NULL)) { + if ((p_Time == NULL) || (p_Dev_Handle == NULL)) { return ESP_ERR_INVALID_ARG; } @@ -343,14 +348,14 @@ esp_err_t RTC_SetTime(const struct tm *p_Time) Year, Month, p_Time->tm_mday, p_Time->tm_hour, p_Time->tm_min, p_Time->tm_sec); - return RTC_WriteRegisters(RV8263_REG_SECONDS, Buffer, sizeof(Buffer)); + return RTC_WriteRegisters(p_Dev_Handle, RV8263_REG_SECONDS, Buffer, sizeof(Buffer)); } -esp_err_t RTC_SetAlarm(const RTC_Alarm_t *p_Alarm) +esp_err_t RTC_SetAlarm(i2c_master_dev_handle_t *p_Dev_Handle, const RTC_Alarm_t *p_Alarm) { uint8_t Buffer[5]; - if ((p_Alarm == NULL) || (_RTC_Dev_Handle == NULL)) { + if ((p_Alarm == NULL) || (p_Dev_Handle == NULL)) { return ESP_ERR_INVALID_ARG; } @@ -361,43 +366,45 @@ esp_err_t RTC_SetAlarm(const RTC_Alarm_t *p_Alarm) Buffer[3] = p_Alarm->EnableDay ? RTC_Bin2BCD(p_Alarm->Day) : RV8263_ALARM_AE; Buffer[4] = p_Alarm->EnableWeekday ? p_Alarm->Weekday : RV8263_ALARM_AE; - return RTC_WriteRegisters(RV8263_REG_SECONDS_ALARM, Buffer, sizeof(Buffer)); + return RTC_WriteRegisters(p_Dev_Handle, RV8263_REG_SECONDS_ALARM, Buffer, sizeof(Buffer)); } -esp_err_t RTC_EnableAlarmInterrupt(bool Enable) +esp_err_t RTC_EnableAlarmInterrupt(i2c_master_dev_handle_t *p_Dev_Handle, bool Enable) { - return I2CM_ModifyRegister(_RTC_Dev_Handle, RV8263_REG_CONTROL2, RV8263_CTRL2_AIE, + return I2CM_ModifyRegister(p_Dev_Handle, RV8263_REG_CONTROL2, RV8263_CTRL2_AIE, Enable ? RV8263_CTRL2_AIE : 0); } -esp_err_t RTC_ClearAlarmFlag(void) +esp_err_t RTC_ClearAlarmFlag(i2c_master_dev_handle_t *p_Dev_Handle) { - return I2CM_ModifyRegister(_RTC_Dev_Handle, RV8263_REG_CONTROL2, RV8263_CTRL2_AF, 0); + return I2CM_ModifyRegister(p_Dev_Handle, RV8263_REG_CONTROL2, RV8263_CTRL2_AF, 0); } -bool RTC_IsAlarmTriggered(void) +bool RTC_IsAlarmTriggered(i2c_master_dev_handle_t *p_Dev_Handle) { uint8_t Control2; - if (RTC_ReadRegister(RV8263_REG_CONTROL2, &Control2) != ESP_OK) { - ESP_LOGE(TAG, "Failed to read Control2 register for alarm status"); + if (RTC_ReadRegister(p_Dev_Handle, RV8263_REG_CONTROL2, &Control2) != ESP_OK) { + ESP_LOGE(TAG, "Failed to read Control2 register for alarm status!"); + return false; } return (Control2 & RV8263_CTRL2_AF) != 0; } -esp_err_t RTC_SetTimer(uint8_t Value, RTC_TimerFreq_t Frequency, bool InterruptEnable) +esp_err_t RTC_SetTimer(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Value, RTC_TimerFreq_t Frequency, + bool InterruptEnable) { esp_err_t Error; uint8_t TimerMode; - if (_RTC_Dev_Handle == NULL) { + if (p_Dev_Handle == NULL) { return ESP_ERR_INVALID_STATE; } /* Set timer value */ - Error = RTC_WriteRegister(RV8263_REG_TIMER_VALUE, Value); + Error = RTC_WriteRegister(p_Dev_Handle, RV8263_REG_TIMER_VALUE, Value); if (Error != ESP_OK) { return Error; } @@ -408,44 +415,30 @@ esp_err_t RTC_SetTimer(uint8_t Value, RTC_TimerFreq_t Frequency, bool InterruptE TimerMode |= RV8263_TIMER_TIE; } - return RTC_WriteRegister(RV8263_REG_TIMER_MODE, TimerMode); + return RTC_WriteRegister(p_Dev_Handle, RV8263_REG_TIMER_MODE, TimerMode); } -esp_err_t RTC_StopTimer(void) +esp_err_t RTC_StopTimer(i2c_master_dev_handle_t *p_Dev_Handle) { - return RTC_WriteRegister(RV8263_REG_TIMER_MODE, 0); + return RTC_WriteRegister(p_Dev_Handle, RV8263_REG_TIMER_MODE, 0); } -esp_err_t RTC_SoftwareReset(void) +esp_err_t RTC_SoftwareReset(i2c_master_dev_handle_t *p_Dev_Handle) { ESP_LOGD(TAG, "Performing software reset..."); - return RTC_WriteRegister(RV8263_REG_CONTROL1, RV8263_CTRL1_SR); -} - -esp_err_t RTC_WriteRAM(uint8_t Data) -{ - return RTC_WriteRegister(RV8263_REG_RAM, Data); -} - -esp_err_t RTC_ReadRAM(uint8_t *p_Data) -{ - if (p_Data == NULL) { - return ESP_ERR_INVALID_ARG; - } - - return RTC_ReadRegister(RV8263_REG_RAM, p_Data); + return RTC_WriteRegister(p_Dev_Handle, RV8263_REG_CONTROL1, RV8263_CTRL1_SR); } #ifdef DEBUG -void RTC_DumpRegisters(void) +void RTC_DumpRegisters(i2c_master_dev_handle_t *p_Dev_Handle) { uint8_t Data; ESP_LOGI(TAG, "Register dump:"); for (uint8_t i = 0x00; i <= 0x11; i++) { - if (RTC_ReadRegister(i, &Data) == ESP_OK) { + if (RTC_ReadRegister(p_Dev_Handle, i, &Data) == ESP_OK) { ESP_LOGI(TAG, " Register 0x%02X: 0x%02X", i, Data); } } diff --git a/main/Application/Manager/Devices/RV8263-C8/rv8263c8.h b/main/Application/Manager/Devices/RV8263-C8/rv8263c8.h new file mode 100644 index 0000000..f641737 --- /dev/null +++ b/main/Application/Manager/Devices/RV8263-C8/rv8263c8.h @@ -0,0 +1,141 @@ +/* + * rv8263c8.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: RV8263-C8 Real-Time Clock driver definition. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef RV8263C8_H_ +#define RV8263C8_H_ + +#include + +#include +#include +#include + +#include "../I2C/i2c.h" + +/** @brief Alarm configuration structure. + */ +typedef struct { + uint8_t Seconds; /**< Alarm seconds (0-59) */ + uint8_t Minutes; /**< Alarm minutes (0-59) */ + uint8_t Hours; /**< Alarm hours (0-23) */ + uint8_t Day; /**< Alarm day of month (1-31) */ + uint8_t Weekday; /**< Alarm weekday (0-6) */ + bool EnableSeconds; /**< Enable seconds matching */ + bool EnableMinutes; /**< Enable minutes matching */ + bool EnableHours; /**< Enable hours matching */ + bool EnableDay; /**< Enable day matching */ + bool EnableWeekday; /**< Enable weekday matching */ +} RTC_Alarm_t; + +/** @brief Timer frequency options. + */ +typedef enum { + RTC_TIMER_FREQ_4096HZ = 0, /**< 4096 Hz (244 µs resolution) */ + RTC_TIMER_FREQ_64HZ = 1, /**< 64 Hz (15.625 ms resolution) */ + RTC_TIMER_FREQ_1HZ = 2, /**< 1 Hz (1 second resolution) */ + RTC_TIMER_FREQ_1_60HZ = 3, /**< 1/60 Hz (1 minute resolution) */ +} RTC_TimerFreq_t; + +/** @brief Initialize the RV8263-C8 RTC. + * @param p_Bus_Handle Pointer to I2C bus handle + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK when successful + */ +esp_err_t RTC_Init(i2c_master_bus_handle_t *p_Bus_Handle, i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Deinitialize the RTC driver. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK when successful + */ +esp_err_t RTC_Deinit(i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Get the current time from the RTC. + * @param p_Dev_Handle Pointer to device handle + * @param p_Time Pointer to store the time + * @return ESP_OK when successful + */ +esp_err_t RTC_GetTime(i2c_master_dev_handle_t *p_Dev_Handle, struct tm *p_Time); + +/** @brief Set the time on the RTC. + * @param p_Dev_Handle Pointer to device handle + * @param p_Time Pointer to the time to set + * @return ESP_OK when successful + */ +esp_err_t RTC_SetTime(i2c_master_dev_handle_t *p_Dev_Handle, const struct tm *p_Time); + +/** @brief Configure the alarm. + * @param p_Dev_Handle Pointer to device handle + * @param p_Alarm Pointer to alarm configuration + * @return ESP_OK when successful + */ +esp_err_t RTC_SetAlarm(i2c_master_dev_handle_t *p_Dev_Handle, const RTC_Alarm_t *p_Alarm); + +/** @brief Enable or disable the alarm interrupt. + * @param p_Dev_Handle Pointer to device handle + * @param Enable true to enable, false to disable + * @return ESP_OK when successful + */ +esp_err_t RTC_EnableAlarmInterrupt(i2c_master_dev_handle_t *p_Dev_Handle, bool Enable); + +/** @brief Clear the alarm flag. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK when successful + */ +esp_err_t RTC_ClearAlarmFlag(i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Check if the alarm has been triggered. + * @param p_Dev_Handle Pointer to device handle + * @return true if alarm is triggered, false otherwise + */ +bool RTC_IsAlarmTriggered(i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Configure and start the countdown timer. + * @param p_Dev_Handle Pointer to device handle + * @param Value Timer countdown value (0-255) + * @param Frequency Timer clock frequency + * @param InterruptEnable Enable timer interrupt + * @return ESP_OK when successful + */ +esp_err_t RTC_SetTimer(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t Value, RTC_TimerFreq_t Frequency, + bool InterruptEnable); + +/** @brief Stop the countdown timer. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK when successful + */ +esp_err_t RTC_StopTimer(i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Perform a software reset of the RTC. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK when successful + */ +esp_err_t RTC_SoftwareReset(i2c_master_dev_handle_t *p_Dev_Handle); + +#ifdef DEBUG +/** @brief Dump all RTC registers for debugging. + * @param p_Dev_Handle Pointer to device handle + */ +void RTC_DumpRegisters(i2c_master_dev_handle_t *p_Dev_Handle); +#endif + +#endif /* RV8263C8_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/SPI/spi.cpp b/main/Application/Manager/Devices/SPI/spi.cpp index 1446650..e8e62a3 100644 --- a/main/Application/Manager/Devices/SPI/spi.cpp +++ b/main/Application/Manager/Devices/SPI/spi.cpp @@ -58,6 +58,7 @@ esp_err_t SPIM_Init(const spi_bus_config_t *p_Config, spi_host_device_t Host, in /* Check if already initialized */ if (_SPI_State[Host].isInitialized) { ESP_LOGW(TAG, "SPI%d already initialized", Host + 1); + return ESP_ERR_INVALID_STATE; } @@ -65,6 +66,7 @@ esp_err_t SPIM_Init(const spi_bus_config_t *p_Config, spi_host_device_t Host, in _SPI_State[Host].Mutex = xSemaphoreCreateMutex(); if (_SPI_State[Host].Mutex == NULL) { ESP_LOGE(TAG, "Failed to create SPI%d mutex!", Host + 1); + return ESP_ERR_NO_MEM; } @@ -72,15 +74,17 @@ esp_err_t SPIM_Init(const spi_bus_config_t *p_Config, spi_host_device_t Host, in Error = spi_bus_initialize(Host, p_Config, DMA_Channel); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize SPI%d bus: %d", Host + 1, Error); + vSemaphoreDelete(_SPI_State[Host].Mutex); _SPI_State[Host].Mutex = NULL; + return Error; } _SPI_State[Host].isInitialized = true; _SPI_State[Host].DeviceCount = 0; - ESP_LOGI(TAG, "SPI%d bus initialized successfully", Host + 1); + ESP_LOGD(TAG, "SPI%d bus initialized successfully", Host + 1); return ESP_OK; } @@ -120,7 +124,7 @@ esp_err_t SPIM_Deinit(spi_host_device_t Host) _SPI_State[Host].isInitialized = false; _SPI_State[Host].DeviceCount = 0; - ESP_LOGI(TAG, "SPI%d bus deinitialized", Host + 1); + ESP_LOGD(TAG, "SPI%d bus deinitialized", Host + 1); return ESP_OK; } @@ -155,7 +159,7 @@ esp_err_t SPIM_AddDevice(spi_host_device_t Host, const spi_device_interface_conf _SPI_State[Host].DeviceCount++; xSemaphoreGive(_SPI_State[Host].Mutex); - ESP_LOGI(TAG, "Device added to SPI%d (total: %d devices)", Host + 1, _SPI_State[Host].DeviceCount); + ESP_LOGD(TAG, "Device added to SPI%d (total: %d devices)", Host + 1, _SPI_State[Host].DeviceCount); return ESP_OK; } @@ -182,7 +186,7 @@ esp_err_t SPIM_RemoveDevice(spi_host_device_t Host, spi_device_handle_t Handle) xSemaphoreGive(_SPI_State[Host].Mutex); - ESP_LOGI(TAG, "SPI device removed"); + ESP_LOGD(TAG, "SPI device removed"); return ESP_OK; } diff --git a/main/Application/Manager/Devices/TMP117/tmp117.cpp b/main/Application/Manager/Devices/TMP117/tmp117.cpp new file mode 100644 index 0000000..6a041c2 --- /dev/null +++ b/main/Application/Manager/Devices/TMP117/tmp117.cpp @@ -0,0 +1,373 @@ +/* + * tmp117.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: TMP117 Temperature Sensor driver implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include +#include + +#include "tmp117.h" + +#include + +static const char *TAG = "TMP117"; + +/** @brief TMP117 I2C address (ADD0 pin connected to GND). + */ +#define TMP117_I2C_ADDR 0x48 + +/** @brief TMP117 register addresses. + */ +#define TMP117_REG_TEMP_RESULT 0x00 +#define TMP117_REG_CONFIGURATION 0x01 +#define TMP117_REG_T_HIGH_LIMIT 0x02 +#define TMP117_REG_T_LOW_LIMIT 0x03 +#define TMP117_REG_EEPROM_UL 0x04 +#define TMP117_REG_EEPROM1 0x05 +#define TMP117_REG_EEPROM2 0x06 +#define TMP117_REG_TEMP_OFFSET 0x07 +#define TMP117_REG_EEPROM3 0x08 +#define TMP117_REG_DEVICE_ID 0x0F + +/** @brief Configuration register bit masks. + */ +#define TMP117_CFG_MOD_MASK 0x0C00 +#define TMP117_CFG_MOD_SHIFT 10 +#define TMP117_CFG_CONV_MASK 0x01C0 +#define TMP117_CFG_CONV_SHIFT 7 +#define TMP117_CFG_AVG_MASK 0x0060 +#define TMP117_CFG_AVG_SHIFT 5 +#define TMP117_CFG_DATA_READY 0x2000 +#define TMP117_CFG_SOFT_RESET 0x0002 + +/** @brief TMP117 device ID expected value. + */ +#define TMP117_DEVICE_ID 0x0117 + +/** @brief Temperature resolution in °C per LSB. + */ +#define TMP117_RESOLUTION 0.0078125f + +/** @brief Write a 16-bit register to TMP117. + * @param p_Dev_Handle Device handle + * @param RegAddr Register address + * @param Value 16-bit value to write + * @return ESP_OK on success + */ +static esp_err_t TMP117_Write_Register(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t RegAddr, uint16_t Value) +{ + uint8_t Buffer[3]; + + Buffer[0] = RegAddr; + Buffer[1] = (uint8_t)((Value >> 8) & 0xFF); + Buffer[2] = (uint8_t)(Value & 0xFF); + + return i2c_master_transmit(*p_Dev_Handle, Buffer, sizeof(Buffer), pdMS_TO_TICKS(1000)); +} + +/** @brief Read a 16-bit register from TMP117. + * @param p_Dev_Handle Device handle + * @param RegAddr Register address + * @param p_Value Pointer to store the read value + * @return ESP_OK on success + */ +static esp_err_t TMP117_Read_Register(i2c_master_dev_handle_t *p_Dev_Handle, uint8_t RegAddr, uint16_t *p_Value) +{ + uint8_t Buffer[2]; + esp_err_t Error; + + Error = i2c_master_transmit_receive(*p_Dev_Handle, &RegAddr, 1, Buffer, sizeof(Buffer), pdMS_TO_TICKS(1000)); + if (Error != ESP_OK) { + return Error; + } + + *p_Value = ((uint16_t)Buffer[0] << 8) | Buffer[1]; + + return ESP_OK; +} + +esp_err_t TMP117_Init(i2c_master_bus_handle_t *p_Bus_Handle, i2c_master_dev_handle_t *p_Dev_Handle) +{ + esp_err_t Error; + uint16_t DeviceID; + + if ((p_Bus_Handle == NULL) || (p_Dev_Handle == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Create I2C device handle */ + i2c_device_config_t DevConfig = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = TMP117_I2C_ADDR, + .scl_speed_hz = 400000, + }; + + Error = i2c_master_bus_add_device(*p_Bus_Handle, &DevConfig, p_Dev_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to add I2C device: %d!", Error); + + return Error; + } + + /* Verify device ID */ + Error = TMP117_ReadDeviceID(p_Dev_Handle, &DeviceID); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read device ID: %d!", Error); + + i2c_master_bus_rm_device(*p_Dev_Handle); + + return Error; + } + + if (DeviceID != TMP117_DEVICE_ID) { + ESP_LOGE(TAG, "Invalid device ID: 0x%04X (expected 0x%04X)!", DeviceID, TMP117_DEVICE_ID); + + i2c_master_bus_rm_device(*p_Dev_Handle); + + return ESP_ERR_NOT_FOUND; + } + + ESP_LOGI(TAG, "TMP117 initialized successfully (ID: 0x%04X)", DeviceID); + + /* Configure default settings: Continuous mode, 1 second cycle, no averaging */ + TMP117_Config_t DefaultConfig = { + .Mode = TMP117_MODE_CONTINUOUS, + .Cycle = TMP117_CYCLE_1S, + .Averaging = TMP117_AVG_NONE, + }; + + Error = TMP117_Configure(p_Dev_Handle, &DefaultConfig); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to configure default settings: %d!", Error); + + i2c_master_bus_rm_device(*p_Dev_Handle); + + return Error; + } + + return ESP_OK; +} + +esp_err_t TMP117_Deinit(i2c_master_dev_handle_t *p_Dev_Handle) +{ + if ((p_Dev_Handle == NULL) || (*p_Dev_Handle == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t Error = i2c_master_bus_rm_device(*p_Dev_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to remove I2C device: %d!", Error); + + return Error; + } + + ESP_LOGI(TAG, "TMP117 deinitialized"); + + return ESP_OK; +} + +esp_err_t TMP117_Configure(i2c_master_dev_handle_t *p_Dev_Handle, const TMP117_Config_t *p_Config) +{ + uint16_t ConfigReg; + esp_err_t Error; + + if ((p_Dev_Handle == NULL) || (p_Config == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Read current configuration */ + Error = TMP117_Read_Register(p_Dev_Handle, TMP117_REG_CONFIGURATION, &ConfigReg); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read configuration register: %d!", Error); + + return Error; + } + + /* Clear mode, conversion cycle, and averaging bits */ + ConfigReg &= ~(TMP117_CFG_MOD_MASK | TMP117_CFG_CONV_MASK | TMP117_CFG_AVG_MASK); + + /* Set new configuration */ + ConfigReg |= ((uint16_t)p_Config->Mode << TMP117_CFG_MOD_SHIFT) & TMP117_CFG_MOD_MASK; + ConfigReg |= ((uint16_t)p_Config->Cycle << TMP117_CFG_CONV_SHIFT) & TMP117_CFG_CONV_MASK; + ConfigReg |= ((uint16_t)p_Config->Averaging << TMP117_CFG_AVG_SHIFT) & TMP117_CFG_AVG_MASK; + + /* Write configuration */ + Error = TMP117_Write_Register(p_Dev_Handle, TMP117_REG_CONFIGURATION, ConfigReg); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to write configuration register: %d!", Error); + + return Error; + } + + ESP_LOGD(TAG, "TMP117 configured: Mode=%d, Cycle=%d, Avg=%d", + static_cast(p_Config->Mode), static_cast(p_Config->Cycle), static_cast(p_Config->Averaging)); + + return ESP_OK; +} + +esp_err_t TMP117_ReadTemperature(i2c_master_dev_handle_t *p_Dev_Handle, float *p_Temp) +{ + uint16_t TempRaw; + int16_t TempSigned; + esp_err_t Error; + + if ((p_Dev_Handle == NULL) || (p_Temp == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Read temperature register */ + Error = TMP117_Read_Register(p_Dev_Handle, TMP117_REG_TEMP_RESULT, &TempRaw); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read temperature register: %d!", Error); + + return Error; + } + + /* Convert to signed 16-bit value */ + TempSigned = static_cast(TempRaw); + + /* Apply resolution (0.0078125°C per LSB) */ + *p_Temp = static_cast(TempSigned) * TMP117_RESOLUTION; + + ESP_LOGD(TAG, "Temperature: %.4f°C (Raw: 0x%04X)", *p_Temp, TempRaw); + + return ESP_OK; +} + +esp_err_t TMP117_TriggerOneShot(i2c_master_dev_handle_t *p_Dev_Handle) +{ + uint16_t ConfigReg; + esp_err_t Error; + + if (p_Dev_Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Read current configuration */ + Error = TMP117_Read_Register(p_Dev_Handle, TMP117_REG_CONFIGURATION, &ConfigReg); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read configuration register: %d!", Error); + + return Error; + } + + /* Check if in one-shot mode */ + uint8_t CurrentMode = static_cast((ConfigReg & TMP117_CFG_MOD_MASK) >> TMP117_CFG_MOD_SHIFT); + if (CurrentMode != TMP117_MODE_ONE_SHOT) { + ESP_LOGE(TAG, "Device not in one-shot mode (current mode: %d)!", CurrentMode); + + return ESP_ERR_INVALID_STATE; + } + + /* Trigger one-shot conversion by setting mode bits back to one-shot */ + ConfigReg &= ~TMP117_CFG_MOD_MASK; + ConfigReg |= (static_cast(TMP117_MODE_ONE_SHOT) << TMP117_CFG_MOD_SHIFT) & TMP117_CFG_MOD_MASK; + + Error = TMP117_Write_Register(p_Dev_Handle, TMP117_REG_CONFIGURATION, ConfigReg); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to trigger one-shot conversion: %d!", Error); + + return Error; + } + + ESP_LOGD(TAG, "One-shot conversion triggered"); + + return ESP_OK; +} + +esp_err_t TMP117_IsDataReady(i2c_master_dev_handle_t *p_Dev_Handle, bool *p_Ready) +{ + uint16_t ConfigReg; + esp_err_t Error; + + if ((p_Dev_Handle == NULL) || (p_Ready == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Read configuration register */ + Error = TMP117_Read_Register(p_Dev_Handle, TMP117_REG_CONFIGURATION, &ConfigReg); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read configuration register: %d!", Error); + + return Error; + } + + /* Check Data_Ready flag */ + *p_Ready = (ConfigReg & TMP117_CFG_DATA_READY) != 0; + + return ESP_OK; +} + +esp_err_t TMP117_ReadDeviceID(i2c_master_dev_handle_t *p_Dev_Handle, uint16_t *p_DeviceID) +{ + esp_err_t Error; + + if ((p_Dev_Handle == NULL) || (p_DeviceID == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* Read device ID register */ + Error = TMP117_Read_Register(p_Dev_Handle, TMP117_REG_DEVICE_ID, p_DeviceID); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read device ID register: %d!", Error); + + return Error; + } + + return ESP_OK; +} + +esp_err_t TMP117_SoftReset(i2c_master_dev_handle_t *p_Dev_Handle) +{ + uint16_t ConfigReg; + esp_err_t Error; + + if (p_Dev_Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Read current configuration */ + Error = TMP117_Read_Register(p_Dev_Handle, TMP117_REG_CONFIGURATION, &ConfigReg); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read configuration register: %d!", Error); + + return Error; + } + + /* Set soft reset bit */ + ConfigReg |= TMP117_CFG_SOFT_RESET; + + Error = TMP117_Write_Register(p_Dev_Handle, TMP117_REG_CONFIGURATION, ConfigReg); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to write soft reset: %d!", Error); + + return Error; + } + + /* Wait for reset to complete (minimum 2ms) */ + vTaskDelay(5 / portTICK_PERIOD_MS); + + ESP_LOGI(TAG, "TMP117 soft reset completed"); + + return ESP_OK; +} \ No newline at end of file diff --git a/main/Application/Manager/Devices/TMP117/tmp117.h b/main/Application/Manager/Devices/TMP117/tmp117.h new file mode 100644 index 0000000..17f16e9 --- /dev/null +++ b/main/Application/Manager/Devices/TMP117/tmp117.h @@ -0,0 +1,170 @@ +/* + * tmp117.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: TMP117 Temperature Sensor driver definition. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef TMP117_H_ +#define TMP117_H_ + +#include + +#include +#include + +#include "../I2C/i2c.h" + +/** @brief TMP117 conversion mode options. + */ +typedef enum { + TMP117_MODE_CONTINUOUS = 0x00, /**< Continuous conversion mode */ + TMP117_MODE_SHUTDOWN = 0x01, /**< Shutdown mode (low power) */ + TMP117_MODE_ONE_SHOT = 0x03, /**< One-shot conversion mode */ +} TMP117_ConversionMode_t; + +/** @brief TMP117 conversion cycle time options. + */ +typedef enum { + TMP117_CYCLE_15_5MS = 0x00, /**< 15.5 ms conversion cycle */ + TMP117_CYCLE_125MS = 0x01, /**< 125 ms conversion cycle */ + TMP117_CYCLE_250MS = 0x02, /**< 250 ms conversion cycle */ + TMP117_CYCLE_500MS = 0x03, /**< 500 ms conversion cycle */ + TMP117_CYCLE_1S = 0x04, /**< 1 second conversion cycle */ + TMP117_CYCLE_4S = 0x05, /**< 4 seconds conversion cycle */ + TMP117_CYCLE_8S = 0x06, /**< 8 seconds conversion cycle */ + TMP117_CYCLE_16S = 0x07, /**< 16 seconds conversion cycle */ +} TMP117_ConversionCycle_t; + +/** @brief TMP117 averaging mode options. + */ +typedef enum { + TMP117_AVG_NONE = 0x00, /**< No averaging (1 conversion) */ + TMP117_AVG_8 = 0x01, /**< Average over 8 conversions */ + TMP117_AVG_32 = 0x02, /**< Average over 32 conversions */ + TMP117_AVG_64 = 0x03, /**< Average over 64 conversions */ +} TMP117_AveragingMode_t; + +/** @brief TMP117 configuration structure. + */ +typedef struct { + TMP117_ConversionMode_t Mode; /**< Conversion mode */ + TMP117_ConversionCycle_t Cycle; /**< Conversion cycle time */ + TMP117_AveragingMode_t Averaging; /**< Number of conversions to average */ +} TMP117_Config_t; + +/** @brief Initializes the TMP117 driver with default configuration. + * Default settings: Continuous mode, 1 second cycle, no averaging. + * @note The device is configured for continuous conversion at 1 second intervals. + * Call TMP117_ReadTemperature() to retrieve temperature readings. + * @param p_Bus_Handle Pointer to I2C bus handle + * @param p_Dev_Handle Pointer to store the created device handle + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_ERR_NO_MEM if device handle allocation fails + * ESP_FAIL if I2C communication fails + */ +esp_err_t TMP117_Init(i2c_master_bus_handle_t *p_Bus_Handle, i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Deinitializes the TMP117 driver and frees resources. + * @note After calling this function, the device handle becomes invalid. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointer is NULL + */ +esp_err_t TMP117_Deinit(i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Configure the TMP117 sensor. + * Allows customization of conversion mode, cycle time, and averaging. + * @note Configuration is written to the device immediately. + * In One-Shot mode, call TMP117_TriggerOneShot() to start conversion. + * @param p_Dev_Handle Pointer to device handle + * @param p_Config Pointer to configuration structure + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_FAIL if I2C communication fails + */ +esp_err_t TMP117_Configure(i2c_master_dev_handle_t *p_Dev_Handle, const TMP117_Config_t *p_Config); + +/** @brief Read temperature from TMP117 sensor. + * Reads the current temperature value from the sensor's result register. + * Resolution is 0.0078125°C (7.8125 m°C) per LSB. + * @note In continuous mode, returns the latest conversion result. + * In one-shot mode, returns the result of the last triggered conversion. + * Temperature range: -256°C to +256°C. + * @param p_Dev_Handle Pointer to device handle + * @param p_Temp Pointer to store temperature in degrees Celsius + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_FAIL if I2C communication fails + */ +esp_err_t TMP117_ReadTemperature(i2c_master_dev_handle_t *p_Dev_Handle, float *p_Temp); + +/** @brief Trigger a one-shot temperature conversion. + * Only applicable in One-Shot mode. Initiates a single temperature conversion. + * @note Conversion time depends on averaging setting (15.5ms to ~1 second). + * Wait for conversion to complete before reading temperature. + * Use TMP117_IsDataReady() to check if conversion is complete. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointer is NULL + * ESP_ERR_INVALID_STATE if not in One-Shot mode + * ESP_FAIL if I2C communication fails + */ +esp_err_t TMP117_TriggerOneShot(i2c_master_dev_handle_t *p_Dev_Handle); + +/** @brief Check if new temperature data is ready. + * Reads the Data_Ready flag from the configuration register. + * @note In continuous mode, flag is set after each conversion completes. + * In one-shot mode, flag is set after the triggered conversion completes. + * Flag is cleared automatically when temperature register is read. + * @param p_Dev_Handle Pointer to device handle + * @param p_Ready Pointer to store ready status (true if data is ready) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_FAIL if I2C communication fails + */ +esp_err_t TMP117_IsDataReady(i2c_master_dev_handle_t *p_Dev_Handle, bool *p_Ready); + +/** @brief Read the TMP117 device ID. + * Reads the device ID register to verify sensor identity. + * Expected value: 0x0117 + * @note Use this function to verify correct I2C communication. + * Device ID should always read 0x0117. + * @param p_Dev_Handle Pointer to device handle + * @param p_DeviceID Pointer to store device ID + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_FAIL if I2C communication fails + */ +esp_err_t TMP117_ReadDeviceID(i2c_master_dev_handle_t *p_Dev_Handle, uint16_t *p_DeviceID); + +/** @brief Perform a soft reset of the TMP117. + * Resets the device to power-on default state. All configuration is lost. + * @note After reset, device returns to default configuration. + * Wait at least 2ms after reset before accessing the device. + * @warning All custom configuration will be lost after reset. + * @param p_Dev_Handle Pointer to device handle + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointer is NULL + * ESP_FAIL if I2C communication fails + */ +esp_err_t TMP117_SoftReset(i2c_master_dev_handle_t *p_Dev_Handle); + +#endif /* TMP117_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/devicesManager.cpp b/main/Application/Manager/Devices/devicesManager.cpp index f2630d2..2900ec4 100644 --- a/main/Application/Manager/Devices/devicesManager.cpp +++ b/main/Application/Manager/Devices/devicesManager.cpp @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Devices management implementation. + * File info: Devices Manager implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,37 +22,49 @@ */ #include -#include #include #include #include -#include "lepton.h" -#include "devices.h" -#include "devicesManager.h" -#include "I2C/i2c.h" #include "SPI/spi.h" #include "ADC/adc.h" -#include "RTC/rtc.h" -#include "PortExpander/portexpander.h" -#include "../Time/timeManager.h" - -/** @brief Voltage divider resistors for battery measurement. - */ -#define BATTERY_R1 10000 /* Upper resistor */ -#define BATTERY_R2 3300 /* Lower resistor */ +#include "TMP117/tmp117.h" +#include "RV8263-C8/rv8263c8.h" +#include "PCAL6416AHF/pcal6416ahf.h" +#include "PCA9633DP1/pca9633dp1.h" +#include "devicesManager.h" -/** @brief Battery voltage range (in millivolts). +#if defined(CONFIG_TOUCH_I2C0_HOST) +#define TOUCH_I2C_HOST I2C_NUM_0 +#elif defined(CONFIG_TOUCH_I2C1_HOST) +#define TOUCH_I2C_HOST I2C_NUM_1 +#else +#error "No I2C host defined for touch!" +#endif + +#if defined(CONFIG_DEVICES_I2C_I2C0_HOST) +#define DEVICES_I2C_HOST I2C_NUM_0 +#elif defined(CONFIG_DEVICES_I2C_I2C1_HOST) +#define DEVICES_I2C_HOST I2C_NUM_1 +#else +#error "No I2C host defined for devices!" +#endif + +ESP_EVENT_DEFINE_BASE(DEVICES_EVENTS); + +/** @brief */ -#define BATTERY_MIN_VOLTAGE 3300 /* 3.3V */ -#define BATTERY_MAX_VOLTAGE 4200 /* 4.2V (fully charged LiPo) */ +enum { + DEVICES_EXPANDER_MAINBOARD = 0, + DEVICES_EXPANDER_DISPLAYBOARD, +}; -/** @brief Default configuration for the I2C interface. +/** @brief Default configuration for the I2C interface (shared by RTC, Port Expander, Lepton and Temperature Sensor). */ -static i2c_master_bus_config_t _Devices_Manager_I2CM_Config = { - .i2c_port = static_cast(CONFIG_DEVICES_I2C_HOST), +static i2c_master_bus_config_t _Devices_Manager_Devices_I2CM_Config = { + .i2c_port = DEVICES_I2C_HOST, .sda_io_num = static_cast(CONFIG_DEVICES_I2C_SDA), .scl_io_num = static_cast(CONFIG_DEVICES_I2C_SCL), .clk_source = I2C_CLK_SRC_DEFAULT, @@ -65,9 +77,29 @@ static i2c_master_bus_config_t _Devices_Manager_I2CM_Config = { }, }; +/** @brief Default configuration for the I2C interface (shared by Touch). + */ +static i2c_master_bus_config_t _Devices_Manager_Touch_I2CM_Config = { + .i2c_port = TOUCH_I2C_HOST, + .sda_io_num = static_cast(CONFIG_TOUCH_SDA), + .scl_io_num = static_cast(CONFIG_TOUCH_SCL), + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .intr_priority = 0, + .trans_queue_depth = 0, + .flags = { + .enable_internal_pullup = true, + .allow_pd = false, + }, +}; + +/** @brief + */ +static const spi_host_device_t _Devices_Manager_Periph_SPI = SPI3_HOST; + /** @brief Default configuration for the SPI3 bus (shared by LCD, Touch, SD card). */ -static const spi_bus_config_t _Devices_Manager_SPI_Config = { +static const spi_bus_config_t _Devices_Manager_Periph_SPI_Config = { .mosi_io_num = CONFIG_SPI_MOSI, .miso_io_num = CONFIG_SPI_MISO, .sclk_io_num = CONFIG_SPI_SCLK, @@ -87,46 +119,59 @@ static const spi_bus_config_t _Devices_Manager_SPI_Config = { typedef struct { bool initialized; i2c_master_dev_handle_t RTC_Handle; + i2c_master_dev_handle_t Expander_Handle[2]; i2c_master_bus_handle_t I2C_Bus_Handle; + i2c_master_bus_handle_t Touch_I2C_Bus_Handle; } Devices_Manager_State_t; static Devices_Manager_State_t _Devices_Manager_State; -static const char *TAG = "devices-manager"; +static const char *TAG = "Devices-Manager"; esp_err_t DevicesManager_Init(void) { if (_Devices_Manager_State.initialized) { ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; } - if (I2CM_Init(&_Devices_Manager_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize I2C!"); + ESP_LOGD(TAG, "Initializing Devices Manager..."); + + memset(&_Devices_Manager_State, 0, sizeof(Devices_Manager_State_t)); + + if (I2CM_Init(&_Devices_Manager_Touch_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize Touch I2C!"); + return ESP_FAIL; } - if (SPIM_Init(&_Devices_Manager_SPI_Config, SPI3_HOST, SPI_DMA_CH_AUTO) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize SPI3!"); + if (I2CM_Init(&_Devices_Manager_Devices_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize Peripheral I2C!"); + return ESP_FAIL; } - if (PortExpander_Init(&_Devices_Manager_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { - ESP_LOGE(TAG, "Failed to set default configuration for port expander!"); + if (SPIM_Init(&_Devices_Manager_Periph_SPI_Config, _Devices_Manager_Periph_SPI, SPI_DMA_CH_AUTO) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize SPI3!"); + return ESP_FAIL; } - /* Give the camera time to power up and stabilize (Lepton requires ~1.5s boot time) */ - ESP_LOGI(TAG, "Waiting for camera power stabilization..."); - vTaskDelay(2000 / portTICK_PERIOD_MS); + if (PortExpander_Init(&_Devices_Manager_State.I2C_Bus_Handle, + &_Devices_Manager_State.Expander_Handle[DEVICES_EXPANDER_MAINBOARD]) != ESP_OK) { + ESP_LOGE(TAG, "Failed to set default configuration for the mainboard port expander!"); + + return ESP_FAIL; + } - if (RTC_Init(&_Devices_Manager_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle, - &_Devices_Manager_State.RTC_Handle) != ESP_OK) { + if (RTC_Init(&_Devices_Manager_State.I2C_Bus_Handle, &_Devices_Manager_State.RTC_Handle) != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize RTC!"); + return ESP_FAIL; } - PortExpander_EnableBatteryVoltage(false); + PortExpander_EnableBatteryVoltage(&_Devices_Manager_State.Expander_Handle[DEVICES_EXPANDER_MAINBOARD], false); _Devices_Manager_State.initialized = true; @@ -138,18 +183,20 @@ esp_err_t DevicesManager_Deinit(void) esp_err_t Error; if (_Devices_Manager_State.initialized == false) { - ESP_LOGE(TAG, "Devices manager not initialized yet!"); + ESP_LOGE(TAG, "Devices Manager not initialized yet!"); + return ESP_OK; } - PortExpander_EnableBatteryVoltage(false); - ADC_Deinit(); - RTC_Deinit(); - PortExpander_Deinit(); + + PortExpander_EnableBatteryVoltage(&_Devices_Manager_State.Expander_Handle[DEVICES_EXPANDER_MAINBOARD], false); + + RTC_Deinit(&_Devices_Manager_State.RTC_Handle); + PortExpander_Deinit(&_Devices_Manager_State.Expander_Handle[DEVICES_EXPANDER_MAINBOARD]); Error = I2CM_Deinit(_Devices_Manager_State.I2C_Bus_Handle); - SPIM_Deinit(SPI3_HOST); + SPIM_Deinit(_Devices_Manager_Periph_SPI); _Devices_Manager_State.initialized = false; @@ -159,48 +206,61 @@ esp_err_t DevicesManager_Deinit(void) i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void) { if (_Devices_Manager_State.initialized == false) { - ESP_LOGE(TAG, "Devices manager not initialized yet!"); + ESP_LOGE(TAG, "Devices Manager not initialized yet!"); + return NULL; } return _Devices_Manager_State.I2C_Bus_Handle; } +i2c_master_bus_handle_t DevicesManager_GetTouchI2CBusHandle(void) +{ + if (_Devices_Manager_State.initialized == false) { + ESP_LOGE(TAG, "Devices Manager not initialized yet!"); + + return NULL; + } + + return _Devices_Manager_State.Touch_I2C_Bus_Handle; +} + +spi_host_device_t DevicesManager_GetSPIHost(void) +{ + return _Devices_Manager_Periph_SPI; +} + esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, uint8_t *p_Percentage) { esp_err_t Error; if (_Devices_Manager_State.initialized == false) { ESP_LOGE(TAG, "Devices Manager not initialized yet!"); + return ESP_ERR_INVALID_STATE; } else if ((p_Voltage == NULL) || (p_Percentage == NULL)) { return ESP_ERR_INVALID_ARG; } - PortExpander_EnableBatteryVoltage(true); + PortExpander_EnableBatteryVoltage(&_Devices_Manager_State.Expander_Handle[DEVICES_EXPANDER_MAINBOARD], true); Error = ADC_ReadBattery(p_Voltage, p_Percentage); if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to read battery voltage: %d", Error); - - PortExpander_EnableBatteryVoltage(false); - - return Error; + ESP_LOGE(TAG, "Failed to read battery voltage: %d!", Error); } - PortExpander_EnableBatteryVoltage(false); + PortExpander_EnableBatteryVoltage(&_Devices_Manager_State.Expander_Handle[DEVICES_EXPANDER_MAINBOARD], false); - return ESP_OK; + return Error; } esp_err_t DevicesManager_GetRTCHandle(i2c_master_dev_handle_t *p_Handle) { if (_Devices_Manager_State.initialized == false) { ESP_LOGE(TAG, "Devices Manager not initialized yet!"); - return ESP_ERR_INVALID_STATE; - } - if (p_Handle == NULL) { + return ESP_ERR_INVALID_STATE; + } else if (p_Handle == NULL) { return ESP_ERR_INVALID_ARG; } @@ -208,3 +268,13 @@ esp_err_t DevicesManager_GetRTCHandle(i2c_master_dev_handle_t *p_Handle) return ESP_OK; } + +esp_err_t DevicesManager_GetTime(struct tm *p_Time) +{ + return RTC_GetTime(&_Devices_Manager_State.RTC_Handle, p_Time); +} + +esp_err_t DevicesManager_SetTime(const struct tm *p_Time) +{ + return RTC_SetTime(&_Devices_Manager_State.RTC_Handle, p_Time); +} \ No newline at end of file diff --git a/main/Application/Manager/Devices/devicesManager.h b/main/Application/Manager/Devices/devicesManager.h index 269c0b2..486f60a 100644 --- a/main/Application/Manager/Devices/devicesManager.h +++ b/main/Application/Manager/Devices/devicesManager.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Devices management for the peripheral devices. + * File info: Devices Manager definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,38 +24,111 @@ #ifndef DEVICESMANAGER_H_ #define DEVICESMANAGER_H_ -#include #include +#include #include #include -/** @brief Initialize the Devices Manager. - * @return ESP_OK on success +#include "I2C/i2c.h" +#include "devicesTypes.h" + +/** @brief Initialize the Devices Manager. + * Initializes all hardware peripherals including I2C and SPI buses, + * port expander, RTC, ADC, and LED driver. Must be called before + * any other DevicesManager functions. + * @note This function must be called after NVS initialization. + * I2C bus speed: 400 kHz, SPI: up to 40 MHz. + * @warning Not thread-safe. Call once from main task during startup. + * @return ESP_OK on success + * ESP_ERR_NO_MEM if memory allocation fails + * ESP_FAIL if I2C/SPI initialization fails */ esp_err_t DevicesManager_Init(void); -/** @brief Deinitialize the Devices Manager. - * @return ESP_OK on success +/** @brief Deinitialize the Devices Manager. + * Cleans up all device handles, removes I2C/SPI devices, and frees + * allocated resources. Should be called during shutdown. + * @note After calling this, DevicesManager_Init() must be called again. + * @warning All device handles become invalid after this call. + * @return ESP_OK on success + * ESP_FAIL if cleanup fails */ esp_err_t DevicesManager_Deinit(void); -/** @brief Get the I2C bus handle. - * @return I2C bus handle or NULL if not initialized +/** @brief Get the I2C bus handle for peripheral devices. + * Returns the I2C bus handle used by RTC, Port Expander, and other + * peripheral devices (not the touch controller). + * @note This is the main I2C bus (I2C_NUM_0). + * Bus speed: 400 kHz. + * @return I2C bus handle on success + * NULL if DevicesManager not initialized */ i2c_master_bus_handle_t DevicesManager_GetI2CBusHandle(void); +/** @brief Get the I2C bus handle for touch controller. + * Returns the dedicated I2C bus handle used exclusively by the + * GT911 touch controller. + * @note This is a separate I2C bus (I2C_NUM_1). + * Dedicated bus prevents interference with other peripherals. + * @return I2C bus handle on success + * NULL if DevicesManager not initialized + */ +i2c_master_bus_handle_t DevicesManager_GetTouchI2CBusHandle(void); + +/** @brief Get the SPI host device identifier. + * Returns the SPI host device that is managed by the Devices Manager. + * This host is shared by LCD display, touch controller, and SD card. + * @note Shared SPI bus requires proper CS (Chip Select) management. + * Maximum clock speed depends on connected device (LCD: 40MHz). + * @return SPI host identifier (typically SPI2_HOST) + */ +spi_host_device_t DevicesManager_GetSPIHost(void); + /** @brief Get the battery voltage and percentage. - * @param p_Voltage Pointer to store voltage in mV + * Reads the battery voltage via ADC and calculates the remaining + * charge percentage based on voltage curve. Voltage measurement is + * enabled via port expander GPIO. + * @note ADC is calibrated using eFuse values. + * Battery voltage range: typically 3.0V to 4.2V for Li-Ion. + * @warning Measurement enables battery voltage divider (increases power consumption). + * @param p_Voltage Pointer to store voltage in mV (millivolts) * @param p_Percentage Pointer to store percentage (0-100) * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_FAIL if ADC read fails */ esp_err_t DevicesManager_GetBatteryVoltage(int *p_Voltage, uint8_t *p_Percentage); /** @brief Get the RTC device handle (for Time Manager). - * @param p_Handle Pointer to store the RTC handle + * Returns the I2C device handle for the RV8263-C8 Real-Time Clock. + * Used by TimeManager for time synchronization. + * @note RTC provides backup time when network unavailable. + * This function is typically called by TimeManager only. + * @param p_Handle Pointer to store the RTC I2C device handle * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Handle is NULL + * ESP_ERR_INVALID_STATE if DevicesManager not initialized */ esp_err_t DevicesManager_GetRTCHandle(i2c_master_dev_handle_t *p_Handle); +/** @brief Get the current time from the RTC. + * Reads the current date and time from the RV8263-C8 Real-Time Clock + * and converts it to a tm structure. + * @note This is a convenience wrapper for TimeManager. + * Time is in local timezone (not UTC). + * @param p_Time Pointer to tm structure to store the time + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Time is NULL + * ESP_ERR_INVALID_STATE if RTC not initialized + * ESP_FAIL if I2C communication fails + */ +esp_err_t DevicesManager_GetTime(struct tm *p_Time); + +/** @brief Set the time on the RTC. + * @param p_Time Pointer to the time to set + * @return ESP_OK when successful + */ +esp_err_t DevicesManager_SetTime(const struct tm *p_Time); + #endif /* DEVICESMANAGER_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Devices/devicesTypes.h b/main/Application/Manager/Devices/devicesTypes.h new file mode 100644 index 0000000..53cfb96 --- /dev/null +++ b/main/Application/Manager/Devices/devicesTypes.h @@ -0,0 +1,48 @@ +/* + * devicesTypes.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Common type definitions for the Devices Manager component. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef DEVICES_TYPES_H_ +#define DEVICES_TYPES_H_ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +/** @brief Devices Manager events base. + */ +ESP_EVENT_DECLARE_BASE(DEVICES_EVENTS); + +/** @brief Devices Manager event identifiers. + */ +enum { + +}; + +#endif /* DEVICES_TYPES_H_ */ diff --git a/main/Application/Manager/Memory/memoryManager.cpp b/main/Application/Manager/Memory/memoryManager.cpp new file mode 100644 index 0000000..375a348 --- /dev/null +++ b/main/Application/Manager/Memory/memoryManager.cpp @@ -0,0 +1,533 @@ +/* + * memoryManager.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Memory Manager implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "../Devices/SPI/spi.h" +#include "../Devices/devicesManager.h" +#include "memoryManager.h" + +ESP_EVENT_DEFINE_BASE(MEMORY_EVENTS); + +typedef struct { + bool isInitialized; + bool hasSDCard; + bool isFilesystemLocked; + MemoryManager_Location_t StorageLocation; + sdmmc_card_t *p_SDCard; + wl_handle_t WL_Handle; +} Memory_Manager_State_t; + +static Memory_Manager_State_t _Memory_Manager_State; + +static const char *TAG = "Memory-Manager"; + +/** @brief Calculate directory size recursively. + * @param p_Path Path to directory + * @return Total size in bytes + */ +static size_t MemoryManager_Calc_Dir_Size(const char *p_Path) +{ + size_t TotalSize = 0; + DIR *Dir = opendir(p_Path); + + if (Dir == NULL) { + return 0; + } + + struct dirent *Entry; + while ((Entry = readdir(Dir)) != NULL) { + struct stat St; + char FullPath[256]; + + if ((strcmp(Entry->d_name, ".") == 0) || (strcmp(Entry->d_name, "..") == 0)) { + continue; + } + + snprintf(FullPath, sizeof(FullPath), "%s/%s", p_Path, Entry->d_name); + + if (stat(FullPath, &St) == 0) { + if (S_ISDIR(St.st_mode)) { + TotalSize += MemoryManager_Calc_Dir_Size(FullPath); + } else { + TotalSize += St.st_size; + } + } + } + + closedir(Dir); + + return TotalSize; +} + +/** @brief Mount internal flash storage as FAT32 with wear leveling. + * @return ESP_OK if mounted successfully + */ +static esp_err_t MemoryManager_Mount_Internal_Storage(void) +{ + esp_err_t Error; + const esp_vfs_fat_mount_config_t MountConfig = { + .format_if_mount_failed = true, + .max_files = 5, + .allocation_unit_size = 4096, + .disk_status_check_enable = false + }; + const esp_partition_t *Partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_DATA_FAT, + "storage"); + + ESP_LOGD(TAG, "Mounting internal storage with FAT32 and wear leveling..."); + + if (Partition == NULL) { + ESP_LOGE(TAG, "Storage partition not found!"); + return ESP_ERR_NOT_FOUND; + } + + ESP_LOGD(TAG, "Found storage partition: size=%lu bytes", Partition->size); + + Error = esp_vfs_fat_spiflash_mount_rw_wl("/storage", "storage", &MountConfig, &_Memory_Manager_State.WL_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount FAT filesystem: %d", Error); + return Error; + } + + ESP_LOGD(TAG, "Internal storage mounted successfully at /storage"); + ESP_LOGD(TAG, "Wear leveling handle: %d", _Memory_Manager_State.WL_Handle); + + return ESP_OK; +} + +/** @brief Try to mount SD card via SPI. + * @return ESP_OK if SD card mounted successfully + */ +static esp_err_t MemoryManager_Mount_SD_Card(void) +{ + esp_err_t Error; + sdmmc_host_t Host = SDSPI_HOST_DEFAULT(); + sdspi_device_config_t SlotConfig = SDSPI_DEVICE_CONFIG_DEFAULT(); + spi_host_device_t SPI_Host = DevicesManager_GetSPIHost(); + const esp_vfs_fat_mount_config_t MountConfig = { + .format_if_mount_failed = false, + .max_files = 5, + .allocation_unit_size = 16 * 1024 + }; + + ESP_LOGD(TAG, "Attempting to mount SD card via SPI..."); + + if (SPIM_IsInitialized(SPI_Host) == false) { + ESP_LOGE(TAG, "SPI bus not initialized!"); + + return ESP_ERR_INVALID_STATE; + } + + SlotConfig.gpio_cs = static_cast(CONFIG_SD_CARD_PIN_CS); + SlotConfig.host_id = SPI_Host; + Host.slot = SPI_Host; + + Error = esp_vfs_fat_sdspi_mount("/sdcard", &Host, &SlotConfig, &MountConfig, &_Memory_Manager_State.p_SDCard); + if (Error != ESP_OK) { + if (Error == ESP_FAIL) { + ESP_LOGW(TAG, "Failed to mount SD card filesystem"); + } else { + ESP_LOGW(TAG, "Failed to initialize SD card: %d!", Error); + } + + return Error; + } + + ESP_LOGD(TAG, "SD card mounted successfully at /sdcard via SPI"); + + return ESP_OK; +} + +esp_err_t MemoryManager_Init(void) +{ + esp_err_t Error; + + if (_Memory_Manager_State.isInitialized) { + ESP_LOGW(TAG, "Memory Manager already initialized"); + + return ESP_OK; + } + + ESP_LOGD(TAG, "Initializing Memory Manager"); + + memset(&_Memory_Manager_State, 0, sizeof(Memory_Manager_State_t)); + + /* Try to mount SD card first */ + if (MemoryManager_Mount_SD_Card() == ESP_OK) { + ESP_LOGD(TAG, "Using SD card for storage"); + + _Memory_Manager_State.hasSDCard = true; + _Memory_Manager_State.StorageLocation = MEMORY_LOCATION_SD_CARD; + + esp_event_post(MEMORY_EVENTS, MEMORY_EVENT_SD_CARD_MOUNTED, NULL, 0, portMAX_DELAY); + } else { + ESP_LOGD(TAG, "SD card not available, using internal flash"); + + /* Mount internal flash with FAT32 */ + Error = MemoryManager_Mount_Internal_Storage(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount internal storage: %d!", Error); + + return Error; + } + + _Memory_Manager_State.hasSDCard = false; + _Memory_Manager_State.StorageLocation = MEMORY_LOCATION_INTERNAL; + esp_event_post(MEMORY_EVENTS, MEMORY_EVENT_FLASH_MOUNTED, NULL, 0, portMAX_DELAY); + } + + _Memory_Manager_State.isInitialized = true; + + return ESP_OK; +} + +esp_err_t MemoryManager_Deinit(void) +{ + if (_Memory_Manager_State.isInitialized == false) { + return ESP_OK; + } + + ESP_LOGD(TAG, "Deinitializing Memory Manager"); + + if (_Memory_Manager_State.hasSDCard) { + esp_vfs_fat_sdcard_unmount("/sdcard", _Memory_Manager_State.p_SDCard); + _Memory_Manager_State.p_SDCard = NULL; + _Memory_Manager_State.hasSDCard = false; + } else if (_Memory_Manager_State.WL_Handle != WL_INVALID_HANDLE) { + esp_vfs_fat_spiflash_unmount_rw_wl("/storage", _Memory_Manager_State.WL_Handle); + _Memory_Manager_State.WL_Handle = WL_INVALID_HANDLE; + } + + _Memory_Manager_State.isInitialized = false; + + return ESP_OK; +} + +bool MemoryManager_HasSDCard(void) +{ + return _Memory_Manager_State.hasSDCard; +} + +MemoryManager_Location_t MemoryManager_GetStorageLocation(void) +{ + return _Memory_Manager_State.StorageLocation; +} + +const char *MemoryManager_GetStoragePath(void) +{ + if (_Memory_Manager_State.StorageLocation == MEMORY_LOCATION_SD_CARD) { + return "/sdcard"; + } else { + return "/storage"; + } +} + +esp_err_t MemoryManager_GetStorageUsage(MemoryManager_Usage_t *p_Usage) +{ + if (p_Usage == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (_Memory_Manager_State.StorageLocation == MEMORY_LOCATION_SD_CARD) { + FATFS *fs; + DWORD fre_clust; + + if (_Memory_Manager_State.hasSDCard == false) { + ESP_LOGE(TAG, "SD card not mounted!"); + + return ESP_ERR_INVALID_STATE; + } + + if (f_getfree("0:", &fre_clust, &fs) == FR_OK) { + uint64_t total_sectors = (fs->n_fatent - 2) * fs->csize; + uint64_t free_sectors = fre_clust * fs->csize; + + p_Usage->TotalBytes = total_sectors * fs->ssize; + p_Usage->FreeBytes = free_sectors * fs->ssize; + p_Usage->UsedBytes = p_Usage->TotalBytes - p_Usage->FreeBytes; + + if (p_Usage->TotalBytes > 0) { + p_Usage->UsedPercent = (uint8_t)((p_Usage->UsedBytes * 100) / p_Usage->TotalBytes); + } else { + p_Usage->UsedPercent = 0; + } + + return ESP_OK; + } else { + ESP_LOGE(TAG, "Failed to get SD card filesystem info!"); + + return ESP_FAIL; + } + } else { + /* Get internal FAT storage usage */ + FATFS *fs; + DWORD fre_clust; + + if (_Memory_Manager_State.WL_Handle == WL_INVALID_HANDLE) { + ESP_LOGE(TAG, "Internal storage not mounted!"); + return ESP_ERR_INVALID_STATE; + } + + if (f_getfree("1:", &fre_clust, &fs) == FR_OK) { + uint64_t total_sectors = (fs->n_fatent - 2) * fs->csize; + uint64_t free_sectors = fre_clust * fs->csize; + + p_Usage->TotalBytes = total_sectors * fs->ssize; + p_Usage->FreeBytes = free_sectors * fs->ssize; + p_Usage->UsedBytes = p_Usage->TotalBytes - p_Usage->FreeBytes; + + if (p_Usage->TotalBytes > 0) { + p_Usage->UsedPercent = (uint8_t)((p_Usage->UsedBytes * 100) / p_Usage->TotalBytes); + } else { + p_Usage->UsedPercent = 0; + } + + return ESP_OK; + } else { + ESP_LOGE(TAG, "Failed to get internal storage filesystem info!"); + return ESP_FAIL; + } + } +} + +esp_err_t MemoryManager_GetCoredumpUsage(MemoryManager_Usage_t *p_Usage) +{ + if (p_Usage == NULL) { + return ESP_ERR_INVALID_ARG; + } + + const esp_partition_t *Partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_DATA_COREDUMP, + "coredump"); + if (Partition == NULL) { + ESP_LOGE(TAG, "Coredump partition not found!"); + + return ESP_ERR_NOT_FOUND; + } + + p_Usage->TotalBytes = Partition->size; + + /* Read first 4 bytes to check if coredump exists (magic number check) */ + uint32_t Magic = 0; + esp_err_t Error = esp_partition_read(Partition, 0, &Magic, sizeof(Magic)); + + if ((Error == ESP_OK) && (Magic != 0xFFFFFFFF) && (Magic != 0x00000000)) { + /* Coredump likely present - assume partition is used */ + p_Usage->UsedBytes = p_Usage->TotalBytes; + p_Usage->FreeBytes = 0; + p_Usage->UsedPercent = 100; + } else { + /* No coredump or empty partition */ + p_Usage->UsedBytes = 0; + p_Usage->FreeBytes = p_Usage->TotalBytes; + p_Usage->UsedPercent = 0; + } + + return ESP_OK; +} + +esp_err_t MemoryManager_EraseStorage(void) +{ + if (_Memory_Manager_State.StorageLocation == MEMORY_LOCATION_SD_CARD) { + struct dirent *Entry; + + ESP_LOGD(TAG, "Erasing SD card storage..."); + + DIR *Dir = opendir("/sdcard"); + if (Dir == NULL) { + ESP_LOGE(TAG, "Failed to open SD card directory!"); + + return ESP_FAIL; + } + + while ((Entry = readdir(Dir)) != NULL) { + char FilePath[512]; + + if ((strcmp(Entry->d_name, ".") == 0) || (strcmp(Entry->d_name, "..") == 0)) { + continue; + } + + snprintf(FilePath, sizeof(FilePath), "/sdcard/%s", Entry->d_name); + + struct stat St; + if (stat(FilePath, &St) == 0) { + if (S_ISDIR(St.st_mode)) { + /* TODO: Implement recursive directory deletion */ + ESP_LOGW(TAG, "Skipping directory: %s", FilePath); + } else { + if (unlink(FilePath) != 0) { + ESP_LOGW(TAG, "Failed to delete: %s", FilePath); + } + } + } + } + + closedir(Dir); + + ESP_LOGD(TAG, "SD card storage erased successfully"); + + return ESP_OK; + + } else { + esp_err_t Error; + const esp_vfs_fat_mount_config_t MountConfig = { + .format_if_mount_failed = true, + .max_files = 5, + .allocation_unit_size = 4096, + .disk_status_check_enable = false + }; + + /* Erase internal FAT storage by unmounting and reformatting */ + ESP_LOGD(TAG, "Erasing internal storage..."); + + /* Unmount current filesystem */ + if (_Memory_Manager_State.WL_Handle != WL_INVALID_HANDLE) { + esp_vfs_fat_spiflash_unmount_rw_wl("/storage", _Memory_Manager_State.WL_Handle); + _Memory_Manager_State.WL_Handle = WL_INVALID_HANDLE; + } + + Error = esp_vfs_fat_spiflash_mount_rw_wl("/storage", "storage", &MountConfig, &_Memory_Manager_State.WL_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to remount storage: %d!", Error); + return ESP_FAIL; + } + + ESP_LOGD(TAG, "Internal storage erased and reformatted successfully"); + + return ESP_OK; + } +} + +esp_err_t MemoryManager_EraseCoredump(void) +{ + esp_err_t Error; + const esp_partition_t *Partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_DATA_COREDUMP, + "coredump"); + + if (Partition == NULL) { + ESP_LOGE(TAG, "Coredump partition not found!"); + return ESP_ERR_NOT_FOUND; + } + + ESP_LOGD(TAG, "Erasing coredump partition (%d bytes)...", Partition->size); + + Error = esp_partition_erase_range(Partition, 0, Partition->size); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to erase coredump partition: %d!", Error); + return ESP_FAIL; + } + + ESP_LOGD(TAG, "Coredump partition erased successfully"); + + return ESP_OK; +} + +esp_err_t MemoryManager_GetWearLevelingHandle(wl_handle_t *p_Handle) +{ + if (p_Handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (_Memory_Manager_State.StorageLocation != MEMORY_LOCATION_INTERNAL) { + ESP_LOGE(TAG, "Wear leveling only available for internal storage!"); + return ESP_ERR_INVALID_STATE; + } + + if (_Memory_Manager_State.WL_Handle == WL_INVALID_HANDLE) { + ESP_LOGE(TAG, "Internal storage not mounted!"); + return ESP_ERR_INVALID_STATE; + } + + *p_Handle = _Memory_Manager_State.WL_Handle; + + return ESP_OK; +} + +esp_err_t MemoryManager_GetSDCardHandle(sdmmc_card_t **pp_Card) +{ + if (pp_Card == NULL) { + return ESP_ERR_INVALID_ARG; + } else if (_Memory_Manager_State.StorageLocation != MEMORY_LOCATION_SD_CARD) { + ESP_LOGE(TAG, "SD card handle only available when SD card is mounted!"); + + return ESP_ERR_INVALID_STATE; + } else if (_Memory_Manager_State.p_SDCard == NULL) { + ESP_LOGE(TAG, "SD card not mounted!"); + + return ESP_ERR_INVALID_STATE; + } + + *pp_Card = _Memory_Manager_State.p_SDCard; + + return ESP_OK; +} + +esp_err_t MemoryManager_LockFilesystem(void) +{ + if (_Memory_Manager_State.isFilesystemLocked) { + ESP_LOGW(TAG, "Filesystem already locked!"); + + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGD(TAG, "Locking filesystem for USB access"); + ESP_LOGW(TAG, " Application MUST NOT write to %s while USB is active!", MemoryManager_GetStoragePath()); + + _Memory_Manager_State.isFilesystemLocked = true; + + return ESP_OK; +} + +esp_err_t MemoryManager_UnlockFilesystem(void) +{ + if (_Memory_Manager_State.isFilesystemLocked == false) { + ESP_LOGW(TAG, "Filesystem not locked!"); + + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGD(TAG, "Unlocking filesystem - application can write again"); + + _Memory_Manager_State.isFilesystemLocked = false; + + return ESP_OK; +} + +bool MemoryManager_IsFilesystemLocked(void) +{ + return _Memory_Manager_State.isFilesystemLocked; +} diff --git a/main/Application/Manager/Memory/memoryManager.h b/main/Application/Manager/Memory/memoryManager.h new file mode 100644 index 0000000..46e5e95 --- /dev/null +++ b/main/Application/Manager/Memory/memoryManager.h @@ -0,0 +1,209 @@ +/* + * memoryManager.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Memory Manager definition. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef MEMORYMANAGER_H_ +#define MEMORYMANAGER_H_ + +#include +#include + +#include "memoryTypes.h" + +/** @brief Storage location types. + */ +typedef enum { + MEMORY_LOCATION_INTERNAL, /**< Internal flash storage partition. */ + MEMORY_LOCATION_SD_CARD, /**< External SD card. */ +} MemoryManager_Location_t; + +/** @brief Memory usage information. + */ +typedef struct { + size_t TotalBytes; /**< Total partition/storage size in bytes. */ + size_t UsedBytes; /**< Used space in bytes. */ + size_t FreeBytes; /**< Free space in bytes. */ + uint8_t UsedPercent; /**< Used space percentage (0-100). */ +} MemoryManager_Usage_t; + +/** @brief Initialize the Memory Manager. + * Detects SD card presence and determines storage location (internal flash + * or SD card). Mounts the filesystem and prepares it for use. + * @note SD card is preferred if detected, otherwise internal flash is used. + * Internal storage uses LittleFS with wear leveling. + * SD card uses FAT filesystem. + * @warning Must be called after SPI bus initialization (DevicesManager). + * @return ESP_OK on success + * ESP_ERR_NO_MEM if memory allocation fails + * ESP_FAIL if filesystem mount fails + */ +esp_err_t MemoryManager_Init(void); + +/** @brief Deinitialize the Memory Manager. + * Unmounts filesystem, releases SD card handle, and frees all + * allocated resources. + * @note All open file handles must be closed before calling this. + * @warning Storage path and handles become invalid after this call. + * @return ESP_OK on success + * ESP_FAIL if unmount fails + */ +esp_err_t MemoryManager_Deinit(void); + +/** @brief Check if SD card is present and mounted. + * Returns the SD card availability status. True means SD card is + * currently in use as active storage. + * @note SD card is hot-plug capable but requires re-initialization. + * This is thread-safe. + * @return true if SD card is detected and mounted + * false if using internal flash or SD not detected + */ +bool MemoryManager_HasSDCard(void); + +/** @brief Get current active storage location. + * Returns whether internal flash or SD card is currently used for + * file storage operations. + * @note Location is determined at initialization time. + * This is thread-safe. + * @return MEMORY_LOCATION_INTERNAL for internal flash + * MEMORY_LOCATION_SD_CARD for SD card + */ +MemoryManager_Location_t MemoryManager_GetStorageLocation(void); + +/** @brief Get base path for current storage location. + * Returns the mount point path for file operations. + * Use this path as base for all file access. + * @note Path is valid until MemoryManager_Deinit() is called. + * NULL if not initialized + * Path is constant and can be cached. + * Append filename with e.g. "/storage/image.png". + * Always prepend this path to filename for file operations. + * @return "/storage" for internal flash + * "/sdcard" for SD card + */ +const char *MemoryManager_GetStoragePath(void); + +/** @brief Get storage usage information for current location. + * Retrieves total, used, and free space in bytes, plus usage percentage + * for the active storage location. + * @note Storage must be mounted to get usage information. + * Values are approximate for wear-leveled storage. + * @param p_Usage Pointer to MemoryManager_Usage_t structure to populate + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Usage is NULL + * ESP_ERR_NOT_FOUND if storage not found + * ESP_FAIL if filesystem not mounted + */ +esp_err_t MemoryManager_GetStorageUsage(MemoryManager_Usage_t *p_Usage); + +/** @brief Get coredump partition usage information. + * Returns size of stored crash dump data if any exists in the + * dedicated coredump partition. + * @note Coredump partition is separate from application storage. + * Use MemoryManager_EraseCoredump() to clear crash dumps. + * @param p_Usage Pointer to MemoryManager_Usage_t structure to populate + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Usage is NULL + * ESP_ERR_NOT_FOUND if coredump partition not found + */ +esp_err_t MemoryManager_GetCoredumpUsage(MemoryManager_Usage_t *p_Usage); + +/** @brief Lock filesystem for USB Mass Storage access. + * Prevents application from accessing filesystem while USB MSC is active. + * Must be called before enabling USB Mass Storage to prevent corruption. + * @note All application file operations will fail when locked. + * GUI should show "USB Mode Active" warning. + * @warning Do NOT write to filesystem while locked - causes corruption! + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if already locked + */ +esp_err_t MemoryManager_LockFilesystem(void); + +/** @brief Unlock filesystem for application access. + * Allows application to access filesystem again after USB Mass Storage + * is deactivated. + * @note Call this after USB MSC is disconnected. + * Application can resume normal file operations. + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not locked + */ +esp_err_t MemoryManager_UnlockFilesystem(void); + +/** @brief Check if filesystem is locked for USB access. + * Returns current filesystem lock status. Use this to check before + * any file write operations. + * @note This is thread-safe and fast - check before every write. + * Image saving, logging, and config writes should check this. + * @return true if locked (USB active, app must not write) + * false if unlocked (app can write normally) + */ +bool MemoryManager_IsFilesystemLocked(void); + +/** @brief Erase current storage location completely. + * Deletes all files in the active storage filesystem (internal flash + * or SD card) and reformats it. + * @note Filesystem is automatically reformatted after erase. + * All data loss is permanent - no recovery possible. + * @warning This will delete ALL files including images and logs! + * @return ESP_OK on success + * ESP_ERR_NOT_FOUND if storage not found + * ESP_FAIL if erase or format fails + */ +esp_err_t MemoryManager_EraseStorage(void); + +/** @brief Erase coredump partition completely. + * Deletes any stored crash dumps from the dedicated coredump partition. + * Useful for clearing old crash data or freeing partition space. + * @note Partition will be cleared and ready for new coredumps. + * Does not affect application data or settings. + * @warning Crash dump data will be lost permanently. + * @return ESP_OK on success + * ESP_ERR_NOT_FOUND if coredump partition not found + * ESP_FAIL if erase fails + */ +esp_err_t MemoryManager_EraseCoredump(void); + +/** @brief Get wear leveling handle for internal storage. + * Returns the wear leveling layer handle for direct access to + * internal flash storage statistics and control. + * @note Only valid for internal flash storage (not SD card). + * Used for low-level wear leveling statistics. + * @param p_Handle Pointer to receive the wl_handle_t + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Handle is NULL + * ESP_ERR_INVALID_STATE if not using internal storage + * ESP_ERR_INVALID_STATE if storage not mounted + */ +esp_err_t MemoryManager_GetWearLevelingHandle(wl_handle_t *p_Handle); + +/** @brief Get SD card handle. + * Returns pointer to sdmmc_card_t structure for direct SD card + * access and card information queries. + * @note Only valid when SD card storage is active. + * Use for card info (capacity, speed, manufacturer). + * @param pp_Card Pointer to receive the SD card handle pointer + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pp_Card is NULL + * ESP_ERR_INVALID_STATE if SD card not mounted + */ +esp_err_t MemoryManager_GetSDCardHandle(sdmmc_card_t **pp_Card); + +#endif /* MEMORYMANAGER_H_ */ diff --git a/main/Application/Manager/Memory/memoryTypes.h b/main/Application/Manager/Memory/memoryTypes.h new file mode 100644 index 0000000..92bcb5c --- /dev/null +++ b/main/Application/Manager/Memory/memoryTypes.h @@ -0,0 +1,49 @@ +/* + * memoryTypes.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Common type definitions for the Memory Manager component. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef MEMORY_TYPES_H +#define MEMORY_TYPES_H + +#include +#include + +#include +#include +#include + +#include +#include +#include + +/** @brief Memory Manager events base. + */ +ESP_EVENT_DECLARE_BASE(MEMORY_EVENTS); + +/** @brief Memory Manager event identifiers. + */ +enum { + MEMORY_EVENT_SD_CARD_MOUNTED, /**< SD card was successfully mounted and is ready for use. */ + MEMORY_EVENT_FLASH_MOUNTED /**< Internal flash storage was mounted and is ready for use. */ +}; + +#endif /* MEMORY_TYPES_H */ diff --git a/main/Application/Manager/Network/DNS/dnsServer.cpp b/main/Application/Manager/Network/DNS/dnsServer.cpp index a5872f2..9f711bd 100644 --- a/main/Application/Manager/Network/DNS/dnsServer.cpp +++ b/main/Application/Manager/Network/DNS/dnsServer.cpp @@ -40,16 +40,14 @@ /** @brief DNS header structure. */ -typedef struct __attribute__((packed)) -{ +typedef struct { uint16_t ID; /**< Identification */ uint16_t Flags; /**< Flags */ uint16_t QDCount; /**< Number of questions */ uint16_t ANCount; /**< Number of answer RRs */ uint16_t NSCount; /**< Number of authority RRs */ uint16_t ARCount; /**< Number of additional RRs */ -} -DNS_Header_t; +} __attribute__((packed)) DNS_Header_t; typedef struct { bool isRunning; @@ -59,7 +57,7 @@ typedef struct { static DNS_Server_State_t _DNS_Server_State; -static const char *TAG = "DNS_Server"; +static const char *TAG = "DNS-Server"; /** @brief DNS server task. * @param p_Arg Task argument (not used) @@ -153,6 +151,7 @@ esp_err_t DNS_Server_Start(void) if (_DNS_Server_State.isRunning) { ESP_LOGW(TAG, "DNS server already running"); + return ESP_OK; } @@ -160,6 +159,7 @@ esp_err_t DNS_Server_Start(void) _DNS_Server_State.Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (_DNS_Server_State.Socket < 0) { ESP_LOGE(TAG, "Failed to create socket: %d!", errno); + return ESP_FAIL; } @@ -168,7 +168,7 @@ esp_err_t DNS_Server_Start(void) Timeout.tv_sec = 1; Timeout.tv_usec = 0; if (setsockopt(_DNS_Server_State.Socket, SOL_SOCKET, SO_RCVTIMEO, &Timeout, sizeof(Timeout)) < 0) { - ESP_LOGW(TAG, "Failed to set socket timeout: %d", errno); + ESP_LOGW(TAG, "Failed to set socket timeout: %d!", errno); } /* Bind to DNS port */ @@ -179,7 +179,9 @@ esp_err_t DNS_Server_Start(void) if (bind(_DNS_Server_State.Socket, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) { ESP_LOGE(TAG, "Failed to bind socket: %d!", errno); + close(_DNS_Server_State.Socket); + return ESP_FAIL; } diff --git a/main/Application/Manager/Network/DNS/dnsServer.h b/main/Application/Manager/Network/DNS/dnsServer.h index 4e649d1..14f1a3f 100644 --- a/main/Application/Manager/Network/DNS/dnsServer.h +++ b/main/Application/Manager/Network/DNS/dnsServer.h @@ -21,19 +21,19 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ -#ifndef DNSSERVER_H_ -#define DNSSERVER_H_ +#ifndef DNS_SERVER_H_ +#define DNS_SERVER_H_ #include -/** @brief Start DNS server for captive portal. +/** @brief Start the DNS server for captive portal. * Redirects all DNS queries to the ESP32's IP address. * @return ESP_OK on success */ esp_err_t DNS_Server_Start(void); -/** @brief Stop DNS server. +/** @brief Stop the DNS server. */ void DNS_Server_Stop(void); -#endif /* DNSSERVER_H_ */ +#endif /* DNS_SERVER_H_ */ diff --git a/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp b/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp index 2e6c8b2..2e085ec 100644 --- a/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp +++ b/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp @@ -37,7 +37,7 @@ #include "../networkManager.h" #include "../../Settings/settingsManager.h" -static const char *TAG = "ProvisionHandlers"; +static const char *TAG = "Provision-Handlers"; /* Embed HTML file */ extern const uint8_t provision_html_start[] asm("_binary_provision_html_start"); @@ -53,7 +53,7 @@ extern const uint8_t logo_png_end[] asm("_binary_logo_png_end"); * @param StatusCode HTTP status code * @return ESP_OK on success */ -static esp_err_t send_JSON_Response(httpd_req_t *p_Request, cJSON *p_JSON, int StatusCode) +static esp_err_t Provision_Handler_Send_JSON_Response(httpd_req_t *p_Request, cJSON *p_JSON, int StatusCode) { esp_err_t Error; @@ -137,7 +137,7 @@ esp_err_t Provision_Handler_Scan(httpd_req_t *p_Request) Response = cJSON_CreateObject(); cJSON_AddArrayToObject(Response, "networks"); - return send_JSON_Response(p_Request, Response, 200); + return Provision_Handler_Send_JSON_Response(p_Request, Response, 200); } /* Wait for scan to complete (max 10 seconds) */ @@ -153,7 +153,7 @@ esp_err_t Provision_Handler_Scan(httpd_req_t *p_Request) Response = cJSON_CreateObject(); cJSON_AddArrayToObject(Response, "networks"); - return send_JSON_Response(p_Request, Response, 200); + return Provision_Handler_Send_JSON_Response(p_Request, Response, 200); } wifi_ap_record_t *APList = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * APCount); @@ -180,7 +180,7 @@ esp_err_t Provision_Handler_Scan(httpd_req_t *p_Request) free(APList); - return send_JSON_Response(p_Request, Response, 200); + return Provision_Handler_Send_JSON_Response(p_Request, Response, 200); } esp_err_t Provision_Handler_Connect(httpd_req_t *p_Request) @@ -262,7 +262,7 @@ esp_err_t Provision_Handler_Connect(httpd_req_t *p_Request) cJSON_AddBoolToObject(Response, "success", true); cJSON_AddStringToObject(Response, "message", "Credentials saved, connecting to WiFi..."); - send_JSON_Response(p_Request, Response, 200); + Provision_Handler_Send_JSON_Response(p_Request, Response, 200); /* Post event with short timeout to avoid blocking HTTP task */ esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_SUCCESS, NULL, 0, pdMS_TO_TICKS(100)); @@ -271,12 +271,12 @@ esp_err_t Provision_Handler_Connect(httpd_req_t *p_Request) cJSON_AddBoolToObject(Response, "success", false); cJSON_AddStringToObject(Response, "error", "NVS storage full, please reset device"); - send_JSON_Response(p_Request, Response, 500); + Provision_Handler_Send_JSON_Response(p_Request, Response, 500); } } else { cJSON_AddBoolToObject(Response, "success", false); cJSON_AddStringToObject(Response, "error", "Failed to save credentials"); - send_JSON_Response(p_Request, Response, 400); + Provision_Handler_Send_JSON_Response(p_Request, Response, 400); } cJSON_Delete(JSON); diff --git a/main/Application/Manager/Network/Provisioning/provisionHandlers.h b/main/Application/Manager/Network/Provisioning/provisionHandlers.h index 7b7c096..7d15d90 100644 --- a/main/Application/Manager/Network/Provisioning/provisionHandlers.h +++ b/main/Application/Manager/Network/Provisioning/provisionHandlers.h @@ -21,8 +21,8 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ -#ifndef PROVISIONHANDLERS_H_ -#define PROVISIONHANDLERS_H_ +#ifndef PROVISION_HANDLERS_H_ +#define PROVISION_HANDLERS_H_ #include @@ -57,4 +57,4 @@ esp_err_t Provision_Handler_Connect(httpd_req_t *p_Request); */ esp_err_t Provision_Handler_CaptivePortal(httpd_req_t *p_Request); -#endif /* PROVISIONHANDLERS_H_ */ +#endif /* PROVISION_HANDLERS_H_ */ diff --git a/main/Application/Manager/Network/Provisioning/provisioning.cpp b/main/Application/Manager/Network/Provisioning/provisioning.cpp index 1534759..b0ed3c6 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.cpp +++ b/main/Application/Manager/Network/Provisioning/provisioning.cpp @@ -38,12 +38,11 @@ typedef struct { bool isInitialized; - bool active; - bool use_captive_portal; - char device_name[32]; - char pop[32]; - uint32_t timeout_sec; - esp_timer_handle_t timeout_timer; + bool isActive; + bool usePortal; + char Name[32]; + uint32_t TimeOut; + esp_timer_handle_t TimeoutTimer; wifi_sta_config_t WiFi_STA_Config; bool hasCredentials; } Provisioning_State_t; @@ -55,7 +54,7 @@ static const char *TAG = "Provisioning"; /** @brief Timeout timer callback. * @param p_Arg Timer argument */ -static void on_Timeout_Timer_Handler(void *p_Arg) +static void on_TimeoutTimer_Handler(void *p_Arg) { ESP_LOGI(TAG, "Provisioning timeout reached"); esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_TIMEOUT, NULL, 0, pdMS_TO_TICKS(100)); @@ -102,8 +101,8 @@ static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t Event ESP_LOGD(TAG, "Provisioning successful"); - if (_Provisioning_State.timeout_timer != NULL) { - esp_timer_stop(_Provisioning_State.timeout_timer); + if (_Provisioning_State.TimeoutTimer != NULL) { + esp_timer_stop(_Provisioning_State.TimeoutTimer); } memset(&Credentials, 0, sizeof(Credentials)); @@ -126,7 +125,7 @@ static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t Event wifi_prov_mgr_deinit(); - _Provisioning_State.active = false; + _Provisioning_State.isActive = false; break; } @@ -136,62 +135,32 @@ static void on_Prov_Event(void *p_Arg, esp_event_base_t EventBase, int32_t Event } } -/** @brief Custom endpoint handler for device info. - * @param session_id Session ID - * @param inbuf Input buffer - * @param inlen Input length - * @param outbuf Output buffer - * @param outlen Output length - * @param priv_data Private data - * @return ESP_OK on success - */ -static esp_err_t on_Custom_Data_Prov_Handler(uint32_t session_id, const uint8_t *p_InBuf, - ssize_t inlen, uint8_t **p_OutBuf, - ssize_t *p_OutLen, void *p_PrivData) -{ - if (p_InBuf) { - ESP_LOGD(TAG, "Received custom data: %.*s", (int)inlen, (char *)p_InBuf); - } - - const char *response = "{\"device\":\"PyroVision\",\"version\":\"1.0\"}"; - *p_OutLen = strlen(response); - *p_OutBuf = (uint8_t *)heap_caps_malloc(*p_OutLen, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - - if (*p_OutBuf == NULL) { - ESP_LOGE(TAG, "Failed to allocate response buffer!"); - return ESP_ERR_NO_MEM; - } - - memcpy(*p_OutBuf, response, *p_OutLen); - - return ESP_OK; -} - esp_err_t Provisioning_Init(Network_Provisioning_Config_t *p_Config) { if (_Provisioning_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; } else if (p_Config == NULL) { return ESP_ERR_INVALID_ARG; } ESP_LOGD(TAG, "Initializing Provisioning Manager"); - strncpy(_Provisioning_State.device_name, p_Config->Name, - sizeof(_Provisioning_State.device_name) - 1); - _Provisioning_State.timeout_sec = p_Config->Timeout; - _Provisioning_State.use_captive_portal = true; + strncpy(_Provisioning_State.Name, p_Config->Name, + sizeof(_Provisioning_State.Name) - 1); + _Provisioning_State.TimeOut = p_Config->Timeout; + _Provisioning_State.usePortal = true; ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &on_Prov_Event, NULL)); const esp_timer_create_args_t timer_args = { - .callback = on_Timeout_Timer_Handler, + .callback = on_TimeoutTimer_Handler, .arg = NULL, .dispatch_method = ESP_TIMER_TASK, .name = "prov_timeout", .skip_unhandled_events = false }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &_Provisioning_State.timeout_timer)); + ESP_ERROR_CHECK(esp_timer_create(&timer_args, &_Provisioning_State.TimeoutTimer)); _Provisioning_State.isInitialized = true; @@ -212,9 +181,9 @@ void Provisioning_Deinit(void) wifi_prov_mgr_deinit(); - if (_Provisioning_State.timeout_timer != NULL) { - esp_timer_delete(_Provisioning_State.timeout_timer); - _Provisioning_State.timeout_timer = NULL; + if (_Provisioning_State.TimeoutTimer != NULL) { + esp_timer_delete(_Provisioning_State.TimeoutTimer); + _Provisioning_State.TimeoutTimer = NULL; } esp_event_handler_unregister(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &on_Prov_Event); @@ -225,174 +194,127 @@ void Provisioning_Deinit(void) esp_err_t Provisioning_Start(void) { esp_err_t Error; - wifi_prov_mgr_config_t prov_config; - const char *pop = NULL; - char service_name[32]; - uint8_t mac[6]; + uint8_t MAC[6]; + wifi_config_t Config; + Network_HTTP_Server_Config_t ServerConfig; if (_Provisioning_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - if (_Provisioning_State.active) { + if (_Provisioning_State.isActive) { ESP_LOGW(TAG, "Provisioning already active"); + return ESP_OK; } - memset(&prov_config, 0, sizeof(prov_config)); - - ESP_LOGD(TAG, "Starting Provisioning"); - - if (_Provisioning_State.use_captive_portal) { - uint8_t MAC[6]; - wifi_config_t Config; - Network_HTTP_Server_Config_t ServerConfig; - - ESP_LOGI(TAG, "Using captive portal provisioning"); + ESP_LOGI(TAG, "Starting captive portal provisioning"); - NetworkManager_GetMAC(MAC); + NetworkManager_GetMAC(MAC); - /* Create unique SSID */ - snprintf((char *)Config.ap.ssid, sizeof(Config.ap.ssid), - "%.26s-%02X%02X", _Provisioning_State.device_name, MAC[4], MAC[5]); - Config.ap.ssid_len = strlen((char *)Config.ap.ssid); - Config.ap.channel = 1; - Config.ap.authmode = WIFI_AUTH_OPEN; - Config.ap.max_connection = 4; + /* Create unique SSID */ + snprintf(reinterpret_cast(Config.ap.ssid), sizeof(Config.ap.ssid), + "%.26s-%02X%02X", _Provisioning_State.Name, MAC[4], MAC[5]); + Config.ap.ssid_len = strlen(reinterpret_cast(Config.ap.ssid)); + Config.ap.channel = 1; + Config.ap.authmode = WIFI_AUTH_OPEN; + Config.ap.max_connection = 4; - ESP_LOGI(TAG, "Starting SoftAP with SSID: %s", Config.ap.ssid); + ESP_LOGI(TAG, "Starting SoftAP with SSID: %s", Config.ap.ssid); - /* Set APSTA mode to allow WiFi scanning while AP is active */ - Error = esp_wifi_set_mode(WIFI_MODE_APSTA); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to set APSTA mode: %d!", Error); - return Error; - } - - Error = esp_wifi_set_config(WIFI_IF_AP, &Config); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to set AP config: %d!", Error); - return Error; - } - - Error = esp_wifi_start(); - if ((Error != ESP_OK) && (Error != ESP_ERR_WIFI_STATE)) { - ESP_LOGE(TAG, "Failed to start WiFi: %d!", Error); - return Error; - } - - vTaskDelay(100 / portTICK_PERIOD_MS); - - /* Start HTTP server with minimal configuration for provisioning */ - ServerConfig.Port = 80; - ServerConfig.MaxClients = 1; /* Only one client for provisioning */ - ServerConfig.EnableCORS = true; - ServerConfig.API_Key = NULL; - - /* Initialize HTTP server first (without WebSocket) */ - Error = HTTP_Server_Init(&ServerConfig); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to init HTTP server: 0x%x!", Error); - - esp_wifi_stop(); - - return Error; - } - - Error = HTTP_Server_Start(); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to start HTTP server: 0x%x!", Error); - - HTTP_Server_Deinit(); - esp_wifi_stop(); - - return Error; - } + /* Set APSTA mode to allow WiFi scanning while AP is active */ + Error = esp_wifi_set_mode(WIFI_MODE_APSTA); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set APSTA mode: %d!", Error); - /* Start DNS server for captive portal */ - Error = DNS_Server_Start(); - if (Error != ESP_OK) { - ESP_LOGW(TAG, "Failed to start DNS server: %d!", Error); - /* Continue anyway, DNS is not critical */ - } + return Error; + } - _Provisioning_State.active = true; - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STARTED, NULL, 0, portMAX_DELAY); + Error = esp_wifi_set_config(WIFI_IF_AP, &Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set AP config: %d!", Error); - /* Start timeout timer */ - if (_Provisioning_State.timeout_timer != NULL) { - esp_timer_start_once(_Provisioning_State.timeout_timer, _Provisioning_State.timeout_sec * 1000000ULL); - } + return Error; + } - /* Get and log the actual AP IP address */ - esp_netif_t *ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); - if (ap_netif != NULL) { - esp_netif_ip_info_t ip_info; - if (esp_netif_get_ip_info(ap_netif, &ip_info) == ESP_OK) { - ESP_LOGI(TAG, "Captive portal started at http://" IPSTR, IP2STR(&ip_info.ip)); - } else { - ESP_LOGI(TAG, "Captive portal started at http://192.168.4.1"); - } - } else { - ESP_LOGI(TAG, "Captive portal started at http://192.168.4.1"); - } + Error = esp_wifi_start(); + if ((Error != ESP_OK) && (Error != ESP_ERR_WIFI_STATE)) { + ESP_LOGE(TAG, "Failed to start WiFi: %d!", Error); - return ESP_OK; + return Error; } - /* Use ESP Provisioning API (original protobuf method) */ - prov_config.scheme = wifi_prov_scheme_softap; - prov_config.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; - prov_config.app_event_handler = WIFI_PROV_EVENT_HANDLER_NONE; + vTaskDelay(100 / portTICK_PERIOD_MS); - Error = wifi_prov_mgr_init(prov_config); + /* Start HTTP server with minimal configuration for provisioning */ + ServerConfig.Port = 80; + ServerConfig.MaxClients = 1; /* Only one client for provisioning */ + ServerConfig.EnableCORS = true; + ServerConfig.API_Key = NULL; + + /* Initialize HTTP server first (without WebSocket) */ + Error = HTTP_Server_Init(&ServerConfig); if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to init Provisioning: %d!", Error); + ESP_LOGE(TAG, "Failed to init HTTP server: 0x%x!", Error); + + esp_wifi_stop(); return Error; } - NetworkManager_GetMAC(mac); - snprintf(service_name, sizeof(service_name), "%.26s_%02X%02X", _Provisioning_State.device_name, mac[4], mac[5]); - - /* Register custom endpoint */ - wifi_prov_mgr_endpoint_create("custom-data"); - - Error = wifi_prov_mgr_start_provisioning(WIFI_PROV_SECURITY_1, - pop, service_name, NULL); + Error = HTTP_Server_Start(); if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to start provisioning: %d!", Error); + ESP_LOGE(TAG, "Failed to start HTTP server: 0x%x!", Error); - wifi_prov_mgr_deinit(); + HTTP_Server_Deinit(); + esp_wifi_stop(); return Error; } - wifi_prov_mgr_endpoint_register("custom-data", on_Custom_Data_Prov_Handler, NULL); - _Provisioning_State.active = true; + /* Start DNS server for captive portal */ + Error = DNS_Server_Start(); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to start DNS server: %d!", Error); + /* Continue anyway, DNS is not critical */ + } + _Provisioning_State.isActive = true; esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STARTED, NULL, 0, portMAX_DELAY); - if (_Provisioning_State.timeout_timer != NULL) { - esp_timer_start_once(_Provisioning_State.timeout_timer, _Provisioning_State.timeout_sec * 1000000ULL); + /* Start timeout timer */ + if (_Provisioning_State.TimeoutTimer != NULL) { + esp_timer_start_once(_Provisioning_State.TimeoutTimer, _Provisioning_State.TimeOut * 1000000ULL); } - ESP_LOGD(TAG, "Provisioning started. Service name: %s", service_name); + /* Get and log the actual AP IP address */ + esp_netif_t *ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); + if (ap_netif != NULL) { + esp_netif_ip_info_t ip_info; + + if (esp_netif_get_ip_info(ap_netif, &ip_info) == ESP_OK) { + ESP_LOGI(TAG, "Captive portal started at http://" IPSTR, IP2STR(&ip_info.ip)); + } else { + ESP_LOGI(TAG, "Captive portal started at http://192.168.4.1"); + } + } else { + ESP_LOGI(TAG, "Captive portal started at http://192.168.4.1"); + } return ESP_OK; } esp_err_t Provisioning_Stop(void) { - if (_Provisioning_State.active == false) { + if (_Provisioning_State.isActive == false) { return ESP_OK; } ESP_LOGI(TAG, "Stopping Provisioning"); - _Provisioning_State.active = false; + _Provisioning_State.isActive = false; - if (_Provisioning_State.use_captive_portal) { + if (_Provisioning_State.usePortal) { ESP_LOGD(TAG, "Stopping DNS server"); DNS_Server_Stop(); @@ -410,13 +332,14 @@ esp_err_t Provisioning_Stop(void) ESP_LOGD(TAG, "Provisioning stopped"); } else { - if (_Provisioning_State.timeout_timer != NULL) { - esp_timer_stop(_Provisioning_State.timeout_timer); + if (_Provisioning_State.TimeoutTimer != NULL) { + esp_timer_stop(_Provisioning_State.TimeoutTimer); } + wifi_prov_mgr_stop_provisioning(); } - esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STOPPED, NULL, 0, pdMS_TO_TICKS(100)); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_PROV_STOPPED, NULL, 0, portMAX_DELAY); return ESP_OK; } @@ -450,7 +373,7 @@ esp_err_t Provisioning_Reset(void) return ESP_OK; } -bool Provisioning_isActive(void) +bool Provisioning_IsActive(void) { - return _Provisioning_State.active; + return _Provisioning_State.isActive; } \ No newline at end of file diff --git a/main/Application/Manager/Network/Provisioning/provisioning.h b/main/Application/Manager/Network/Provisioning/provisioning.h index 61ae289..0be2ed7 100644 --- a/main/Application/Manager/Network/Provisioning/provisioning.h +++ b/main/Application/Manager/Network/Provisioning/provisioning.h @@ -62,6 +62,6 @@ esp_err_t Provisioning_Reset(void); /** @brief Check if provisioning is active. * @return true if provisioning is running */ -bool Provisioning_isActive(void); +bool Provisioning_IsActive(void); #endif /* PROVISIONING_H_ */ diff --git a/main/Application/Manager/Network/SNTP/sntp.cpp b/main/Application/Manager/Network/SNTP/sntp.cpp index d1e26bf..af29867 100644 --- a/main/Application/Manager/Network/SNTP/sntp.cpp +++ b/main/Application/Manager/Network/SNTP/sntp.cpp @@ -29,7 +29,7 @@ ESP_EVENT_DEFINE_BASE(SNTP_EVENTS); -static const char *TAG = "sntp"; +static const char *TAG = "SNTP"; /** @brief SNTP time synchronization callback. * @param p_tv Pointer to timeval structure with synchronized time @@ -41,7 +41,7 @@ static void on_SNTP_Time_Sync(struct timeval *p_tv) esp_event_post(SNTP_EVENTS, SNTP_EVENT_SNTP_SYNCED, p_tv, sizeof(struct timeval), portMAX_DELAY); } -esp_err_t SNTP_Init(const char* p_Timezone, const char* p_Server, uint32_t SyncInterval) +esp_err_t SNTP_Init(const char *p_Timezone, const char *p_Server, uint32_t SyncInterval) { esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); esp_sntp_setservername(0, p_Server); @@ -93,7 +93,7 @@ esp_err_t SNTP_GetTime(uint8_t Retries) return ESP_OK; } -void SNTP_SetTimezone(const char* p_Timezone) +void SNTP_SetTimezone(const char *p_Timezone) { setenv("TZ", p_Timezone, 1); tzset(); diff --git a/main/Application/Manager/Network/SNTP/sntp.h b/main/Application/Manager/Network/SNTP/sntp.h index 8eefa04..2fbc132 100644 --- a/main/Application/Manager/Network/SNTP/sntp.h +++ b/main/Application/Manager/Network/SNTP/sntp.h @@ -29,6 +29,10 @@ #include +/** @brief SNTP events base. + */ +ESP_EVENT_DECLARE_BASE(SNTP_EVENTS); + /** @brief SNTP event types (used as event IDs in SNTP_EVENTS base). */ typedef enum { @@ -38,15 +42,14 @@ typedef enum { Data is of type const char* */ } SNTP_Event_t; -ESP_EVENT_DECLARE_BASE(SNTP_EVENTS); - /** @brief Initialize SNTP and event handlers. * @param p_Timezone Timezone string (e.g. "CET-1CEST,M3.5.0,M10.5.0/3") * @param p_Server NTP server address (e.g. "pool.ntp.org") * @param SyncInterval SNTP sync interval in seconds * @return ESP_OK on success */ -esp_err_t SNTP_Init(const char* p_Timezone = "CET-1CEST,M3.5.0,M10.5.0/3", const char* p_Server = "pool.ntp.org", uint32_t SyncInterval = 3600); +esp_err_t SNTP_Init(const char *p_Timezone = "CET-1CEST,M3.5.0,M10.5.0/3", const char *p_Server = "pool.ntp.org", + uint32_t SyncInterval = 3600); /** @brief Deinitialize SNTP and event handlers. * @return ESP_OK on success @@ -62,6 +65,6 @@ esp_err_t SNTP_GetTime(uint8_t Retries); /** @brief Set SNTP timezone. * @param p_Timezone Timezone string (e.g. "CET-1CEST,M3.5.0,M10.5.0/3") */ -void SNTP_SetTimezone(const char* p_Timezone); +void SNTP_SetTimezone(const char *p_Timezone); #endif /* SNTP_H_ */ \ No newline at end of file diff --git a/main/Application/Manager/Network/Server/http_server.cpp b/main/Application/Manager/Network/Server/HTTP/http_server.cpp similarity index 81% rename from main/Application/Manager/Network/Server/http_server.cpp rename to main/Application/Manager/Network/Server/HTTP/http_server.cpp index c220842..c8fa992 100644 --- a/main/Application/Manager/Network/Server/http_server.cpp +++ b/main/Application/Manager/Network/Server/HTTP/http_server.cpp @@ -34,10 +34,9 @@ #include #include "http_server.h" -#include "ImageEncoder/imageEncoder.h" -#include "../networkTypes.h" -#include "../Provisioning/provisionHandlers.h" -#include "../SNTP/sntp.h" +#include "../ImageEncoder/imageEncoder.h" +#include "../../Provisioning/provisionHandlers.h" +#include "../../SNTP/sntp.h" #define HTTP_SERVER_API_BASE_PATH "/api/v1" #define HTTP_SERVER_API_KEY_HEADER "X-API-Key" @@ -52,9 +51,9 @@ typedef struct { uint32_t StartTime; } HTTP_Server_State_t; -static HTTP_Server_State_t _HTTPServer_State; +static HTTP_Server_State_t _HTTP_Server_State; -static const char *TAG = "http_server"; +static const char *TAG = "HTTP-Server"; /** @brief Check API key authentication. * @param p_Request HTTP request handle @@ -64,7 +63,7 @@ static bool HTTP_Server_CheckAuth(httpd_req_t *p_Request) { char ApiKey[64] = {0}; - if (_HTTPServer_State.Config.API_Key == NULL) { + if (_HTTP_Server_State.Config.API_Key == NULL) { return true; } @@ -72,7 +71,7 @@ static bool HTTP_Server_CheckAuth(httpd_req_t *p_Request) return false; } - return (strcmp(ApiKey, _HTTPServer_State.Config.API_Key) == 0); + return (strcmp(ApiKey, _HTTP_Server_State.Config.API_Key) == 0); } /** @brief Send JSON response. @@ -99,7 +98,7 @@ static esp_err_t HTTP_Server_SendJSON(httpd_req_t *p_Request, cJSON *p_JSON, int httpd_resp_set_type(p_Request, "application/json"); - if (_HTTPServer_State.Config.EnableCORS) { + if (_HTTP_Server_State.Config.EnableCORS) { httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Origin", "*"); } @@ -140,23 +139,21 @@ static esp_err_t HTTP_Server_SendError(httpd_req_t *p_Request, int StatusCode, c */ static cJSON *HTTP_Server_ParseJSON(httpd_req_t *p_Request) { - int ContentLen = p_Request->content_len; - if (ContentLen <= 0 || ContentLen > 4096) { + if ((p_Request->content_len <= 0) || (p_Request->content_len > 4096)) { return NULL; } - char *Buffer = (char *)heap_caps_malloc(ContentLen + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + char *Buffer = (char *)heap_caps_malloc(p_Request->content_len + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (Buffer == NULL) { return NULL; } - int Received = httpd_req_recv(p_Request, Buffer, ContentLen); - if (Received != ContentLen) { + if (httpd_req_recv(p_Request, Buffer, p_Request->content_len) != p_Request->content_len) { free(Buffer); return NULL; } - Buffer[ContentLen] = '\0'; + Buffer[p_Request->content_len] = '\0'; cJSON *Json = cJSON_Parse(Buffer); free(Buffer); @@ -171,7 +168,7 @@ static esp_err_t HTTP_Handler_Time(httpd_req_t *p_Request) { esp_err_t Error; - _HTTPServer_State.RequestCount++; + _HTTP_Server_State.RequestCount++; if (HTTP_Server_CheckAuth(p_Request) == false) { return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); @@ -227,11 +224,11 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) Network_ImageFormat_t format = NETWORK_IMAGE_FORMAT_JPEG; Server_Palette_t palette = PALETTE_IRON; - _HTTPServer_State.RequestCount++; + _HTTP_Server_State.RequestCount++; if (HTTP_Server_CheckAuth(p_Request) == false) { return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); - } else if (_HTTPServer_State.ThermalFrame == NULL) { + } else if (_HTTP_Server_State.ThermalFrame == NULL) { return HTTP_Server_SendError(p_Request, 503, "No thermal data available"); } @@ -253,13 +250,13 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) } } - if (xSemaphoreTake(_HTTPServer_State.ThermalFrame->Mutex, 100 / portTICK_PERIOD_MS) != pdTRUE) { + if (xSemaphoreTake(_HTTP_Server_State.ThermalFrame->Mutex, 100 / portTICK_PERIOD_MS) != pdTRUE) { return HTTP_Server_SendError(p_Request, 503, "Frame busy"); } - Error = ImageEncoder_Encode(_HTTPServer_State.ThermalFrame, format, palette, &encoded); + Error = ImageEncoder_Encode(_HTTP_Server_State.ThermalFrame, format, palette, &encoded); - xSemaphoreGive(_HTTPServer_State.ThermalFrame->Mutex); + xSemaphoreGive(_HTTP_Server_State.ThermalFrame->Mutex); if (Error != ESP_OK) { return HTTP_Server_SendError(p_Request, 500, "Image encoding failed"); @@ -278,7 +275,7 @@ static esp_err_t HTTP_Handler_Image(httpd_req_t *p_Request) break; } - if (_HTTPServer_State.Config.EnableCORS) { + if (_HTTP_Server_State.Config.EnableCORS) { httpd_resp_set_hdr(p_Request, "Access-Control-Allow-Origin", "*"); } @@ -298,7 +295,7 @@ static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) { esp_err_t Error; - _HTTPServer_State.RequestCount++; + _HTTP_Server_State.RequestCount++; if (HTTP_Server_CheckAuth(p_Request) == false) { return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); @@ -310,9 +307,9 @@ static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) cJSON_AddNumberToObject(json, "uptime_s", uptime); /* Sensor temperature (from thermal frame if available) */ - if (_HTTPServer_State.ThermalFrame != NULL) { + if (_HTTP_Server_State.ThermalFrame != NULL) { // TODO - //cJSON_AddNumberToObject(json, "sensor_temp_c", _HTTPServer_State.ThermalFrame->temp_avg); + //cJSON_AddNumberToObject(json, "sensor_temp_c", _HTTP_Server_State.ThermalFrame->temp_avg); } cJSON_AddNumberToObject(json, "supply_voltage_v", 0); @@ -341,13 +338,12 @@ static esp_err_t HTTP_Handler_Telemetry(httpd_req_t *p_Request) */ static esp_err_t HTTP_Handler_Update(httpd_req_t *p_Request) { - int content_len; - int received = 0; - int total_received = 0; + int Received; + int Total_Received; esp_err_t Error; esp_ota_handle_t ota_handle; - _HTTPServer_State.RequestCount++; + _HTTP_Server_State.RequestCount++; if (HTTP_Server_CheckAuth(p_Request) == false) { return HTTP_Server_SendError(p_Request, 401, "Unauthorized"); @@ -375,12 +371,12 @@ static esp_err_t HTTP_Handler_Update(httpd_req_t *p_Request) return HTTP_Server_SendError(p_Request, 500, "Memory allocation failed"); } - content_len = p_Request->content_len; - - while (total_received < content_len) { - received = httpd_req_recv(p_Request, buffer, 1024); - if (received <= 0) { - if (received == HTTPD_SOCK_ERR_TIMEOUT) { + Received = 0; + Total_Received = 0; + while (Total_Received < p_Request->content_len) { + Received = httpd_req_recv(p_Request, buffer, 1024); + if (Received <= 0) { + if (Received == HTTPD_SOCK_ERR_TIMEOUT) { continue; } free(buffer); @@ -389,7 +385,7 @@ static esp_err_t HTTP_Handler_Update(httpd_req_t *p_Request) return HTTP_Server_SendError(p_Request, 500, "Receive failed"); } - Error = esp_ota_write(ota_handle, buffer, received); + Error = esp_ota_write(ota_handle, buffer, Received); if (Error != ESP_OK) { free(buffer); esp_ota_abort(ota_handle); @@ -398,8 +394,8 @@ static esp_err_t HTTP_Handler_Update(httpd_req_t *p_Request) return HTTP_Server_SendError(p_Request, 500, "OTA write failed"); } - total_received += received; - ESP_LOGD(TAG, "OTA progress: %d/%d bytes", total_received, content_len); + Total_Received += Received; + ESP_LOGD(TAG, "OTA progress: %d/%d bytes", Total_Received, p_Request->content_len); } free(buffer); @@ -563,31 +559,33 @@ esp_err_t HTTP_Server_Init(const Network_HTTP_Server_Config_t *p_Config) return ESP_ERR_INVALID_ARG; } - if (_HTTPServer_State.isInitialized) { + if (_HTTP_Server_State.isInitialized) { ESP_LOGW(TAG, "Already initialized, updating config"); - memcpy(&_HTTPServer_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); + + memcpy(&_HTTP_Server_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); + return ESP_OK; } ESP_LOGD(TAG, "Initializing HTTP server"); - memcpy(&_HTTPServer_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); - _HTTPServer_State.Handle = NULL; - _HTTPServer_State.ThermalFrame = NULL; - _HTTPServer_State.RequestCount = 0; - _HTTPServer_State.isInitialized = true; + memcpy(&_HTTP_Server_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); + _HTTP_Server_State.Handle = NULL; + _HTTP_Server_State.ThermalFrame = NULL; + _HTTP_Server_State.RequestCount = 0; + _HTTP_Server_State.isInitialized = true; return ESP_OK; } void HTTP_Server_Deinit(void) { - if (_HTTPServer_State.isInitialized == false) { + if (_HTTP_Server_State.isInitialized == false) { return; } HTTP_Server_Stop(); - _HTTPServer_State.isInitialized = false; + _HTTP_Server_State.isInitialized = false; ESP_LOGD(TAG, "HTTP server deinitialized"); } @@ -596,15 +594,15 @@ esp_err_t HTTP_Server_Start(void) { esp_err_t Error; - if (_HTTPServer_State.isInitialized == false) { + if (_HTTP_Server_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_HTTPServer_State.isRunning) { + } else if (_HTTP_Server_State.isRunning) { ESP_LOGW(TAG, "Server already running"); return ESP_OK; } httpd_config_t config = HTTPD_DEFAULT_CONFIG(); - config.server_port = _HTTPServer_State.Config.Port; + config.server_port = _HTTP_Server_State.Config.Port; config.max_uri_handlers = 12; /* Use only 2 sockets for provisioning */ @@ -629,30 +627,30 @@ esp_err_t HTTP_Server_Start(void) ESP_LOGD(TAG, "Starting HTTP server on port %d", config.server_port); - Error = httpd_start(&_HTTPServer_State.Handle, &config); + Error = httpd_start(&_HTTP_Server_State.Handle, &config); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to start HTTP server: %d!", Error); return Error; } /* Register URI handlers */ - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Root); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Logo); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Scan); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Provision_Connect); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_CaptivePortal_Generate204); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_CaptivePortal_Generate204_NoUnderscore); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Time); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Image); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Telemetry); - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Update); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Provision_Root); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Provision_Logo); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Provision_Scan); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Provision_Connect); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_CaptivePortal_Generate204); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_CaptivePortal_Generate204_NoUnderscore); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Time); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Image); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Telemetry); + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Update); - if (_HTTPServer_State.Config.EnableCORS) { - httpd_register_uri_handler(_HTTPServer_State.Handle, &_URI_Options); + if (_HTTP_Server_State.Config.EnableCORS) { + httpd_register_uri_handler(_HTTP_Server_State.Handle, &_URI_Options); } - _HTTPServer_State.isRunning = true; - _HTTPServer_State.StartTime = esp_timer_get_time() / 1000000; + _HTTP_Server_State.isRunning = true; + _HTTP_Server_State.StartTime = esp_timer_get_time() / 1000000; ESP_LOGD(TAG, "HTTP server started"); @@ -661,29 +659,29 @@ esp_err_t HTTP_Server_Start(void) esp_err_t HTTP_Server_Stop(void) { - if (_HTTPServer_State.isRunning == false) { + if (_HTTP_Server_State.isRunning == false) { return ESP_OK; } ESP_LOGD(TAG, "Stopping HTTP server"); - _HTTPServer_State.isRunning = false; - _HTTPServer_State.Handle = NULL; + _HTTP_Server_State.isRunning = false; + _HTTP_Server_State.Handle = NULL; return ESP_OK; } -bool HTTP_Server_isRunning(void) +bool HTTP_Server_IsRunning(void) { - return _HTTPServer_State.isRunning; + return _HTTP_Server_State.isRunning; } void HTTP_Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) { - _HTTPServer_State.ThermalFrame = p_Frame; + _HTTP_Server_State.ThermalFrame = p_Frame; } httpd_handle_t HTTP_Server_GetHandle(void) { - return _HTTPServer_State.Handle; + return _HTTP_Server_State.Handle; } diff --git a/main/Application/Manager/Network/Server/http_server.h b/main/Application/Manager/Network/Server/HTTP/http_server.h similarity index 96% rename from main/Application/Manager/Network/Server/http_server.h rename to main/Application/Manager/Network/Server/HTTP/http_server.h index 6194e13..236d4be 100644 --- a/main/Application/Manager/Network/Server/http_server.h +++ b/main/Application/Manager/Network/Server/HTTP/http_server.h @@ -27,7 +27,7 @@ #include #include -#include "../networkTypes.h" +#include "../../networkTypes.h" /** @brief Initialize the HTTP server. * @param p_Config Pointer to server configuration. @@ -52,7 +52,7 @@ esp_err_t HTTP_Server_Stop(void); /** @brief Check if the HTTP server is running. * @return true if running */ -bool HTTP_Server_isRunning(void); +bool HTTP_Server_IsRunning(void); /** @brief Set thermal frame data for image endpoint. * @param p_Frame Pointer to thermal frame data. diff --git a/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp b/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp index d20812b..d63262d 100644 --- a/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp +++ b/main/Application/Manager/Network/Server/ImageEncoder/imageEncoder.cpp @@ -34,11 +34,11 @@ typedef struct { bool isInitialized; uint8_t JpegQuality; -} ImageEncoder_State_t; +} Image_Image_Encoder_State_t; -static ImageEncoder_State_t _Encoder_State; +static Image_Image_Encoder_State_t _Image_Encoder_State; -static const char *TAG = "image_encoder"; +static const char *TAG = "Image-Encoder"; /** @brief Get palette lookup table. * @param palette Palette type. @@ -106,7 +106,7 @@ static esp_err_t ImageEncoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t Width, u return ESP_FAIL; } ; - p_Encoded->Data = (uint8_t *)heap_caps_malloc(Width * Height * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + p_Encoded->Data = static_cast(heap_caps_malloc(Width * Height * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); if (p_Encoded->Data == NULL) { jpeg_enc_close(encoder); ESP_LOGE(TAG, "Failed to allocate JPEG output buffer!"); @@ -135,34 +135,34 @@ static esp_err_t ImageEncoder_EncodeJPEG(const uint8_t *p_RGB, uint16_t Width, u esp_err_t ImageEncoder_Init(uint8_t Quality) { - if (_Encoder_State.isInitialized) { + if (_Image_Encoder_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); return ESP_OK; } ESP_LOGD(TAG, "Initializing image encoder, quality=%d", Quality); - _Encoder_State.JpegQuality = Quality; - if (_Encoder_State.JpegQuality < 1) { - _Encoder_State.JpegQuality = 1; + _Image_Encoder_State.JpegQuality = Quality; + if (_Image_Encoder_State.JpegQuality < 1) { + _Image_Encoder_State.JpegQuality = 1; } - if (_Encoder_State.JpegQuality > 100) { - _Encoder_State.JpegQuality = 100; + if (_Image_Encoder_State.JpegQuality > 100) { + _Image_Encoder_State.JpegQuality = 100; } - _Encoder_State.isInitialized = true; + _Image_Encoder_State.isInitialized = true; return ESP_OK; } void ImageEncoder_Deinit(void) { - if (_Encoder_State.isInitialized == false) { + if (_Image_Encoder_State.isInitialized == false) { return; } - _Encoder_State.isInitialized = false; + _Image_Encoder_State.isInitialized = false; ESP_LOGD(TAG, "Image encoder deinitialized"); } @@ -182,7 +182,7 @@ esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, size_t pixel_count = p_Frame->Width * p_Frame->Height; - uint8_t *rgb_buffer = (uint8_t *)heap_caps_malloc(pixel_count * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + uint8_t *rgb_buffer = static_cast(heap_caps_malloc(pixel_count * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); if (rgb_buffer == NULL) { ESP_LOGE(TAG, "Failed to allocate RGB buffer!"); return ESP_ERR_NO_MEM; @@ -197,7 +197,7 @@ esp_err_t ImageEncoder_Encode(const Network_Thermal_Frame_t *p_Frame, switch (Format) { case NETWORK_IMAGE_FORMAT_JPEG: { Error = ImageEncoder_EncodeJPEG(rgb_buffer, p_Frame->Width, p_Frame->Height, - _Encoder_State.JpegQuality, p_Encoded); + _Image_Encoder_State.JpegQuality, p_Encoded); break; } case NETWORK_IMAGE_FORMAT_PNG: { @@ -239,14 +239,14 @@ void ImageEncoder_Free(Network_Encoded_Image_t *p_Encoded) void ImageEncoder_SetQuality(uint8_t Quality) { - _Encoder_State.JpegQuality = Quality; - if (_Encoder_State.JpegQuality < 1) { - _Encoder_State.JpegQuality = 1; + _Image_Encoder_State.JpegQuality = Quality; + if (_Image_Encoder_State.JpegQuality < 1) { + _Image_Encoder_State.JpegQuality = 1; } - if (_Encoder_State.JpegQuality > 100) { - _Encoder_State.JpegQuality = 100; + if (_Image_Encoder_State.JpegQuality > 100) { + _Image_Encoder_State.JpegQuality = 100; } - ESP_LOGD(TAG, "JPEG quality set to %d", _Encoder_State.JpegQuality); + ESP_LOGD(TAG, "JPEG quality set to %d", _Image_Encoder_State.JpegQuality); } diff --git a/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp b/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp index 52f5e54..3adf8ba 100644 --- a/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp +++ b/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp @@ -230,7 +230,7 @@ static int VISA_CMD_SENS_IMG_DATA(char *Response, size_t MaxLen) /* Format: # where n = digits in length */ /* Example with dummy data */ - uint8_t *image_data = (uint8_t *)heap_caps_malloc(1024, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + uint8_t *image_data = static_cast(heap_caps_malloc(1024, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); if (image_data == NULL) { VISA_PushError(SCPI_ERROR_OUT_OF_MEMORY); return SCPI_ERROR_OUT_OF_MEMORY; diff --git a/main/Application/Manager/Network/Server/VISA/visaServer.cpp b/main/Application/Manager/Network/Server/VISA/visaServer.cpp index 447bcde..bfa4380 100644 --- a/main/Application/Manager/Network/Server/VISA/visaServer.cpp +++ b/main/Application/Manager/Network/Server/VISA/visaServer.cpp @@ -21,13 +21,14 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ +#include +#include + #include #include #include #include -#include -#include #include #include #include @@ -35,8 +36,6 @@ #include "visaServer.h" #include "Private/visaCommands.h" -static const char *TAG = "VISA-Server"; - typedef struct { int ListenSocket; /**< Listening socket */ TaskHandle_t ServerTask; /**< Server task handle */ @@ -47,6 +46,8 @@ typedef struct { static VISA_Server_State_t _VISA_Server_State; +static const char *TAG = "VISA-Server"; + /** @brief Process VISA command and generate response * @param Command Received command string * @param Response Response buffer @@ -281,7 +282,7 @@ esp_err_t VISAServer_Deinit(void) return ESP_OK; } -bool VISAServer_isRunning(void) +bool VISAServer_IsRunning(void) { return _VISA_Server_State.isRunning; } diff --git a/main/Application/Manager/Network/Server/VISA/visaServer.h b/main/Application/Manager/Network/Server/VISA/visaServer.h index 2c97b65..62ea98b 100644 --- a/main/Application/Manager/Network/Server/VISA/visaServer.h +++ b/main/Application/Manager/Network/Server/VISA/visaServer.h @@ -63,7 +63,7 @@ esp_err_t VISAServer_Deinit(void); /** @brief Check if VISA server is running * @return true if running, false otherwise */ -bool VISAServer_isRunning(void); +bool VISAServer_IsRunning(void); /** @brief Start VISA server. * @return VISA_OK on success, error code otherwise diff --git a/main/Application/Manager/Network/Server/websocket_handler.cpp b/main/Application/Manager/Network/Server/WebSocket/websocket.cpp similarity index 55% rename from main/Application/Manager/Network/Server/websocket_handler.cpp rename to main/Application/Manager/Network/Server/WebSocket/websocket.cpp index 0bf9bfb..6fad777 100644 --- a/main/Application/Manager/Network/Server/websocket_handler.cpp +++ b/main/Application/Manager/Network/Server/WebSocket/websocket.cpp @@ -27,8 +27,8 @@ #include -#include "websocket_handler.h" -#include "ImageEncoder/imageEncoder.h" +#include "websocket.h" +#include "../ImageEncoder/imageEncoder.h" /** @brief WebSocket client state. */ @@ -46,36 +46,36 @@ typedef struct { typedef struct { bool isInitialized; + bool isRunning; httpd_handle_t ServerHandle; Network_HTTP_Server_Config_t Config; - WS_Client_t Clients[WS_MAX_CLIENTS]; + WS_Client_t Clients[CONFIG_NETWORK_WEBSOCKET_CLIENTS]; uint8_t ClientCount; Network_Thermal_Frame_t *ThermalFrame; SemaphoreHandle_t ClientsMutex; TaskHandle_t BroadcastTask; QueueHandle_t FrameReadyQueue; - bool TaskRunning; -} WebSocket_Handler_State_t; +} WebSocket_State_t; -static WebSocket_Handler_State_t _WSHandler_State; +static WebSocket_State_t WebSocket_State; -static const char *TAG = "websocket_handler"; +static const char *TAG = "WebSocket"; /** @brief Find client by file descriptor. * @param FD File descriptor * @return Pointer to client or NULL if not found */ -static WS_Client_t *WS_FindClient(int FD) +static WS_Client_t *WebSocket_FindClient(int FD) { - xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + xSemaphoreTake(WebSocket_State.ClientsMutex, portMAX_DELAY); - for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { - if (_WSHandler_State.Clients[i].active && _WSHandler_State.Clients[i].fd == FD) { - return &_WSHandler_State.Clients[i]; + for (uint8_t i = 0; i < CONFIG_NETWORK_WEBSOCKET_CLIENTS; i++) { + if (WebSocket_State.Clients[i].active && WebSocket_State.Clients[i].fd == FD) { + return &WebSocket_State.Clients[i]; } } - xSemaphoreGive(_WSHandler_State.ClientsMutex); + xSemaphoreGive(WebSocket_State.ClientsMutex); return NULL; } @@ -84,31 +84,32 @@ static WS_Client_t *WS_FindClient(int FD) * @param FD File descriptor * @return Pointer to new client or NULL if full */ -static WS_Client_t *WS_AddClient(int FD) +static WS_Client_t *WebSocket_AddClient(int FD) { - xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); - - for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { - if (_WSHandler_State.Clients[i].active == false) { - _WSHandler_State.Clients[i].fd = FD; - _WSHandler_State.Clients[i].active = true; - _WSHandler_State.Clients[i].stream_enabled = false; - _WSHandler_State.Clients[i].telemetry_enabled = false; - _WSHandler_State.Clients[i].stream_format = NETWORK_IMAGE_FORMAT_JPEG; - _WSHandler_State.Clients[i].stream_fps = 8; - _WSHandler_State.Clients[i].telemetry_interval_ms = 1000; - _WSHandler_State.Clients[i].last_telemetry_time = 0; - _WSHandler_State.Clients[i].last_frame_time = 0; - _WSHandler_State.ClientCount++; - - xSemaphoreGive(_WSHandler_State.ClientsMutex); - - ESP_LOGI(TAG, "Client added: fd=%d, total=%d", FD, _WSHandler_State.ClientCount); - return &_WSHandler_State.Clients[i]; + xSemaphoreTake(WebSocket_State.ClientsMutex, portMAX_DELAY); + + for (uint8_t i = 0; i < CONFIG_NETWORK_WEBSOCKET_CLIENTS; i++) { + if (WebSocket_State.Clients[i].active == false) { + WebSocket_State.Clients[i].fd = FD; + WebSocket_State.Clients[i].active = true; + WebSocket_State.Clients[i].stream_enabled = false; + WebSocket_State.Clients[i].telemetry_enabled = false; + WebSocket_State.Clients[i].stream_format = NETWORK_IMAGE_FORMAT_JPEG; + WebSocket_State.Clients[i].stream_fps = 8; + WebSocket_State.Clients[i].telemetry_interval_ms = 1000; + WebSocket_State.Clients[i].last_telemetry_time = 0; + WebSocket_State.Clients[i].last_frame_time = 0; + WebSocket_State.ClientCount++; + + xSemaphoreGive(WebSocket_State.ClientsMutex); + + ESP_LOGI(TAG, "Client added: fd=%d, total=%d", FD, WebSocket_State.ClientCount); + + return &WebSocket_State.Clients[i]; } } - xSemaphoreGive(_WSHandler_State.ClientsMutex); + xSemaphoreGive(WebSocket_State.ClientsMutex); ESP_LOGW(TAG, "Max clients reached, rejecting fd=%d", FD); @@ -118,21 +119,22 @@ static WS_Client_t *WS_AddClient(int FD) /** @brief Remove a client. * @param FD File descriptor */ -static void WS_RemoveClient(int FD) +static void WebSocket_RemoveClient(int FD) { - xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + xSemaphoreTake(WebSocket_State.ClientsMutex, portMAX_DELAY); - for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { - if (_WSHandler_State.Clients[i].active && _WSHandler_State.Clients[i].fd == FD) { - _WSHandler_State.Clients[i].active = false; - _WSHandler_State.ClientCount--; + for (uint8_t i = 0; i < CONFIG_NETWORK_WEBSOCKET_CLIENTS; i++) { + if (WebSocket_State.Clients[i].active && WebSocket_State.Clients[i].fd == FD) { + WebSocket_State.Clients[i].active = false; + WebSocket_State.ClientCount--; + + ESP_LOGI(TAG, "Client removed: fd=%d, total=%d", FD, WebSocket_State.ClientCount); - ESP_LOGI(TAG, "Client removed: fd=%d, total=%d", FD, _WSHandler_State.ClientCount); break; } } - xSemaphoreGive(_WSHandler_State.ClientsMutex); + xSemaphoreGive(WebSocket_State.ClientsMutex); } /** @brief Send JSON message to a client. @@ -141,8 +143,18 @@ static void WS_RemoveClient(int FD) * @param p_Data Data JSON object (will not be freed, can be NULL) * @return ESP_OK on success */ -static esp_err_t WS_SendJSON(int FD, const char *p_Cmd, cJSON *p_Data) +static esp_err_t WebSocket_SendJSON(int FD, const char *p_Cmd, cJSON *p_Data) { + esp_err_t Error; + char *JSON; + httpd_ws_frame_t Frame = { + .final = true, + .fragmented = false, + .type = HTTPD_WS_TYPE_TEXT, + .payload = NULL, + .len = 0, + }; + cJSON *msg = cJSON_CreateObject(); cJSON_AddStringToObject(msg, "cmd", p_Cmd); @@ -150,26 +162,21 @@ static esp_err_t WS_SendJSON(int FD, const char *p_Cmd, cJSON *p_Data) cJSON_AddItemReferenceToObject(msg, "data", p_Data); } - char *json_str = cJSON_PrintUnformatted(msg); + JSON = cJSON_PrintUnformatted(msg); cJSON_Delete(msg); - if (json_str == NULL) { + if (JSON == NULL) { return ESP_ERR_NO_MEM; } - httpd_ws_frame_t Frame = { - .final = true, - .fragmented = false, - .type = HTTPD_WS_TYPE_TEXT, - .payload = (uint8_t *)json_str, - .len = strlen(json_str), - }; + Frame.payload = (uint8_t *)JSON; + Frame.len = strlen(JSON); - esp_err_t err = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &Frame); + Error = httpd_ws_send_frame_async(WebSocket_State.ServerHandle, FD, &Frame); - cJSON_free(json_str); + cJSON_free(JSON); - return err; + return Error; } /** @brief Send binary frame to a client. @@ -178,8 +185,9 @@ static esp_err_t WS_SendJSON(int FD, const char *p_Cmd, cJSON *p_Data) * @param Length Data length * @return ESP_OK on success */ -static esp_err_t WS_SendBinary(int FD, const uint8_t *p_Data, size_t Length) +static esp_err_t WebSocket_SendBinary(int FD, const uint8_t *p_Data, size_t Length) { + esp_err_t Error; httpd_ws_frame_t Frame = { .final = true, .fragmented = false, @@ -189,35 +197,35 @@ static esp_err_t WS_SendBinary(int FD, const uint8_t *p_Data, size_t Length) }; /* Try to send with retry logic to handle queue congestion */ - esp_err_t err = ESP_FAIL; + Error = ESP_FAIL; for (uint8_t retry = 0; retry < 3; retry++) { - err = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &Frame); + Error = httpd_ws_send_frame_async(WebSocket_State.ServerHandle, FD, &Frame); - if (err == ESP_OK) { + if (Error == ESP_OK) { /* Send queued successfully - add small delay to prevent queue overflow */ vTaskDelay(5 / portTICK_PERIOD_MS); + break; } /* Queue might be full, wait and retry */ - ESP_LOGW(TAG, "Failed to queue frame to fd=%d (retry %d): %s", - FD, retry + 1, esp_err_to_name(err)); + ESP_LOGW(TAG, "Failed to queue frame to fd=%d (retry %d): %d!", FD, retry + 1, Error); vTaskDelay(50 / portTICK_PERIOD_MS); } - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to send binary frame to fd=%d after retries: %s (len=%zu)", - FD, esp_err_to_name(err), Length); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to send binary frame to fd=%d after retries: %d (len=%zu)!", + FD, Error, Length); } - return err; + return Error; } /** @brief Handle start command. * @param p_Client Client pointer * @param p_Data Command data */ -static void WS_HandleStart(WS_Client_t *p_Client, cJSON *p_Data) +static void WebSocket_HandleStart(WS_Client_t *p_Client, cJSON *p_Data) { cJSON *fps = cJSON_GetObjectItem(p_Data, "fps"); @@ -240,34 +248,34 @@ static void WS_HandleStart(WS_Client_t *p_Client, cJSON *p_Data) ESP_LOGI(TAG, "Stream started for fd=%d, fps=%d", p_Client->fd, p_Client->stream_fps); /* Send ACK */ - cJSON *response = cJSON_CreateObject(); - cJSON_AddStringToObject(response, "status", "ok"); - cJSON_AddNumberToObject(response, "fps", p_Client->stream_fps); - WS_SendJSON(p_Client->fd, "started", response); - cJSON_Delete(response); + cJSON *JSON = cJSON_CreateObject(); + cJSON_AddStringToObject(JSON, "status", "ok"); + cJSON_AddNumberToObject(JSON, "fps", p_Client->stream_fps); + WebSocket_SendJSON(p_Client->fd, "started", JSON); + cJSON_Delete(JSON); } /** @brief Handle stop command. * @param p_Client Client pointer */ -static void WS_HandleStop(WS_Client_t *p_Client) +static void WebSocket_HandleStop(WS_Client_t *p_Client) { p_Client->stream_enabled = false; p_Client->last_frame_time = 0; ESP_LOGI(TAG, "Stream stopped for fd=%d", p_Client->fd); - cJSON *response = cJSON_CreateObject(); - cJSON_AddStringToObject(response, "status", "ok"); - WS_SendJSON(p_Client->fd, "stopped", response); - cJSON_Delete(response); + cJSON *JSON = cJSON_CreateObject(); + cJSON_AddStringToObject(JSON, "status", "ok"); + WebSocket_SendJSON(p_Client->fd, "stopped", JSON); + cJSON_Delete(JSON); } /** @brief Handle subscribe command. * @param p_Client Client pointer * @param p_Data Command data */ -static void WS_HandleTelemetrySubscribe(WS_Client_t *p_Client, cJSON *p_Data) +static void WebSocket_HandleTelemetrySubscribe(WS_Client_t *p_Client, cJSON *p_Data) { cJSON *interval = cJSON_GetObjectItem(p_Data, "interval"); @@ -283,25 +291,25 @@ static void WS_HandleTelemetrySubscribe(WS_Client_t *p_Client, cJSON *p_Data) ESP_LOGI(TAG, "Telemetry subscribed for fd=%d, interval=%lu ms", p_Client->fd, p_Client->telemetry_interval_ms); - cJSON *response = cJSON_CreateObject(); - cJSON_AddStringToObject(response, "status", "ok"); - WS_SendJSON(p_Client->fd, "subscribed", response); - cJSON_Delete(response); + cJSON *JSON = cJSON_CreateObject(); + cJSON_AddStringToObject(JSON, "status", "ok"); + WebSocket_SendJSON(p_Client->fd, "subscribed", JSON); + cJSON_Delete(JSON); } /** @brief Handle unsubscribe command. * @param p_Client Client pointer */ -static void WS_HandleTelemetryUnsubscribe(WS_Client_t *p_Client) +static void WebSocket_HandleTelemetryUnsubscribe(WS_Client_t *p_Client) { p_Client->telemetry_enabled = false; ESP_LOGI(TAG, "Telemetry unsubscribed for fd=%d", p_Client->fd); - cJSON *response = cJSON_CreateObject(); - cJSON_AddStringToObject(response, "status", "ok"); - WS_SendJSON(p_Client->fd, "unsubscribed", response); - cJSON_Delete(response); + cJSON *JSON = cJSON_CreateObject(); + cJSON_AddStringToObject(JSON, "status", "ok"); + WebSocket_SendJSON(p_Client->fd, "unsubscribed", JSON); + cJSON_Delete(JSON); } /** @brief Process incoming WebSocket message. @@ -309,7 +317,7 @@ static void WS_HandleTelemetryUnsubscribe(WS_Client_t *p_Client) * @param p_Data Message data * @param length Message length */ -static void WS_ProcessMessage(WS_Client_t *p_Client, const char *p_Data, size_t length) +static void WebSocket_ProcessMessage(WS_Client_t *p_Client, const char *p_Data, size_t length) { cJSON *json = cJSON_ParseWithLength(p_Data, length); if (json == NULL) { @@ -329,13 +337,13 @@ static void WS_ProcessMessage(WS_Client_t *p_Client, const char *p_Data, size_t /* Handle commands */ const char *cmd_str = cmd->valuestring; if (strcmp(cmd_str, "start") == 0) { - WS_HandleStart(p_Client, data); + WebSocket_HandleStart(p_Client, data); } else if (strcmp(cmd_str, "stop") == 0) { - WS_HandleStop(p_Client); + WebSocket_HandleStop(p_Client); } else if (strcmp(cmd_str, "subscribe") == 0) { - WS_HandleTelemetrySubscribe(p_Client, data); + WebSocket_HandleTelemetrySubscribe(p_Client, data); } else if (strcmp(cmd_str, "unsubscribe") == 0) { - WS_HandleTelemetryUnsubscribe(p_Client); + WebSocket_HandleTelemetryUnsubscribe(p_Client); } else { ESP_LOGW(TAG, "Unknown command from fd=%d: %s", p_Client->fd, cmd_str); } @@ -343,9 +351,11 @@ static void WS_ProcessMessage(WS_Client_t *p_Client, const char *p_Data, size_t cJSON_Delete(json); } -/** @brief WebSocket handler callback. +/** @brief WebSocket handler callback. + * @param p_Request HTTP request pointer + * @return ESP_OK on success, error code on failure */ -static esp_err_t WS_Handler(httpd_req_t *p_Request) +static esp_err_t WebSocket_Handler(httpd_req_t *p_Request) { httpd_ws_frame_t Frame; esp_err_t Error; @@ -354,13 +364,16 @@ static esp_err_t WS_Handler(httpd_req_t *p_Request) /* Handle new connection */ if (p_Request->method == HTTP_GET) { - WS_Client_t *client = WS_AddClient(httpd_req_to_sockfd(p_Request)); + WS_Client_t *client = WebSocket_AddClient(httpd_req_to_sockfd(p_Request)); + if (client == NULL) { httpd_resp_send_err(p_Request, HTTPD_500_INTERNAL_SERVER_ERROR, "Max clients reached"); + return ESP_FAIL; } ESP_LOGI(TAG, "WebSocket handshake with fd=%d", client->fd); + return ESP_OK; } @@ -371,20 +384,24 @@ static esp_err_t WS_Handler(httpd_req_t *p_Request) Error = httpd_ws_recv_frame(p_Request, &Frame, 0); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to get frame info: %d!", Error); + return Error; } if (Frame.len > 0) { - Frame.payload = (uint8_t *)heap_caps_malloc(Frame.len + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + Frame.payload = static_cast(heap_caps_malloc(Frame.len + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); if (Frame.payload == NULL) { ESP_LOGE(TAG, "Failed to allocate frame buffer!"); + return ESP_ERR_NO_MEM; } Error = httpd_ws_recv_frame(p_Request, &Frame, Frame.len); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to receive frame: %d!", Error); + free(Frame.payload); + return Error; } @@ -392,19 +409,19 @@ static esp_err_t WS_Handler(httpd_req_t *p_Request) } FD = httpd_req_to_sockfd(p_Request); - Client = WS_FindClient(FD); + Client = WebSocket_FindClient(FD); switch (Frame.type) { case HTTPD_WS_TYPE_TEXT: { if (Client != NULL && Frame.payload != NULL) { - WS_ProcessMessage(Client, (const char *)Frame.payload, Frame.len); + WebSocket_ProcessMessage(Client, (const char *)Frame.payload, Frame.len); } break; } case HTTPD_WS_TYPE_CLOSE: { ESP_LOGI(TAG, "WebSocket close from fd=%d", FD); - WS_RemoveClient(FD); + WebSocket_RemoveClient(FD); break; } @@ -420,16 +437,17 @@ static esp_err_t WS_Handler(httpd_req_t *p_Request) .len = Frame.len, }; - Error = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &pong_frame); + Error = httpd_ws_send_frame_async(WebSocket_State.ServerHandle, FD, &pong_frame); if (Error != ESP_OK) { ESP_LOGW(TAG, "Failed to send Pong to fd=%d: %d, retrying...", FD, Error); /* Pong fails sometimes. So we simply try again */ vTaskDelay(10 / portTICK_PERIOD_MS); - Error = httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, FD, &pong_frame); + Error = httpd_ws_send_frame_async(WebSocket_State.ServerHandle, FD, &pong_frame); if (Error != ESP_OK) { ESP_LOGW(TAG, "Failed to send Pong to fd=%d again: %d, removing client!", FD, Error); - WS_RemoveClient(FD); + + WebSocket_RemoveClient(FD); } } @@ -457,92 +475,97 @@ static esp_err_t WS_Handler(httpd_req_t *p_Request) static const httpd_uri_t _URI_WebSocket = { .uri = "/ws", .method = HTTP_GET, - .handler = WS_Handler, + .handler = WebSocket_Handler, .user_ctx = NULL, .is_websocket = true, .handle_ws_control_frames = true, .supported_subprotocol = NULL, }; -esp_err_t WebSocket_Handler_Init(const Network_HTTP_Server_Config_t *p_Config) +esp_err_t WebSocket_Init(const Network_HTTP_Server_Config_t *p_Config) { if (p_Config == NULL) { return ESP_ERR_INVALID_ARG; } - if (_WSHandler_State.isInitialized) { + if (WebSocket_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; } ESP_LOGI(TAG, "Initializing WebSocket handler"); - memcpy(&_WSHandler_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); - memset(_WSHandler_State.Clients, 0, sizeof(_WSHandler_State.Clients)); - _WSHandler_State.ClientCount = 0; - _WSHandler_State.ThermalFrame = NULL; - _WSHandler_State.ServerHandle = NULL; - _WSHandler_State.BroadcastTask = NULL; - _WSHandler_State.FrameReadyQueue = NULL; - _WSHandler_State.TaskRunning = false; - - _WSHandler_State.ClientsMutex = xSemaphoreCreateMutex(); - if (_WSHandler_State.ClientsMutex == NULL) { - ESP_LOGE(TAG, "Failed to create mutex"); + memcpy(&WebSocket_State.Config, p_Config, sizeof(Network_HTTP_Server_Config_t)); + memset(WebSocket_State.Clients, 0, sizeof(WebSocket_State.Clients)); + WebSocket_State.ClientCount = 0; + WebSocket_State.ThermalFrame = NULL; + WebSocket_State.ServerHandle = NULL; + WebSocket_State.BroadcastTask = NULL; + WebSocket_State.FrameReadyQueue = NULL; + WebSocket_State.isRunning = false; + + WebSocket_State.ClientsMutex = xSemaphoreCreateMutex(); + if (WebSocket_State.ClientsMutex == NULL) { + ESP_LOGE(TAG, "Failed to create mutex!"); + return ESP_ERR_NO_MEM; } /* Create queue for frame ready notifications (queue size = 1, only latest matters) */ - _WSHandler_State.FrameReadyQueue = xQueueCreate(1, sizeof(uint8_t)); - if (_WSHandler_State.FrameReadyQueue == NULL) { + WebSocket_State.FrameReadyQueue = xQueueCreate(1, sizeof(uint8_t)); + if (WebSocket_State.FrameReadyQueue == NULL) { ESP_LOGE(TAG, "Failed to create frame queue!"); - vSemaphoreDelete(_WSHandler_State.ClientsMutex); + + vSemaphoreDelete(WebSocket_State.ClientsMutex); + return ESP_ERR_NO_MEM; } - _WSHandler_State.isInitialized = true; + WebSocket_State.isInitialized = true; return ESP_OK; } -void WebSocket_Handler_Deinit(void) +void WebSocket_Deinit(void) { - if (_WSHandler_State.isInitialized == false) { + if (WebSocket_State.isInitialized == false) { return; } - WebSocket_Handler_StopTask(); + WebSocket_StopTask(); - if (_WSHandler_State.FrameReadyQueue != NULL) { - vQueueDelete(_WSHandler_State.FrameReadyQueue); - _WSHandler_State.FrameReadyQueue = NULL; + if (WebSocket_State.FrameReadyQueue != NULL) { + vQueueDelete(WebSocket_State.FrameReadyQueue); + WebSocket_State.FrameReadyQueue = NULL; } - if (_WSHandler_State.ClientsMutex != NULL) { - vSemaphoreDelete(_WSHandler_State.ClientsMutex); - _WSHandler_State.ClientsMutex = NULL; + if (WebSocket_State.ClientsMutex != NULL) { + vSemaphoreDelete(WebSocket_State.ClientsMutex); + WebSocket_State.ClientsMutex = NULL; } - _WSHandler_State.isInitialized = false; + WebSocket_State.isInitialized = false; ESP_LOGI(TAG, "WebSocket handler deinitialized"); } -esp_err_t WebSocket_Handler_Register(httpd_handle_t p_ServerHandle) +esp_err_t WebSocket_Register(httpd_handle_t p_ServerHandle) { esp_err_t Error; - if (_WSHandler_State.isInitialized == false) { + if (WebSocket_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } else if (p_ServerHandle == NULL) { return ESP_ERR_INVALID_ARG; } - _WSHandler_State.ServerHandle = p_ServerHandle; + WebSocket_State.ServerHandle = p_ServerHandle; Error = httpd_register_uri_handler(p_ServerHandle, &_URI_WebSocket); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to register WebSocket URI: %d!", Error); + return Error; } @@ -551,51 +574,53 @@ esp_err_t WebSocket_Handler_Register(httpd_handle_t p_ServerHandle) return ESP_OK; } -uint8_t WebSocket_Handler_GetClientCount(void) +uint8_t WebSocket_GetClientCount(void) { - return _WSHandler_State.ClientCount; + return WebSocket_State.ClientCount; } -bool WebSocket_Handler_HasClients(void) +bool WebSocket_HasClients(void) { - return _WSHandler_State.ClientCount > 0; + return WebSocket_State.ClientCount > 0; } -void WebSocket_Handler_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) +void WebSocket_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) { - xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); - _WSHandler_State.ThermalFrame = p_Frame; - xSemaphoreGive(_WSHandler_State.ClientsMutex); + xSemaphoreTake(WebSocket_State.ClientsMutex, portMAX_DELAY); + WebSocket_State.ThermalFrame = p_Frame; + xSemaphoreGive(WebSocket_State.ClientsMutex); } -/** @brief Broadcast task function - runs in separate task to avoid blocking GUI. - * @param p_Param Task parameter (unused) +/** @brief Broadcast task function. Runs in separate task to avoid blocking GUI. + * @param p_Param Task parameter */ -static void WS_BroadcastTask(void *p_Param) +static void WebSocket_BroadcastTask(void *p_Param) { uint8_t Signal; + esp_err_t Error; Network_Encoded_Image_t Encoded; ESP_LOGI(TAG, "WebSocket broadcast task started"); - while (_WSHandler_State.TaskRunning) { + while (WebSocket_State.isRunning) { /* Wait for frame ready notification (blocking, 100ms timeout) */ - if (xQueueReceive(_WSHandler_State.FrameReadyQueue, &Signal, 100 / portTICK_PERIOD_MS) == pdTRUE) { + if (xQueueReceive(WebSocket_State.FrameReadyQueue, &Signal, 100 / portTICK_PERIOD_MS) == pdTRUE) { uint32_t Now = esp_timer_get_time() / 1000; - if ((_WSHandler_State.isInitialized == false) || (_WSHandler_State.ThermalFrame == NULL) || - (_WSHandler_State.ClientCount == 0)) { + if ((WebSocket_State.isInitialized == false) || (WebSocket_State.ThermalFrame == NULL) || + (WebSocket_State.ClientCount == 0)) { continue; } /* Encode frame ONCE for all clients (assume JPEG format for simplicity) */ - if (xSemaphoreTake(_WSHandler_State.ThermalFrame->Mutex, 50 / portTICK_PERIOD_MS) == pdTRUE) { - esp_err_t err = ImageEncoder_Encode(_WSHandler_State.ThermalFrame, - NETWORK_IMAGE_FORMAT_JPEG, PALETTE_IRON, &Encoded); - xSemaphoreGive(_WSHandler_State.ThermalFrame->Mutex); + if (xSemaphoreTake(WebSocket_State.ThermalFrame->Mutex, 50 / portTICK_PERIOD_MS) == pdTRUE) { + Error = ImageEncoder_Encode(WebSocket_State.ThermalFrame, + NETWORK_IMAGE_FORMAT_JPEG, PALETTE_IRON, &Encoded); + xSemaphoreGive(WebSocket_State.ThermalFrame->Mutex); + + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to encode frame: %d!", Error); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Failed to encode frame: %d!", err); continue; } } else { @@ -604,9 +629,9 @@ static void WS_BroadcastTask(void *p_Param) } /* Send to all active streaming clients */ - xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); - for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { - WS_Client_t *client = &_WSHandler_State.Clients[i]; + xSemaphoreTake(WebSocket_State.ClientsMutex, portMAX_DELAY); + for (uint8_t i = 0; i < CONFIG_NETWORK_WEBSOCKET_CLIENTS; i++) { + WS_Client_t *client = &WebSocket_State.Clients[i]; if ((client->active == false) || (client->stream_enabled == false)) { continue; @@ -621,83 +646,81 @@ static void WS_BroadcastTask(void *p_Param) int client_fd = client->fd; uint8_t client_idx = i; - xSemaphoreGive(_WSHandler_State.ClientsMutex); - esp_err_t send_err = WS_SendBinary(client_fd, Encoded.Data, Encoded.Size); - xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + xSemaphoreGive(WebSocket_State.ClientsMutex); + Error = WebSocket_SendBinary(client_fd, Encoded.Data, Encoded.Size); + xSemaphoreTake(WebSocket_State.ClientsMutex, portMAX_DELAY); /* Re-validate client is still active and same FD */ - if (_WSHandler_State.Clients[client_idx].active && - _WSHandler_State.Clients[client_idx].fd == client_fd) { - if (send_err == ESP_OK) { - _WSHandler_State.Clients[client_idx].last_frame_time = Now; + if (WebSocket_State.Clients[client_idx].active && + WebSocket_State.Clients[client_idx].fd == client_fd) { + if (Error == ESP_OK) { + WebSocket_State.Clients[client_idx].last_frame_time = Now; } else { ESP_LOGW(TAG, "Removing client fd=%d due to send failure", client_fd); - _WSHandler_State.Clients[client_idx].active = false; - _WSHandler_State.ClientCount--; + WebSocket_State.Clients[client_idx].active = false; + WebSocket_State.ClientCount--; } } } - xSemaphoreGive(_WSHandler_State.ClientsMutex); + xSemaphoreGive(WebSocket_State.ClientsMutex); /* Free encoded frame after sending to all clients */ ImageEncoder_Free(&Encoded); } - /* Small yield to prevent task starvation */ vTaskDelay(10 / portTICK_PERIOD_MS); } - ESP_LOGI(TAG, "WebSocket broadcast task stopped"); - _WSHandler_State.BroadcastTask = NULL; + WebSocket_State.BroadcastTask = NULL; vTaskDelete(NULL); } -esp_err_t WebSocket_Handler_NotifyFrameReady(void) +esp_err_t WebSocket_NotifyFrameReady(void) { uint8_t Signal; - if ((_WSHandler_State.isInitialized == false) || (_WSHandler_State.FrameReadyQueue == NULL)) { + if ((WebSocket_State.isInitialized == false) || (WebSocket_State.FrameReadyQueue == NULL)) { return ESP_ERR_INVALID_STATE; } - if (_WSHandler_State.ClientCount == 0) { + if (WebSocket_State.ClientCount == 0) { return ESP_OK; } /* Signal frame ready (overwrite if queue full - only latest frame matters) */ Signal = 1; - xQueueOverwrite(_WSHandler_State.FrameReadyQueue, &Signal); + xQueueOverwrite(WebSocket_State.FrameReadyQueue, &Signal); return ESP_OK; } -esp_err_t WebSocket_Handler_BroadcastTelemetry(void) +esp_err_t WebSocket_BroadcastTelemetry(void) { uint32_t Now; - if (_WSHandler_State.isInitialized == false) { + if (WebSocket_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - if (_WSHandler_State.ClientCount == 0) { + if (WebSocket_State.ClientCount == 0) { return ESP_OK; } Now = esp_timer_get_time() / 1000; /* Build telemetry data */ - cJSON *data = cJSON_CreateObject(); + cJSON *JSON = cJSON_CreateObject(); - if (_WSHandler_State.ThermalFrame != NULL) { + if (WebSocket_State.ThermalFrame != NULL) { // TODO - //cJSON_AddNumberToObject(data, "temp", _WSHandler_State.ThermalFrame->temp_avg); + //cJSON_AddNumberToObject(JSON, "temp", WebSocket_State.ThermalFrame->temp_avg); } - xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + xSemaphoreTake(WebSocket_State.ClientsMutex, portMAX_DELAY); - for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { - WS_Client_t *client = &_WSHandler_State.Clients[i]; + for (uint8_t i = 0; i < CONFIG_NETWORK_WEBSOCKET_CLIENTS; i++) { + WS_Client_t *client = &WebSocket_State.Clients[i]; if ((client->active == false) || (client->telemetry_enabled == false)) { continue; @@ -708,20 +731,20 @@ esp_err_t WebSocket_Handler_BroadcastTelemetry(void) continue; } - WS_SendJSON(client->fd, "telemetry", data); + WebSocket_SendJSON(client->fd, "telemetry", JSON); client->last_telemetry_time = Now; } - xSemaphoreGive(_WSHandler_State.ClientsMutex); + xSemaphoreGive(WebSocket_State.ClientsMutex); - cJSON_Delete(data); + cJSON_Delete(JSON); return ESP_OK; } -esp_err_t WebSocket_Handler_PingAll(void) +esp_err_t WebSocket_PingAll(void) { - if ((_WSHandler_State.isInitialized == false) || (_WSHandler_State.ServerHandle == NULL)) { + if ((WebSocket_State.isInitialized == false) || (WebSocket_State.ServerHandle == NULL)) { return ESP_ERR_INVALID_STATE; } @@ -733,70 +756,58 @@ esp_err_t WebSocket_Handler_PingAll(void) .len = 0, }; - xSemaphoreTake(_WSHandler_State.ClientsMutex, portMAX_DELAY); + xSemaphoreTake(WebSocket_State.ClientsMutex, portMAX_DELAY); - for (uint8_t i = 0; i < WS_MAX_CLIENTS; i++) { - if (_WSHandler_State.Clients[i].active) { - httpd_ws_send_frame_async(_WSHandler_State.ServerHandle, _WSHandler_State.Clients[i].fd, &Frame); + for (uint8_t i = 0; i < CONFIG_NETWORK_WEBSOCKET_CLIENTS; i++) { + if (WebSocket_State.Clients[i].active) { + httpd_ws_send_frame_async(WebSocket_State.ServerHandle, WebSocket_State.Clients[i].fd, &Frame); } } - xSemaphoreGive(_WSHandler_State.ClientsMutex); + xSemaphoreGive(WebSocket_State.ClientsMutex); return ESP_OK; } -esp_err_t WebSocket_Handler_StartTask(void) +esp_err_t WebSocket_StartTask(void) { - if (_WSHandler_State.isInitialized == false) { + if (WebSocket_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_WSHandler_State.BroadcastTask != NULL) { + } else if (WebSocket_State.BroadcastTask != NULL) { ESP_LOGW(TAG, "Broadcast task already running"); + return ESP_OK; } - _WSHandler_State.TaskRunning = true; + WebSocket_State.isRunning = true; BaseType_t ret = xTaskCreatePinnedToCore( - WS_BroadcastTask, + WebSocket_BroadcastTask, "WS_Broadcast", 4096, NULL, 5, - &_WSHandler_State.BroadcastTask, + &WebSocket_State.BroadcastTask, 1 ); if (ret != pdPASS) { - ESP_LOGE(TAG, "Failed to create broadcast task"); - _WSHandler_State.TaskRunning = false; + ESP_LOGE(TAG, "Failed to create broadcast task!"); + WebSocket_State.isRunning = false; + return ESP_ERR_NO_MEM; } return ESP_OK; } -void WebSocket_Handler_StopTask(uint32_t Timeout_ms) +void WebSocket_StopTask(uint32_t Timeout_ms) { - uint32_t Start; - - if (_WSHandler_State.BroadcastTask == NULL) { + if (WebSocket_State.BroadcastTask == NULL) { return; } ESP_LOGI(TAG, "Stopping WebSocket broadcast task..."); - _WSHandler_State.TaskRunning = false; - - /* Wait for task to finish (max 2 seconds) */ - Start = esp_timer_get_time() / 1000; - - while (_WSHandler_State.BroadcastTask != NULL && - ((esp_timer_get_time() / 1000) - Start) < Timeout_ms) { - vTaskDelay(10 / portTICK_PERIOD_MS); - } - - _WSHandler_State.BroadcastTask = NULL; - - ESP_LOGI(TAG, "WebSocket broadcast task stopped"); + WebSocket_State.isRunning = false; } diff --git a/main/Application/Manager/Network/Server/websocket_handler.h b/main/Application/Manager/Network/Server/WebSocket/websocket.h similarity index 64% rename from main/Application/Manager/Network/Server/websocket_handler.h rename to main/Application/Manager/Network/Server/WebSocket/websocket.h index faa9d54..ba6c526 100644 --- a/main/Application/Manager/Network/Server/websocket_handler.h +++ b/main/Application/Manager/Network/Server/WebSocket/websocket.h @@ -1,9 +1,9 @@ /* - * websocket_handler.h + * websocket.h * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: WebSocket handler. + * File info: WebSocket implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,72 +21,68 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ -#ifndef WEBSOCKET_HANDLER_H_ -#define WEBSOCKET_HANDLER_H_ +#ifndef WEBSOCKET_H_ +#define WEBSOCKET_H_ #include #include -#include "../networkTypes.h" +#include "../../networkTypes.h" -/** @brief Maximum number of WebSocket clients. - */ -#define WS_MAX_CLIENTS 4 - -/** @brief Initialize the WebSocket handler. +/** @brief Initialize the WebSocket. * @param p_Config Pointer to server configuration * @return ESP_OK on success */ -esp_err_t WebSocket_Handler_Init(const Network_HTTP_Server_Config_t *p_Config); +esp_err_t WebSocket_Init(const Network_HTTP_Server_Config_t *p_Config); -/** @brief Deinitialize the WebSocket handler. +/** @brief Deinitialize the WebSocket. */ -void WebSocket_Handler_Deinit(void); +void WebSocket_Deinit(void); -/** @brief Register WebSocket handler with HTTP server. +/** @brief Register WebSocket with HTTP server. * @param p_ServerHandle HTTP server handle * @return ESP_OK on success */ -esp_err_t WebSocket_Handler_Register(httpd_handle_t p_ServerHandle); +esp_err_t WebSocket_Register(httpd_handle_t p_ServerHandle); /** @brief Get the number of connected WebSocket clients. * @return Number of connected clients */ -uint8_t WebSocket_Handler_GetClientCount(void); +uint8_t WebSocket_GetClientCount(void); /** @brief Check if there are any connected clients. * @return true if at least one client is connected */ -bool WebSocket_Handler_HasClients(void); +bool WebSocket_HasClients(void); /** @brief Set thermal frame data for streaming. * @param p_Frame Pointer to thermal frame data */ -void WebSocket_Handler_SetThermalFrame(Network_Thermal_Frame_t *p_Frame); +void WebSocket_SetThermalFrame(Network_Thermal_Frame_t *p_Frame); /** @brief Signal that a new frame is ready for broadcasting (non-blocking). * @return ESP_OK on success */ -esp_err_t WebSocket_Handler_NotifyFrameReady(void); +esp_err_t WebSocket_NotifyFrameReady(void); /** @brief Broadcast telemetry data to all subscribed clients. * @return ESP_OK on success */ -esp_err_t WebSocket_Handler_BroadcastTelemetry(void); +esp_err_t WebSocket_BroadcastTelemetry(void); /** @brief Start the WebSocket broadcast task. * @return ESP_OK on success */ -esp_err_t WebSocket_Handler_StartTask(void); +esp_err_t WebSocket_StartTask(void); /** @brief Stop the WebSocket broadcast task. * @param Timeout_ms Timeout in milliseconds to wait for task to stop (default: 2000ms) */ -void WebSocket_Handler_StopTask(uint32_t Timeout_ms = 2000); +void WebSocket_StopTask(uint32_t Timeout_ms = 2000); /** @brief Send ping to all connected clients. * @return ESP_OK on success. */ -esp_err_t WebSocket_Handler_PingAll(void); +esp_err_t WebSocket_PingAll(void); -#endif /* WEBSOCKET_HANDLER_H_ */ +#endif /* WEBSOCKET_H_ */ diff --git a/main/Application/Manager/Network/Server/Websocket.md b/main/Application/Manager/Network/Server/Websocket.md deleted file mode 100644 index eaa5d5d..0000000 --- a/main/Application/Manager/Network/Server/Websocket.md +++ /dev/null @@ -1,445 +0,0 @@ -# WebSocket Communication - -## Overview - -Simplified WebSocket protocol for real-time thermal image streaming. **All clients receive JPEG format only** for maximum compatibility and efficiency. - -## Features - -- **Real-time Streaming** - JPEG frames at configurable FPS (1-30) -- **Multi-Client Support** - Up to 4 simultaneous connections -- **Simple Protocol** - Flat JSON structure, no nested types -- **Robust** - Single encoding per frame, proper error handling - -## Protocol - -### Message Format - -**All messages use flat JSON:** - -```json -{ - "cmd": "command_name", - "data": { } -} -``` - -### Commands (Client → Server) - -#### Start Streaming - -```json -{ - "cmd": "start", - "data": { - "fps": 8 - } -} -``` - -**Response:** -```json -{ - "cmd": "started", - "data": { - "status": "ok", - "fps": 8 - } -} -``` - -#### Stop Streaming - -```json -{ - "cmd": "stop" -} -``` - -**Response:** -```json -{ - "cmd": "stopped", - "data": { - "status": "ok" - } -} -``` - -#### Subscribe to Telemetry - -```json -{ - "cmd": "subscribe", - "data": { - "interval": 1000 - } -} -``` - -**Response:** -```json -{ - "cmd": "subscribed", - "data": { - "status": "ok" - } -} -``` - -#### Unsubscribe from Telemetry - -```json -{ - "cmd": "unsubscribe" -} -``` - -### Events (Server → Client) - -#### Telemetry Event - -```json -{ - "cmd": "telemetry", - "data": { - "temp": 25.5 - } -} -``` - -#### Binary Frame Data - -Image frames are sent as **binary WebSocket messages (OPCODE 0x02)** containing JPEG data. - -## Python Client Example - -```python -import asyncio -import websockets -import json -from PIL import Image -from io import BytesIO - -async def stream(): - uri = "ws://192.168.1.100/ws" - - async with websockets.connect(uri, - ping_interval=20, - ping_timeout=60, - max_size=None) as ws: - # Start streaming at 8 FPS - await ws.send(json.dumps({ - "cmd": "start", - "data": {"fps": 8} - })) - - # Receive frames - while True: - message = await ws.recv() - - if isinstance(message, bytes): - # JPEG frame - img = Image.open(BytesIO(message)) - img.show() # or process as needed - else: - # JSON response/event - data = json.loads(message) - print(f"Event: {data}") - -asyncio.run(stream()) -``` - -## Architecture - -### System Components - -```sh -┌─────────────┐ ┌──────────────────┐ ┌──────────────┐ -│ GUI Task │ │ Broadcast Task │ │ WS Clients │ -│ (CPU 0) │ │ (CPU 1) │ │ │ -└─────┬───────┘ └────────┬─────────┘ └──────┬───────┘ - │ │ │ - │ 1. Frame Update │ │ - │ (fast, <10ms) │ │ - │ │ │ - │ 2. NotifyFrameReady() │ │ - │ (non-blocking) │ │ - ├──────────────────────────────>│ │ - │ │ │ - │ 3. Continue GUI │ 4. JPEG Encode │ - │ (no blocking!) │ (200-400ms) │ - │ │ │ - │ │ 5. Send Frame │ - │ ├───────────────────────────────>│ - │ │ (TCP Send) │ - │ │ │ - │ │ 6. Wait for │ - │ │ next frame │ - │ │ │ -``` - -### Task Configuration - -**WebSocket Broadcast Task** (`websocket_handler.cpp`) - -- **Task Name:** `WS_Broadcast` -- **Stack Size:** 4096 Bytes -- **Priority:** 5 (lower than GUI Task priority 10) -- **CPU Affinity:** Core 1 (Network CPU) -- **Queue Length:** 1 (only latest frame notification) - -**Key Design Decisions:** - -1. **Separate Task** - Prevents GUI blocking during encoding/transmission -2. **CPU Pinning** - Network operations on Core 1, GUI rendering on Core 0 -3. **Queue-based** - Frame notifications are queued, not frames themselves -4. **Mutex Optimization** - Released during I/O operations to prevent deadlocks - -## Protocol - -### WebSocket Endpoint - -```sh -ws:///ws -``` - -### Message Format - -All messages use JSON format with the following structure: - -```json -{ - "type": "command|response|event", - "name": "message_name", - "payload": { } -} -``` - -### Commands - -#### Stream Control - -**Start Streaming:** - -```json -{ - "type": "command", - "name": "stream.start", - "payload": { - "format": "jpeg|png|raw", - "fps": 8 - } -} -``` - -- **format**: Image encoding format - - `jpeg` - JPEG compressed (default, recommended) - - `png` - PNG compressed (larger, lossless) - - `raw` - Raw RGB888 data (fastest, largest) -- **fps**: Frame rate (1-30, default: 8) - -**Stop Streaming:** - -```json -{ - "type": "command", - "name": "stream.stop" -} -``` - -#### Telemetry Control - -**Subscribe to Telemetry:** - -```json -{ - "type": "command", - "name": "telemetry.subscribe", - "payload": { - "interval_ms": 1000 - } -} -``` - -- **interval_ms**: Update interval in milliseconds (minimum: 100ms) - -**Unsubscribe from Telemetry:** - -```json -{ - "type": "command", - "name": "telemetry.unsubscribe" -} -``` - -#### LED Control - -**Set LED State:** - -```json -{ - "type": "command", - "name": "led.set", - "payload": { - "state": "on|off|blink", - "blink_ms": 500 - } -} -``` - -### Responses - -All commands receive an acknowledgment response: - -```json -{ - "type": "response", - "name": "stream.start", - "payload": { - "status": "streaming|stopped|subscribed|unsubscribed" - } -} -``` - -### Events - -#### Telemetry Event - -Sent periodically when subscribed: - -```json -{ - "type": "event", - "name": "telemetry", - "payload": { - "sensor_temp_c": 25.5, - "core_temp_c": 45.2 - } -} -``` - -#### Binary Frame Data - -Image frames are sent as binary WebSocket messages (OPCODE 0x02): - -- **JPEG Format:** Binary JPEG data -- **PNG Format:** Binary PNG data -- **RAW Format:** RGB888 pixel data (width × height × 3 bytes) - -## API Reference - -### Initialization - -```cpp -/* Initialize WebSocket handler */ -esp_err_t WebSocket_Handler_Init(const Network_Server_Config_t *p_Config); - -/* Register handler with HTTP server */ -esp_err_t WebSocket_Handler_Register(httpd_handle_t p_ServerHandle); - -/* Start broadcast task */ -esp_err_t WebSocket_Handler_StartTask(void); -``` - -### Frame Broadcasting - -```cpp -/* Set thermal frame data source */ -void WebSocket_Handler_SetThermalFrame(Network_Thermal_Frame_t *p_Frame); - -/* Notify that new frame is ready (non-blocking) */ -esp_err_t WebSocket_Handler_NotifyFrameReady(void); -``` - -**Usage Example:** - -```cpp -// In GUI task, after frame update: -if (WebSocket_Handler_HasClients()) { - WebSocket_Handler_NotifyFrameReady(); // Non-blocking notification -} -``` - -### Telemetry Broadcasting - -```cpp -/* Broadcast telemetry to subscribed clients */ -esp_err_t WebSocket_Handler_BroadcastTelemetry(void); -``` - -### Client Management - -```cpp -/* Get number of connected clients */ -uint8_t WebSocket_Handler_GetClientCount(void); - -/* Check if any clients are connected */ -bool WebSocket_Handler_HasClients(void); - -/* Send ping to all clients */ -esp_err_t WebSocket_Handler_PingAll(void); -``` - -### Cleanup - -```cpp -/* Stop broadcast task */ -void WebSocket_Handler_StopTask(void); - -/* Deinitialize handler */ -void WebSocket_Handler_Deinit(void); -``` - -## JavaScript Client Example - -```javascript -const ws = new WebSocket('ws://192.168.1.100/ws'); - -ws.binaryType = 'arraybuffer'; - -ws.onopen = () => { - // Start streaming at 8 FPS - ws.send(JSON.stringify({ - cmd: 'start', - data: { fps: 8 } - })); -}; - -ws.onmessage = (event) => { - if (event.data instanceof ArrayBuffer) { - // JPEG frame - const blob = new Blob([event.data], { type: 'image/jpeg' }); - const url = URL.createObjectURL(blob); - document.getElementById('image').src = url; - } else { - // JSON event - const data = JSON.parse(event.data); - console.log('Event:', data); - } -}; - -ws.onerror = (error) => { - console.error('WebSocket error:', error); -}; - -ws.onclose = () => { - console.log('WebSocket closed'); -}; -``` - -## Architecture - -### Broadcast Task - -- **Single Encoding**: Each frame is encoded once and sent to all clients -- **CPU Pinning**: Runs on Core 1 (network CPU) to avoid GUI blocking -- **Retry Logic**: 3 retries with backoff on send failures -- **Auto-Cleanup**: Failed clients are automatically removed - -### Performance - -- **Encoding**: ~200-400ms per JPEG frame -- **FPS Limit**: Client-specific (1-30 FPS) -- **Memory**: Single encoded frame shared across all clients -- **Latency**: <100ms from frame capture to client receipt diff --git a/main/Application/Manager/Network/Server/server.h b/main/Application/Manager/Network/Server/server.h index 32e36a0..c973361 100644 --- a/main/Application/Manager/Network/Server/server.h +++ b/main/Application/Manager/Network/Server/server.h @@ -24,8 +24,8 @@ #ifndef SERVER_H_ #define SERVER_H_ -#include "http_server.h" -#include "websocket_handler.h" +#include "HTTP/http_server.h" +#include "WebSocket/websocket.h" #include "VISA/visaServer.h" #include "ImageEncoder/imageEncoder.h" @@ -49,7 +49,7 @@ static inline esp_err_t Server_Init(const Network_Server_Config_t *p_Config) return Error; } - Error = WebSocket_Handler_Init(&p_Config->HTTP_Server); + Error = WebSocket_Init(&p_Config->HTTP_Server); if (Error != ESP_OK) { HTTP_Server_Deinit(); ImageEncoder_Deinit(); @@ -58,9 +58,10 @@ static inline esp_err_t Server_Init(const Network_Server_Config_t *p_Config) Error = VISAServer_Init(&p_Config->VISA_Server); if (Error != ESP_OK) { - WebSocket_Handler_Deinit(); + WebSocket_Deinit(); HTTP_Server_Deinit(); ImageEncoder_Deinit(); + return Error; } @@ -72,7 +73,7 @@ static inline esp_err_t Server_Init(const Network_Server_Config_t *p_Config) static inline void Server_Deinit(void) { VISAServer_Deinit(); - WebSocket_Handler_Deinit(); + WebSocket_Deinit(); HTTP_Server_Deinit(); ImageEncoder_Deinit(); } @@ -89,14 +90,13 @@ static inline esp_err_t Server_Start(void) return Error; } - Error = WebSocket_Handler_Register(HTTP_Server_GetHandle()); + Error = WebSocket_Register(HTTP_Server_GetHandle()); if (Error != ESP_OK) { HTTP_Server_Stop(); return Error; } - /* Start WebSocket broadcast task */ - Error = WebSocket_Handler_StartTask(); + Error = WebSocket_StartTask(); if (Error != ESP_OK) { HTTP_Server_Stop(); return Error; @@ -110,7 +110,7 @@ static inline esp_err_t Server_Start(void) */ static inline esp_err_t Server_Stop(void) { - WebSocket_Handler_StopTask(); + WebSocket_StopTask(); return HTTP_Server_Stop(); } @@ -118,9 +118,9 @@ static inline esp_err_t Server_Stop(void) /** @brief Check if the server is running. * @return true if running */ -static inline bool Server_isRunning(void) +static inline bool Server_IsRunning(void) { - return HTTP_Server_isRunning(); + return HTTP_Server_IsRunning(); } /** @brief Set the thermal frame data for both HTTP and WebSocket endpoints. @@ -129,15 +129,15 @@ static inline bool Server_isRunning(void) static inline void Server_SetThermalFrame(Network_Thermal_Frame_t *p_Frame) { HTTP_Server_SetThermalFrame(p_Frame); - WebSocket_Handler_SetThermalFrame(p_Frame); + WebSocket_SetThermalFrame(p_Frame); } /** @brief Notify all clients that a new frame is ready (non-blocking). */ static inline void Server_NotifyClients(void) { - if (WebSocket_Handler_HasClients()) { - WebSocket_Handler_NotifyFrameReady(); + if (WebSocket_HasClients()) { + WebSocket_NotifyFrameReady(); } } diff --git a/main/Application/Manager/Network/networkManager.cpp b/main/Application/Manager/Network/networkManager.cpp index d8cebe9..e57551e 100644 --- a/main/Application/Manager/Network/networkManager.cpp +++ b/main/Application/Manager/Network/networkManager.cpp @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Network management implementation. + * File info: Network Manager implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,6 @@ */ #include -#include #include #include #include @@ -40,7 +39,6 @@ #include "networkManager.h" -/* Define network event base */ ESP_EVENT_DEFINE_BASE(NETWORK_EVENTS); #define NVS_NAMESPACE "wifi_creds" @@ -64,7 +62,7 @@ typedef struct { static Network_Manager_State_t _Network_Manager_State; -static const char *TAG = "Network Manager"; +static const char *TAG = "Network-Manager"; /** @brief WiFi event handler. * @param p_HandlerArgs Handler argument @@ -77,6 +75,7 @@ static void on_WiFi_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID switch (ID) { case WIFI_EVENT_STA_START: { ESP_LOGD(TAG, "WiFi STA started"); + xEventGroupSetBits(_Network_Manager_State.EventGroup, WIFI_STARTED_BIT); esp_wifi_connect(); @@ -84,6 +83,7 @@ static void on_WiFi_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID } case WIFI_EVENT_STA_CONNECTED: { ESP_LOGD(TAG, "Connected to AP"); + _Network_Manager_State.RetryCount = 0; esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_WIFI_CONNECTED, NULL, 0, portMAX_DELAY); @@ -215,6 +215,7 @@ static void on_WiFi_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID } case WIFI_EVENT_AP_START: { ESP_LOGD(TAG, "WiFi AP started"); + _Network_Manager_State.State = NETWORK_STATE_AP_STARTED; esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STARTED, NULL, 0, portMAX_DELAY); @@ -222,6 +223,7 @@ static void on_WiFi_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID } case WIFI_EVENT_AP_STOP: { ESP_LOGD(TAG, "WiFi AP stopped"); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STOPPED, NULL, 0, portMAX_DELAY); break; @@ -229,6 +231,7 @@ static void on_WiFi_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID case WIFI_EVENT_AP_STACONNECTED: { wifi_event_ap_staconnected_t *Event = (wifi_event_ap_staconnected_t *)p_Data; Network_Event_STA_Info_t StaInfo; + ESP_LOGD(TAG, "Station " MACSTR " joined, AID=%d", MAC2STR(Event->mac), Event->aid); memcpy(StaInfo.MAC, Event->mac, 6); esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STA_CONNECTED, &StaInfo, sizeof(StaInfo), portMAX_DELAY); @@ -238,6 +241,7 @@ static void on_WiFi_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID case WIFI_EVENT_AP_STADISCONNECTED: { wifi_event_ap_stadisconnected_t *Event = (wifi_event_ap_stadisconnected_t *)p_Data; Network_Event_STA_Info_t StaInfo; + ESP_LOGD(TAG, "Station " MACSTR " left, AID=%d", MAC2STR(Event->mac), Event->aid); memcpy(StaInfo.MAC, Event->mac, 6); esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_AP_STA_DISCONNECTED, &StaInfo, sizeof(StaInfo), portMAX_DELAY); @@ -279,6 +283,7 @@ static void on_IP_Event(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, } case IP_EVENT_STA_LOST_IP: { ESP_LOGW(TAG, "Lost IP address"); + memset(&_Network_Manager_State.IP_Info, 0, sizeof(esp_netif_ip_info_t)); break; @@ -304,23 +309,24 @@ esp_err_t NetworkManager_Init(Network_WiFi_STA_Config_t *p_Config) ESP_LOGD(TAG, "Initializing WiFi Manager"); - /* Initialize TCP/IP stack */ + memset(&_Network_Manager_State, 0, sizeof(Network_Manager_State_t)); + ESP_ERROR_CHECK(esp_netif_init()); - /* Create event group */ _Network_Manager_State.EventGroup = xEventGroupCreate(); if (_Network_Manager_State.EventGroup == NULL) { ESP_LOGE(TAG, "Failed to create event group!"); + return ESP_ERR_NO_MEM; } - /* Copy configuration */ _Network_Manager_State.STA_Config = p_Config; /* Create network interfaces */ _Network_Manager_State.STA_NetIF = esp_netif_create_default_wifi_sta(); if (_Network_Manager_State.STA_NetIF == NULL) { ESP_LOGE(TAG, "Failed to create STA netif!"); + vEventGroupDelete(_Network_Manager_State.EventGroup); _Network_Manager_State.EventGroup = NULL; @@ -411,7 +417,7 @@ void NetworkManager_Deinit(void) esp_err_t NetworkManager_StartSTA(void) { wifi_config_t WifiConfig; - esp_err_t err; + esp_err_t Error; if (_Network_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; @@ -434,31 +440,34 @@ esp_err_t NetworkManager_StartSTA(void) sizeof(WifiConfig.sta.password) - 1); /* Set STA mode - WiFi might still be in APSTA mode from provisioning */ - err = esp_wifi_set_mode(WIFI_MODE_STA); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to set WiFi mode: %s", esp_err_to_name(err)); - return err; + Error = esp_wifi_set_mode(WIFI_MODE_STA); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set WiFi mode: %d!", Error); + + return Error; } - err = esp_wifi_set_config(WIFI_IF_STA, &WifiConfig); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to set WiFi config: %s", esp_err_to_name(err)); - return err; + Error = esp_wifi_set_config(WIFI_IF_STA, &WifiConfig); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set WiFi config: %d!", Error); + + return Error; } /* Start WiFi if not already running */ - err = esp_wifi_start(); - if (err != ESP_OK && err != ESP_ERR_WIFI_STATE) { - ESP_LOGE(TAG, "Failed to start WiFi: %s", esp_err_to_name(err)); - return err; + Error = esp_wifi_start(); + if ((Error != ESP_OK) && (Error != ESP_ERR_WIFI_STATE)) { + ESP_LOGE(TAG, "Failed to start WiFi: %d!", Error); + + return Error; } ESP_LOGI(TAG, "WiFi started, initiating connection..."); /* Explicitly connect - STA_START event may not fire if WiFi was already running */ - err = esp_wifi_connect(); - if (err != ESP_OK && err != ESP_ERR_WIFI_CONN) { - ESP_LOGW(TAG, "esp_wifi_connect returned: %s (may be normal if already connecting)", esp_err_to_name(err)); + Error = esp_wifi_connect(); + if ((Error != ESP_OK) && (Error != ESP_ERR_WIFI_CONN)) { + ESP_LOGW(TAG, "esp_wifi_connect returned: %d!", Error); } _Network_Manager_State.State = NETWORK_STATE_CONNECTING; diff --git a/main/Application/Manager/Network/networkManager.h b/main/Application/Manager/Network/networkManager.h index 3013f42..b6c8f7c 100644 --- a/main/Application/Manager/Network/networkManager.h +++ b/main/Application/Manager/Network/networkManager.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Network management definitions + * File info: Network Manager definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,78 +34,156 @@ #include "Provisioning/provisioning.h" /** @brief Initialize the Network Manager. - * @param p_Config Pointer to WiFi configuration + * Initializes WiFi subsystem, creates network interfaces (STA and AP), + * and sets up event handlers. Must be called before any network operations. + * @note This function must be called after NVS and event loop init. + * WiFi is not started automatically - call NetworkManager_StartSTA(). + * @warning Not thread-safe during initialization. + * @param p_Config Pointer to WiFi station configuration (SSID, password) * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Config is NULL + * ESP_ERR_NO_MEM if memory allocation fails + * ESP_FAIL if WiFi initialization fails */ esp_err_t NetworkManager_Init(Network_WiFi_STA_Config_t *p_Config); -/** @brief Deinitialize the Network Manager. +/** @brief Deinitialize the Network Manager. + * Stops WiFi, disconnects all connections, stops servers, and cleans up + * network interfaces. All network handles become invalid. + * @note Automatically disconnects from WiFi if connected. + * Stops HTTP server, WebSocket, and VISA server if running. + * @warning Cannot be undone without calling NetworkManager_Init() again. */ void NetworkManager_Deinit(void); -/** @brief Start WiFi in station mode. - * @return ESP_OK on success +/** @brief Start WiFi in station mode. + * Enables WiFi in station (client) mode and attempts to connect to + * the configured access point. + * @note Connection happens asynchronously - check NetworkManager_isConnected(). + * Posts NETWORK_EVENT_WIFI_CONNECTING event. + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not initialized + * ESP_FAIL if WiFi start fails */ esp_err_t NetworkManager_StartSTA(void); -/** @brief Stop Network Manager. - * @return ESP_OK on success +/** @brief Stop Network Manager. + * Stops WiFi radio and disconnects from network. Does not deinitialize + * the manager - use NetworkManager_StartSTA() to restart. + * @note Servers are stopped but not destroyed. + * Posts NETWORK_EVENT_WIFI_DISCONNECTED event. + * @return ESP_OK on success + * ESP_FAIL if stop operation fails */ esp_err_t NetworkManager_Stop(void); -/** @brief Connect to WiFi (station mode). +/** @brief Connect to WiFi access point (station mode). + * Attempts to connect to specified access point. Connection happens + * asynchronously - use NetworkManager_isConnected() to check status. + * @note Maximum retry attempts defined in configuration. + * Posts NETWORK_EVENT_WIFI_CONNECTED on success. + * If NULL parameters, uses credentials from NetworkManager_Init(). * @param p_SSID SSID to connect to (NULL to use configured SSID) * @param p_Password Password (NULL to use configured password) - * @return ESP_OK on success + * @return ESP_OK if connection attempt started + * ESP_ERR_INVALID_STATE if not initialized or already connected + * ESP_ERR_INVALID_ARG if SSID is too long (max 32 chars) + * ESP_FAIL if connection initiation fails */ esp_err_t NetworkManager_ConnectWiFi(const char *p_SSID, const char *p_Password); -/** @brief Disconnect from WiFi. - * @return ESP_OK on success +/** @brief Disconnect from WiFi. + * Disconnects from current WiFi access point. Keeps WiFi radio active. + * @note Posts NETWORK_EVENT_WIFI_DISCONNECTED event. + * To stop WiFi completely, use NetworkManager_Stop(). + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not connected + * ESP_FAIL if disconnect operation fails */ esp_err_t NetworkManager_DisconnectWiFi(void); -/** @brief Check if WiFi is connected. - * @return true if connected +/** @brief Check if WiFi is connected. + * Returns the current WiFi connection status. Returns true only when + * fully connected with valid IP address. + * @note This is thread-safe and can be called from any task. + * @return true if connected to WiFi with IP address + * false if disconnected, connecting, or no IP */ bool NetworkManager_isConnected(void); -/** @brief Get current WiFi state. - * @return Current state +/** @brief Get current WiFi state. + * Returns detailed connection state including disconnected, connecting, + * connected, provisioning, etc. + * @note Thread-safe. + * Use NetworkManager_isConnected() for simple connected check. + * @return Current network state (see Network_State_t) */ Network_State_t NetworkManager_GetState(void); -/** @brief Get IP information. - * @param p_IP Pointer to store IP info - * @return ESP_OK on success +/** @brief Get IP information. + * Retrieves current IP address, netmask, and gateway for the station + * interface. + * @note Only valid when WiFi is connected. + * @param p_IP Pointer to esp_netif_ip_info_t structure to fill + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_IP is NULL + * ESP_ERR_INVALID_STATE if not connected */ esp_err_t NetworkManager_GetIP(esp_netif_ip_info_t *p_IP); -/** @brief Get WiFi signal strength (RSSI). - * @return RSSI in dBm, or 0 if not connected +/** @brief Get WiFi signal strength (RSSI). + * Returns the Received Signal Strength Indicator in dBm. + * Typical values: -30 dBm (excellent) to -90 dBm (poor). + * @note Only valid when connected to WiFi. + * Value updates periodically while connected. + * @return RSSI in dBm (negative value) + * 0 if not connected or error */ int8_t NetworkManager_GetRSSI(void); -/** @brief Get MAC address. - * @param p_MAC Buffer to store MAC address (6 bytes) +/** @brief Get MAC address of WiFi station interface. + * Retrieves the 6-byte hardware MAC address. + * @note MAC address is factory-programmed in ESP32 eFuse. + * @param p_MAC Buffer to store MAC address (must be at least 6 bytes) * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_MAC is NULL + * ESP_FAIL if MAC read fails */ esp_err_t NetworkManager_GetMAC(uint8_t *p_MAC); /** @brief Set WiFi credentials for station mode. - * @param p_Credentials Pointer to credentials + * Updates stored WiFi credentials. Changes take effect on next + * NetworkManager_ConnectWiFi() call. + * @note Does not automatically reconnect - call NetworkManager_ConnectWiFi(). + * SSID max: 32 chars, Password max: 64 chars. + * @param p_Credentials Pointer to credentials structure (SSID, password) * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Credentials is NULL + * ESP_ERR_INVALID_ARG if SSID or password too long */ esp_err_t NetworkManager_SetCredentials(Network_WiFi_Credentials_t *p_Credentials); -/** @brief Get number of connected stations (AP mode). - * @return Number of connected stations +/** @brief Get number of connected stations (AP mode). + * Returns the number of client devices currently connected to the + * soft AP (Access Point) interface. + * @note Only relevant when operating in AP or AP+STA mode. + * Returns 0 in pure STA mode. + * @return Number of connected stations (0-4 typical limit) */ uint8_t NetworkManager_GetConnectedStations(void); -/** @brief Start the network server (HTTP + Websocket + VISA). - * @param p_Config Pointer to server configuration +/** @brief Start the network server (HTTP + WebSocket + VISA). + * Starts HTTP server with WebSocket support and VISA/SCPI server. + * Servers listen on configured ports and handle client connections. + * @note HTTP server default port: 80, VISA default: 5025. + * WebSocket integrated into HTTP server. + * Can be called before or after WiFi connection. + * @param p_Config Pointer to server configuration (ports, max clients) * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Config is NULL + * ESP_ERR_INVALID_STATE if network not initialized + * ESP_ERR_NO_MEM if memory allocation fails + * ESP_FAIL if server start fails */ esp_err_t NetworkManager_StartServer(Network_Server_Config_t *p_Config); diff --git a/main/Application/Manager/Network/networkTypes.h b/main/Application/Manager/Network/networkTypes.h index 20be394..40d8986 100644 --- a/main/Application/Manager/Network/networkTypes.h +++ b/main/Application/Manager/Network/networkTypes.h @@ -1,9 +1,9 @@ /* - * network_types.h + * networkTypes.h * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Common type definitions for the network interface component. + * File info: Common type definitions for the Network Manager component. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,7 +35,8 @@ #include #include -/* Declare network event base */ +/** @brief Network Manager events base. + */ ESP_EVENT_DECLARE_BASE(NETWORK_EVENTS); /** @brief Network connection state. @@ -169,15 +170,14 @@ typedef struct { /** @brief WiFi credentials. */ typedef struct { - char SSID[33]; - char Password[65]; + char SSID[33]; /**< WiFi SSID (null-terminated, max 32 chars). */ + char Password[65]; /**< WiFi password (null-terminated, max 64 chars). */ } Network_WiFi_Credentials_t; /** @brief WiFi provisioning configuration. */ typedef struct { - char Name[32]; - char PoP[32]; + char Name[32]; /**< Product name (null-terminated, max 31 chars). */ uint32_t Timeout; } Network_Provisioning_Config_t; diff --git a/main/Application/Manager/SD/sdManager.cpp b/main/Application/Manager/SD/sdManager.cpp deleted file mode 100644 index 38f125d..0000000 --- a/main/Application/Manager/SD/sdManager.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * sdManager.cpp - * - * Copyright (C) Daniel Kampert, 2026 - * Website: www.kampis-elektroecke.de - * File info: SD card manager implementation. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "sdManager.h" -#include "Application/application.h" -#include "Application/Manager/Devices/SPI/spi.h" - -#if defined(CONFIG_SD_CARD_SPI2_HOST) -#define SD_SPI_HOST SPI2_HOST -#elif defined(CONFIG_SD_CARD_SPI3_HOST) -#define SD_SPI_HOST SPI3_HOST -#else -#error "No SPI host defined for SD card!" -#endif - -#if CONFIG_SD_CARD_PIN_CD > 0 -#define SD_DEBOUNCE_TIME_MS 500 -#endif - -#define SD_MOUNT_TASK_STACK 4096 -#define SD_MOUNT_TASK_PRIORITY 3 - -ESP_EVENT_DEFINE_BASE(SD_EVENTS); - -static const char *TAG = "sd-manager"; - -typedef struct { - sdmmc_card_t *Card; - sdmmc_host_t Host; - sdspi_device_config_t SlotConfig; - bool isInitialized; - esp_timer_handle_t DebounceTimer; - esp_vfs_fat_sdmmc_mount_config_t MountConfig; - TaskHandle_t MountTaskHandle; - volatile bool CardPresent; - gpio_config_t CD_Conf; -} SD_Manager_State_t; - -static SD_Manager_State_t _SD_Manager_State; - -#if CONFIG_SD_CARD_PIN_CD > 0 -/** @brief Debounce timer callback - called after card state is stable. - * @param p_Arg Unused - */ -static void SDManager_DebounceTimerCallback(void *p_Arg) -{ - (void)p_Arg; - - /* Read current card state */ - bool cardPresent = (gpio_get_level(static_cast(CONFIG_SD_CARD_PIN_CD)) == 0); - - ESP_LOGI(TAG, "Card state stable: %s", cardPresent ? "present" : "removed"); - - _SD_Manager_State.CardPresent = cardPresent; - - /* Notify about state change */ - esp_event_post(SD_EVENTS, SD_EVENT_CARD_CHANGED, (const void *)&cardPresent, sizeof(bool), 0); -} - -/** @brief GPIO interrupt handler for card detection. - * Called when the card detect pin changes state. - * @param p_Arg Unused - */ -static void IRAM_ATTR SDManager_CardDetectISR(void *p_Arg) -{ - (void)p_Arg; - - /* Restart debounce timer on every edge - only triggers callback after stable period */ - if (_SD_Manager_State.DebounceTimer != NULL) { - // TODO: Not IRAM save - esp_timer_stop(_SD_Manager_State.DebounceTimer); - esp_timer_start_once(_SD_Manager_State.DebounceTimer, SD_DEBOUNCE_TIME_MS * 1000); - } -} -#endif - -esp_err_t SDManager_Init(void) -{ - if (_SD_Manager_State.isInitialized) { - ESP_LOGW(TAG, "SD Manager already initialized"); - return ESP_OK; - } - - ESP_LOGI(TAG, "Initializing SD Manager..."); - - if (CONFIG_SD_CARD_PIN_CS < 0) { - ESP_LOGE(TAG, "Invalid CS pin!"); - return ESP_ERR_INVALID_ARG; - } - - _SD_Manager_State.MountConfig = { -#ifdef CONFIG_SD_CARD_FORMAT_CARD - .format_if_mount_failed = true, -#else - .format_if_mount_failed = false, -#endif - .max_files = 5, - .allocation_unit_size = 16 * 1024, - .disk_status_check_enable = false, - .use_one_fat = false - }; - - _SD_Manager_State.Host = SDSPI_HOST_DEFAULT(); - _SD_Manager_State.Host.slot = SD_SPI_HOST; - _SD_Manager_State.SlotConfig = SDSPI_DEVICE_CONFIG_DEFAULT(); - _SD_Manager_State.SlotConfig.gpio_cs = static_cast(CONFIG_SD_CARD_PIN_CS); - _SD_Manager_State.SlotConfig.host_id = static_cast(_SD_Manager_State.Host.slot); - - if (esp_vfs_fat_sdspi_mount("/sdcard", &_SD_Manager_State.Host, &_SD_Manager_State.SlotConfig, - &_SD_Manager_State.MountConfig, &_SD_Manager_State.Card) != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount SD card filesystem!"); - return ESP_FAIL; - } - - ESP_LOGI(TAG, "SD card filesystem mounted successfully"); - -#if CONFIG_SD_CARD_PIN_CD > 0 - esp_err_t Error; - - /* Configure card detect pin with interrupt */ - _SD_Manager_State.CD_Conf.intr_type = GPIO_INTR_ANYEDGE; - _SD_Manager_State.CD_Conf.mode = GPIO_MODE_INPUT; - _SD_Manager_State.CD_Conf.pin_bit_mask = (1ULL << CONFIG_SD_CARD_PIN_CD); - _SD_Manager_State.CD_Conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - _SD_Manager_State.CD_Conf.pull_up_en = GPIO_PULLUP_ENABLE; - - Error = gpio_config(&_SD_Manager_State.CD_Conf); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to configure card detect pin: %d!", Error); - return Error; - } - - /* Install GPIO ISR service if not already installed */ - Error = gpio_install_isr_service(0); - if (Error != ESP_OK && Error != ESP_ERR_INVALID_STATE) { - ESP_LOGE(TAG, "Failed to install GPIO ISR service: %d!", Error); - return Error; - } - - /* Add ISR handler for card detect pin */ - Error = gpio_isr_handler_add(static_cast(CONFIG_SD_CARD_PIN_CD), SDManager_CardDetectISR, NULL); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to add ISR handler: %d!", Error); - return Error; - } - - /* Create debounce timer */ - const esp_timer_create_args_t debounce_timer_args = { - .callback = &SDManager_DebounceTimerCallback, - .arg = NULL, - .dispatch_method = ESP_TIMER_TASK, - .name = "sd_debounce", - .skip_unhandled_events = false, - }; - - Error = esp_timer_create(&debounce_timer_args, &_SD_Manager_State.DebounceTimer); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to create debounce timer: %d!", Error); - return Error; - } - - /* Check initial card state and trigger debounced event if present */ - if (gpio_get_level(static_cast(CONFIG_SD_CARD_PIN_CD)) == 0) { - ESP_LOGI(TAG, "SD card present at initialization"); - - _SD_Manager_State.CardPresent = true; - - /* Start timer to trigger initial mount after debounce period */ - esp_timer_start_once(_SD_Manager_State.DebounceTimer, SD_DEBOUNCE_TIME_MS * 1000); - } else { - ESP_LOGI(TAG, "No SD card present at initialization"); - - _SD_Manager_State.CardPresent = false; - } -#endif - - _SD_Manager_State.isInitialized = true; - - ESP_LOGI(TAG, "SD manager initialized"); - - return ESP_OK; -} - -esp_err_t SDManager_Deinit(void) -{ - if (_SD_Manager_State.isInitialized == false) { - return ESP_OK; - } - - ESP_LOGI(TAG, "Deinitializing SD Manager..."); - -#if CONFIG_SD_CARD_PIN_CD > 0 - /* Stop and delete debounce timer */ - if (_SD_Manager_State.DebounceTimer != NULL) { - esp_timer_stop(_SD_Manager_State.DebounceTimer); - esp_timer_delete(_SD_Manager_State.DebounceTimer); - _SD_Manager_State.DebounceTimer = NULL; - } -#endif /* CONFIG_SD_CARD_PIN_CD */ - - /* Wait for mount task to finish if running */ - if (_SD_Manager_State.MountTaskHandle != NULL) { - vTaskDelay(100 / portTICK_PERIOD_MS); - _SD_Manager_State.MountTaskHandle = NULL; - } - - SDManager_Unmount(); - - _SD_Manager_State.isInitialized = false; - - ESP_LOGI(TAG, "SD Manager deinitialized"); - - return ESP_OK; -} - -bool SDManager_isCardPresent(void) -{ - return _SD_Manager_State.CardPresent; -} - -/** @brief Background task for mounting SD card (prevents GUI blocking). - * @param arg Unused - */ -static void SDManager_MountTask(void *arg) -{ - (void)arg; - esp_err_t Error; - - /* Add this task to WDT */ - esp_task_wdt_add(NULL); - - ESP_LOGI(TAG, "Mount task started"); - - /* Reset WDT before mount attempt */ - esp_task_wdt_reset(); - - Error = esp_vfs_fat_sdspi_mount(SD_MOUNT_POINT, &_SD_Manager_State.Host, &_SD_Manager_State.SlotConfig, - &_SD_Manager_State.MountConfig, - &_SD_Manager_State.Card); - - /* Reset WDT after mount attempt */ - esp_task_wdt_reset(); - if (Error != ESP_OK) { - if (Error == ESP_FAIL) { - ESP_LOGE(TAG, "Failed to mount filesystem. Format the card or check hardware connection!"); - } else { - ESP_LOGE(TAG, "Failed to initialize SD card %d!", Error); - } - - _SD_Manager_State.Card = NULL; - - /* Post mount error event */ - esp_event_post(SD_EVENTS, SD_EVENT_MOUNT_ERROR, NULL, 0, portMAX_DELAY); - } else { - /* Card mounted successfully */ - ESP_LOGI(TAG, "SD card mounted successfully"); - ESP_LOGI(TAG, "Card size: %llu MB", ((uint64_t)_SD_Manager_State.Card->csd.capacity) * - _SD_Manager_State.Card->csd.sector_size / - (1024 * 1024)); - - /* Post mount success event */ - esp_event_post(SD_EVENTS, SD_EVENT_MOUNTED, NULL, 0, portMAX_DELAY); - } - - _SD_Manager_State.MountTaskHandle = NULL; - - /* Remove from WDT before deleting */ - esp_task_wdt_delete(NULL); - - vTaskDelete(NULL); -} - -esp_err_t SDManager_Mount(void) -{ - if (_SD_Manager_State.CardPresent == false) { - ESP_LOGW(TAG, "No SD card available!"); - return ESP_ERR_NOT_FOUND; - } - - /* Prevent multiple mount tasks */ - if (_SD_Manager_State.MountTaskHandle != NULL) { - ESP_LOGW(TAG, "Mount task already running"); - return ESP_ERR_INVALID_STATE; - } - - ESP_LOGI(TAG, "Starting async mount task..."); - - BaseType_t ret = xTaskCreatePinnedToCore( - SDManager_MountTask, - "sd_mount", - SD_MOUNT_TASK_STACK, - NULL, - SD_MOUNT_TASK_PRIORITY, - &_SD_Manager_State.MountTaskHandle, - 1 /* Run on CPU 1 to avoid blocking GUI task on CPU 0 */ - ); - - if (ret != pdPASS) { - ESP_LOGE(TAG, "Failed to create mount task!"); - return ESP_ERR_NO_MEM; - } - - return ESP_OK; -} - -esp_err_t SDManager_Unmount(void) -{ - esp_err_t Error; - - if (_SD_Manager_State.Card == NULL) { - return ESP_OK; - } - - ESP_LOGI(TAG, "Unmounting SD card..."); - - Error = esp_vfs_fat_sdcard_unmount(SD_MOUNT_POINT, _SD_Manager_State.Card); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to unmount SD card %d!", Error); - - return Error; - } - - ESP_LOGI(TAG, "SD card unmounted"); - - _SD_Manager_State.Card = NULL; - - return ESP_OK; -} \ No newline at end of file diff --git a/main/Application/Manager/SD/sdManager.h b/main/Application/Manager/SD/sdManager.h deleted file mode 100644 index 4746f1b..0000000 --- a/main/Application/Manager/SD/sdManager.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * sdManager.h - * - * Copyright (C) Daniel Kampert, 2026 - * Website: www.kampis-elektroecke.de - * File info: SD card manager header. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de - */ - -#ifndef SDMANAGER_H_ -#define SDMANAGER_H_ - -#include - -#include -#include - -/** @brief SD card mount point. - */ -#define SD_MOUNT_POINT "/sdcard" - -/** @brief SD card event identifiers. - */ -enum { - SD_EVENT_CARD_CHANGED, /**< SD card has been inserted or removed. - The data type is bool. */ - SD_EVENT_MOUNTED, /**< SD card has been mounted successfully. */ - SD_EVENT_MOUNT_ERROR, /**< SD card mount error occurred. */ -}; - -/** @brief Initialize the SD card manager. - * Sets up card detection GPIO and attempts initial mount if card is present. - * @return ESP_OK on success - */ -esp_err_t SDManager_Init(void); - -/** @brief Deinitialize the SD card manager. - * Unmounts card if present and releases resources. - * @return ESP_OK on success - */ -esp_err_t SDManager_Deinit(void); - -/** @brief Check if SD card is currently present and mounted. - * @return true if card is present and mounted, false otherwise - */ -bool SDManager_isCardPresent(void); - -/** @brief Mount the SD card. - * @return ESP_OK on success - */ -esp_err_t SDManager_Mount(void); - -/** @brief Unmount the SD card. - * @return ESP_OK on success - */ -esp_err_t SDManager_Unmount(void); - -#endif /* SDMANAGER_H_ */ diff --git a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp index f1a31a0..9829e6e 100644 --- a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp @@ -33,7 +33,7 @@ #include "settingsLoader.h" #include "../settingsManager.h" -static const char *TAG = "settings_default_loader"; +static const char *TAG = "Settings-Default-Loader"; void SettingsManager_InitDefaultLeptonROIs(App_Settings_t *p_Settings) { @@ -73,14 +73,15 @@ void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settin p_Settings->Lepton.EmissivityPresets[0].Value = 1.0f; strncpy(p_Settings->Lepton.EmissivityPresets[0].Description, "Unknown", sizeof(p_Settings->Lepton.EmissivityPresets[0].Description)); - + p_Settings->Lepton.CurrentEmissivity = SETTINGS_DEFAULT_LEPTON_EMISSIVITY; } -void SettingsManager_InitDefaults(SettingsManager_State_t *p_State) +void SettingsManager_InitDefaults(Settings_Manager_State_t *p_State) { memset(&p_State->Settings, 0, sizeof(App_Settings_t)); + p_State->Settings.Version = SETTINGS_VERSION; SettingsManager_InitDefaultDisplay(&p_State->Settings); SettingsManager_InitDefaultProvisioning(&p_State->Settings); SettingsManager_InitDefaultWiFi(&p_State->Settings); diff --git a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp index d2b89c5..2990b68 100644 --- a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp @@ -36,13 +36,13 @@ #include "settingsLoader.h" #include "../settingsManager.h" -static const char *TAG = "settings_json_loader"; +static const char *TAG = "Settings-JSON-Loader"; -/** @brief - * @param p_State - * @param p_JSON +/** @brief Load the Lepton settings from the JSON object and apply them to the Settings Manager state. If a setting is missing or invalid, the default value is used. + * @param p_State The Settings Manager state structure to update with the loaded settings + * @param p_JSON The cJSON object representing the root of the settings JSON document */ -static void SettingsManager_LoadLepton(SettingsManager_State_t *p_State, const cJSON *p_JSON) +static void SettingsManager_LoadLepton(Settings_Manager_State_t *p_State, const cJSON *p_JSON) { cJSON *lepton = NULL; cJSON *emissivity_array = NULL; @@ -95,11 +95,11 @@ static void SettingsManager_LoadLepton(SettingsManager_State_t *p_State, const c } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief Load the Display settings from the JSON object and apply them to the Settings Manager state. If a setting is missing or invalid, the default value is used. + * @param p_State The Settings Manager state structure to update with the loaded settings + * @param p_JSON The cJSON object representing the root of the settings JSON document */ -static void SettingsManager_LoadDisplay(SettingsManager_State_t *p_State, const cJSON *p_JSON) +static void SettingsManager_LoadDisplay(Settings_Manager_State_t *p_State, const cJSON *p_JSON) { cJSON *display = NULL; @@ -107,14 +107,14 @@ static void SettingsManager_LoadDisplay(SettingsManager_State_t *p_State, const if (display != NULL) { cJSON *brightness = cJSON_GetObjectItem(display, "brightness"); if (cJSON_IsNumber(brightness)) { - p_State->Settings.Display.Brightness = (uint8_t)(brightness->valueint); + p_State->Settings.Display.Brightness = static_cast(brightness->valueint); } else { p_State->Settings.Display.Brightness = SETTINGS_DISPLAY_DEFAULT_BRIGHTNESS; } cJSON *timeout = cJSON_GetObjectItem(display, "timeout"); if (cJSON_IsNumber(timeout)) { - p_State->Settings.Display.Timeout = (uint16_t)(timeout->valueint); + p_State->Settings.Display.Timeout = static_cast(timeout->valueint); } else { p_State->Settings.Display.Timeout = SETTINGS_DISPLAY_DEFAULT_TIMEOUT; } @@ -123,11 +123,11 @@ static void SettingsManager_LoadDisplay(SettingsManager_State_t *p_State, const } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief Load the WiFi settings from the JSON object and apply them to the Settings Manager state. If a setting is missing or invalid, the default value is used. + * @param p_State The Settings Manager state structure to update with the loaded settings + * @param p_JSON The cJSON object representing the root of the settings JSON document */ -static void SettingsManager_LoadWiFi(SettingsManager_State_t *p_State, const cJSON *p_JSON) +static void SettingsManager_LoadWiFi(Settings_Manager_State_t *p_State, const cJSON *p_JSON) { cJSON *wifi = NULL; @@ -135,14 +135,14 @@ static void SettingsManager_LoadWiFi(SettingsManager_State_t *p_State, const cJS if (wifi != NULL) { cJSON *maxRetries = cJSON_GetObjectItem(wifi, "maxRetries"); if (cJSON_IsNumber(maxRetries)) { - p_State->Settings.WiFi.MaxRetries = (uint8_t)(maxRetries->valueint); + p_State->Settings.WiFi.MaxRetries = static_cast(maxRetries->valueint); } else { p_State->Settings.WiFi.MaxRetries = SETTINGS_WIFI_DEFAULT_MAX_RETRIES; } cJSON *retryInterval = cJSON_GetObjectItem(wifi, "retryInterval"); if (cJSON_IsNumber(retryInterval)) { - p_State->Settings.WiFi.RetryInterval = (uint32_t)(retryInterval->valueint); + p_State->Settings.WiFi.RetryInterval = static_cast(retryInterval->valueint); } else { p_State->Settings.WiFi.RetryInterval = SETTINGS_WIFI_DEFAULT_RETRY_INTERVAL; } @@ -172,11 +172,11 @@ static void SettingsManager_LoadWiFi(SettingsManager_State_t *p_State, const cJS } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief Load the Provisioning settings from the JSON object and apply them to the Settings Manager state. If a setting is missing or invalid, the default value is used. + * @param p_State The Settings Manager state structure to update with the loaded settings + * @param p_JSON The cJSON object representing the root of the settings JSON document */ -static void SettingsManager_LoadProvisioning(SettingsManager_State_t *p_State, const cJSON *p_JSON) +static void SettingsManager_LoadProvisioning(Settings_Manager_State_t *p_State, const cJSON *p_JSON) { cJSON *provisioning = NULL; @@ -192,7 +192,7 @@ static void SettingsManager_LoadProvisioning(SettingsManager_State_t *p_State, c cJSON *timeout = cJSON_GetObjectItem(provisioning, "timeout"); if (cJSON_IsNumber(timeout)) { - p_State->Settings.Provisioning.Timeout = (uint32_t)(timeout->valueint); + p_State->Settings.Provisioning.Timeout = static_cast(timeout->valueint); } else { p_State->Settings.Provisioning.Timeout = SETTINGS_PROVISIONING_DEFAULT_TIMEOUT; } @@ -201,11 +201,11 @@ static void SettingsManager_LoadProvisioning(SettingsManager_State_t *p_State, c } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief Load the System settings from the JSON object and apply them to the Settings Manager state. If a setting is missing or invalid, the default value is used. + * @param p_State The Settings Manager state structure to update with the loaded settings + * @param p_JSON The cJSON object representing the root of the settings JSON document */ -static void SettingsManager_LoadSystem(SettingsManager_State_t *p_State, const cJSON *p_JSON) +static void SettingsManager_LoadSystem(Settings_Manager_State_t *p_State, const cJSON *p_JSON) { cJSON *system = NULL; @@ -230,11 +230,11 @@ static void SettingsManager_LoadSystem(SettingsManager_State_t *p_State, const c } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief Load the HTTP server settings from the JSON object and apply them to the Settings Manager state. If a setting is missing or invalid, the default value is used. + * @param p_State The Settings Manager state structure to update with the loaded settings + * @param p_JSON The cJSON object representing the root of the settings JSON document */ -static void SettingsManager_LoadHTTPServer(SettingsManager_State_t *p_State, const cJSON *p_JSON) +static void SettingsManager_LoadHTTPServer(Settings_Manager_State_t *p_State, const cJSON *p_JSON) { cJSON *http_server = NULL; @@ -242,21 +242,21 @@ static void SettingsManager_LoadHTTPServer(SettingsManager_State_t *p_State, con if (http_server != NULL) { cJSON *port = cJSON_GetObjectItem(http_server, "port"); if (cJSON_IsNumber(port)) { - p_State->Settings.HTTPServer.Port = (uint16_t)(port->valueint); + p_State->Settings.HTTPServer.Port = static_cast(port->valueint); } else { p_State->Settings.HTTPServer.Port = SETTINGS_DEFAULT_HTTP_PORT; } cJSON *wsPingIntervalSec = cJSON_GetObjectItem(http_server, "wsPingIntervalSec"); if (cJSON_IsNumber(wsPingIntervalSec)) { - p_State->Settings.HTTPServer.WSPingIntervalSec = (uint16_t)(wsPingIntervalSec->valueint); + p_State->Settings.HTTPServer.WSPingIntervalSec = static_cast(wsPingIntervalSec->valueint); } else { p_State->Settings.HTTPServer.WSPingIntervalSec = SETTINGS_DEFAULT_WS_PING_INTERVAL; } cJSON *maxClients = cJSON_GetObjectItem(http_server, "maxClients"); if (cJSON_IsNumber(maxClients)) { - p_State->Settings.HTTPServer.MaxClients = (uint8_t)(maxClients->valueint); + p_State->Settings.HTTPServer.MaxClients = static_cast(maxClients->valueint); } else { p_State->Settings.HTTPServer.MaxClients = SETTINGS_DEFAULT_HTTP_MAX_CLIENTS; } @@ -265,11 +265,11 @@ static void SettingsManager_LoadHTTPServer(SettingsManager_State_t *p_State, con } } -/** @brief - * @param p_State - * @param p_JSON +/** @brief Load the VISA server settings from the JSON object and apply them to the Settings Manager state. If a setting is missing or invalid, the default value is used. + * @param p_State The Settings Manager state structure to update with the loaded settings + * @param p_JSON The cJSON object representing the root of the settings JSON document */ -static void SettingsManager_LoadVISAServer(SettingsManager_State_t *p_State, const cJSON *p_JSON) +static void SettingsManager_LoadVISAServer(Settings_Manager_State_t *p_State, const cJSON *p_JSON) { cJSON *visa_server = NULL; @@ -277,7 +277,7 @@ static void SettingsManager_LoadVISAServer(SettingsManager_State_t *p_State, con if (visa_server != NULL) { cJSON *port = cJSON_GetObjectItem(visa_server, "port"); if (cJSON_IsNumber(port)) { - p_State->Settings.VISAServer.Port = (uint16_t)(port->valueint); + p_State->Settings.VISAServer.Port = static_cast(port->valueint); } else { p_State->Settings.VISAServer.Port = SETTINGS_DEFAULT_VISA_PORT; } @@ -286,106 +286,19 @@ static void SettingsManager_LoadVISAServer(SettingsManager_State_t *p_State, con } } -/** @brief Initialize and mount the SD card. - * @return ESP_OK on success - */ -static esp_err_t SettingsManager_Mount_SD_Card(void) -{ - esp_err_t Error; - sdmmc_card_t *card; - const char mount_point[] = "/sdcard"; - - ESP_LOGD(TAG, "Initializing SD card"); - - sdmmc_host_t Host = SDSPI_HOST_DEFAULT(); - Host.slot = SPI2_HOST; - - spi_bus_config_t SPI_Config; - memset(&SPI_Config, 0, sizeof(SPI_Config)); - SPI_Config = { - .mosi_io_num = GPIO_NUM_38, - .miso_io_num = GPIO_NUM_40, - .sclk_io_num = GPIO_NUM_39, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = 4000, - }; - - Error = spi_bus_initialize(static_cast(Host.slot), &SPI_Config, SDSPI_DEFAULT_DMA); - if (Error != ESP_OK) { - if (Error == ESP_ERR_INVALID_STATE) { - ESP_LOGD(TAG, "SPI bus already initialized, continuing..."); - } else { - ESP_LOGD(TAG, "Failed to initialize SPI: %d!", Error); - - return Error; - } - } - - sdspi_device_config_t Slot = SDSPI_DEVICE_CONFIG_DEFAULT(); - Slot.gpio_cs = GPIO_NUM_47; - Slot.host_id = static_cast(Host.slot); - - esp_vfs_fat_sdmmc_mount_config_t Mount_Config = { - .format_if_mount_failed = false, - .max_files = 5, - .allocation_unit_size = 16 * 1024 - }; - - Error = esp_vfs_fat_sdspi_mount(mount_point, &Host, &Slot, &Mount_Config, &card); - if (Error != ESP_OK) { - if (Error == ESP_FAIL) { - ESP_LOGD(TAG, "Failed to mount SD card filesystem!"); - } else { - ESP_LOGD(TAG, "Failed to mount SD card: 0x%x!", Error); - } - - return Error; - } - - /* Log the mount point and list files in the directory */ - DIR *dir = opendir(mount_point); - if (dir == NULL) { - ESP_LOGE(TAG, "Failed to open mount point: %s!", mount_point); - return ESP_FAIL; - } - - struct dirent *entry; - ESP_LOGD(TAG, "Files in mount point %s:", mount_point); - /* Enhanced logging for file names */ - while ((entry = readdir(dir)) != NULL) { - ESP_LOGD(TAG, " Found file: %s", entry->d_name); - if (strcmp(entry->d_name, "settings.json") == 0 || strcmp(entry->d_name, "SETTIN~1.JSO") == 0) { - ESP_LOGD(TAG, " Matched settings file: %s", entry->d_name); - } - } - closedir(dir); - - ESP_LOGD(TAG, "SD card mounted successfully"); - - return ESP_OK; -} - -/** @brief Unmount the SD card. - */ -static void SettingsManager_Unmount_SD_Card(void) -{ - esp_vfs_fat_sdcard_unmount("/sdcard", NULL); - ESP_LOGD(TAG, "SD card unmounted"); -} - /** @brief Load and parse JSON settings from file. * @param p_State Settings state structure * @param filepath Full path to JSON file * @return ESP_OK on success */ -static esp_err_t SettingsManager_Load_JSON(SettingsManager_State_t *p_State, const char *p_FilePath) +static esp_err_t SettingsManager_Load_JSON(Settings_Manager_State_t *p_State, const char *p_FilePath) { FILE *File = NULL; char *Buffer = NULL; long FileSize; size_t BytesRead; cJSON *JSON = NULL; + esp_err_t Error; ESP_LOGD(TAG, "Loading settings from: %s", p_FilePath); @@ -420,7 +333,7 @@ static esp_err_t SettingsManager_Load_JSON(SettingsManager_State_t *p_State, con ESP_LOGD(TAG, "File size: %ld bytes", FileSize); /* Allocate buffer for file content */ - Buffer = (char*)heap_caps_malloc(FileSize + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + Buffer = static_cast(heap_caps_malloc(FileSize + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT)); if (Buffer == NULL) { ESP_LOGE(TAG, "Failed to allocate memory for file buffer!"); @@ -460,16 +373,37 @@ static esp_err_t SettingsManager_Load_JSON(SettingsManager_State_t *p_State, con ESP_LOGD(TAG, "JSON parsed successfully from %s", p_FilePath); + /* Check the version number of the JSON and the version from the firmware. Skip the loading if the version in the JSON is older or invalid. */ + cJSON *version = cJSON_GetObjectItem(JSON, "version"); + if (cJSON_IsNumber(version)) { + p_State->Settings.Version = static_cast(version->valueint); + + if (p_State->Settings.Version != SETTINGS_VERSION) { + ESP_LOGW(TAG, "Settings version mismatch (expected %u, got %u), erasing and using defaults", + SETTINGS_VERSION, p_State->Settings.Version); + + Error = ESP_ERR_INVALID_VERSION; + + goto SettingsManager_Load_JSON_Exit; + } + } else { + Error = ESP_ERR_INVALID_VERSION; + + goto SettingsManager_Load_JSON_Exit; + } + + Error = ESP_OK; + /* Load settings sections */ SettingsManager_LoadDisplay(p_State, JSON); - /* Extract provisioning settings */ + /* Extract Provisioning settings */ SettingsManager_LoadProvisioning(p_State, JSON); /* Extract WiFi settings */ SettingsManager_LoadWiFi(p_State, JSON); - /* Extract system settings */ + /* Extract System settings */ SettingsManager_LoadSystem(p_State, JSON); /* Extract Lepton settings */ @@ -481,24 +415,16 @@ static esp_err_t SettingsManager_Load_JSON(SettingsManager_State_t *p_State, con /* Extract VISA Server settings */ SettingsManager_LoadVISAServer(p_State, JSON); +SettingsManager_Load_JSON_Exit: cJSON_Delete(JSON); - return ESP_OK; + return Error; } -esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State) +esp_err_t SettingsManager_LoadDefaultsFromJSON(Settings_Manager_State_t *p_State) { uint8_t ConfigLoaded = 0; esp_err_t Error; - esp_vfs_littlefs_conf_t LittleFS_Config = { - .base_path = "/littlefs", - .partition_label = "storage", - .partition = NULL, - .format_if_mount_failed = true, - .read_only = true, - .dont_mount = false, - .grow_on_mount = false - }; Error = nvs_get_u8(p_State->NVS_Handle, "config_loaded", &ConfigLoaded); if ((Error == ESP_OK) && (ConfigLoaded == true)) { @@ -506,46 +432,20 @@ esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State) return ESP_OK; } - ESP_LOGD(TAG, "Loading settings with priority: SD Card -> LittleFS -> Built-in defaults"); + ESP_LOGI(TAG, "Loading settings from /storage (managed by MemoryManager)"); - /* 1. Try SD card */ - Error = SettingsManager_Mount_SD_Card(); + /* Try to load from /storage - MemoryManager decides if this is SD card or internal flash */ + Error = SettingsManager_Load_JSON(p_State, "/storage/settings.json"); if (Error == ESP_OK) { - Error = SettingsManager_Load_JSON(p_State, "/sdcard/settings.json"); - - /* Check for 8.3 filename match */ - if (Error != ESP_OK) { - ESP_LOGW(TAG, "Falling back to 8.3 filename: SETTIN~1.JSO"); - Error = SettingsManager_Load_JSON(p_State, "/sdcard/SETTIN~1.JSO"); - } - - SettingsManager_Unmount_SD_Card(); + ESP_LOGI(TAG, "Settings loaded from /storage/settings.json"); - if (Error == ESP_OK) { - ESP_LOGD(TAG, "Settings loaded from SD card"); - return ESP_OK; - } - ESP_LOGW(TAG, "SD card mounted but no valid settings.json found"); - } else { - ESP_LOGD(TAG, "SD card not available, trying LittleFS"); + /* Do NOT delete the file - user should be able to edit it via USB or by placing it on SD card */ + return ESP_OK; } - /* 2. Try LittleFS */ - Error = esp_vfs_littlefs_register(&LittleFS_Config); - if (Error == ESP_OK) { - Error = SettingsManager_Load_JSON(p_State, "/littlefs/settings.json"); - esp_vfs_littlefs_unregister(LittleFS_Config.partition_label); - - if (Error == ESP_OK) { - ESP_LOGD(TAG, "Settings loaded from LittleFS"); - return ESP_OK; - } - ESP_LOGW(TAG, "LittleFS mounted but no valid settings.json found"); - } else { - ESP_LOGW(TAG, "Failed to mount LittleFS: %d!", Error); - } + ESP_LOGW(TAG, "No settings.json found on /storage, falling back to built-in defaults"); - /* 3. Fallback to built-in defaults */ + /* Fallback to built-in defaults */ ESP_LOGW(TAG, "Using built-in default settings"); SettingsManager_InitDefaults(p_State); diff --git a/main/Application/Manager/Settings/Private/settingsLoader.h b/main/Application/Manager/Settings/Private/settingsLoader.h index c3a683f..2bceada 100644 --- a/main/Application/Manager/Settings/Private/settingsLoader.h +++ b/main/Application/Manager/Settings/Private/settingsLoader.h @@ -68,13 +68,15 @@ typedef struct { App_Settings_t Settings; App_Settings_Info_t Info; SemaphoreHandle_t Mutex; -} SettingsManager_State_t; +} Settings_Manager_State_t; /** @brief Initialize the settings presets from the NVS by using a config JSON file. * @param p_State Pointer to the Settings Manager state structure - * @return ESP_OK on success, ESP_ERR_* on failure + * @return ESP_OK on succes + * ESP_ERR_INVALID_VERSION if the version in the JSON is older or invalid + * ESP_ERR_* on failure */ -esp_err_t SettingsManager_LoadDefaultsFromJSON(SettingsManager_State_t *p_State); +esp_err_t SettingsManager_LoadDefaultsFromJSON(Settings_Manager_State_t *p_State); /** @brief Initialize Lepton ROIs with factory defaults. * @param p_Settings Pointer to settings structure @@ -89,7 +91,7 @@ void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settin /** @brief Initialize settings with factory defaults. * @param p_State Pointer to Settings Manager state structure */ -void SettingsManager_InitDefaults(SettingsManager_State_t *p_State); +void SettingsManager_InitDefaults(Settings_Manager_State_t *p_State); /** @brief Initialize Display settings with factory defaults. * @param p_Settings Pointer to settings structure diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index a611d65..a707c72 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Persistent settings management using NVS storage. + * File info: Settings Manager implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,6 @@ */ #include -#include #include #include #include @@ -37,11 +36,11 @@ #include "settingsManager.h" #include "Private/settingsLoader.h" -static const char *TAG = "settings_manager"; +static const char *TAG = "Settings-Manager"; ESP_EVENT_DEFINE_BASE(SETTINGS_EVENTS); -static SettingsManager_State_t _State; +static Settings_Manager_State_t _Settings_Manager_State; /** @brief Update a specific settings section in the Settings Manager RAM and emit the corresponding event. * @param p_Src Pointer to source settings structure @@ -51,21 +50,24 @@ static SettingsManager_State_t _State; * @param p_ChangedSetting Pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) * @return ESP_OK on success */ -static esp_err_t SettingsManager_Update(void* p_Src, void* p_Dst, size_t Size, int EventID, SettingsManager_Setting_t* p_ChangedSetting = NULL) +static esp_err_t SettingsManager_Update(void *p_Src, void *p_Dst, size_t Size, int EventID, + SettingsManager_Setting_t *p_ChangedSetting = NULL) { - if (_State.isInitialized == false) { + if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } else if ((p_Src == NULL) || (p_Dst == NULL) || (Size == 0)) { return ESP_ERR_INVALID_ARG; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); memcpy(p_Dst, p_Src, Size); - xSemaphoreGive(_State.Mutex); + xSemaphoreGive(_Settings_Manager_State.Mutex); - esp_event_post(SETTINGS_EVENTS, EventID, p_ChangedSetting, sizeof(SettingsManager_Setting_t), portMAX_DELAY); + /* Only include event data if p_ChangedSetting is valid */ + esp_event_post(SETTINGS_EVENTS, EventID, p_ChangedSetting, + p_ChangedSetting ? sizeof(SettingsManager_Setting_t) : 0, portMAX_DELAY); return ESP_OK; } @@ -75,97 +77,131 @@ esp_err_t SettingsManager_Init(void) uint16_t Serial; esp_err_t Error; - if (_State.isInitialized) { + if (_Settings_Manager_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; } ESP_LOGI(TAG, "Initializing Settings Manager..."); + memset(&_Settings_Manager_State, 0, sizeof(Settings_Manager_State_t)); + ESP_ERROR_CHECK(nvs_flash_init()); Error = nvs_flash_init_partition("settings"); if ((Error == ESP_ERR_NVS_NO_FREE_PAGES) || (Error == ESP_ERR_NVS_NEW_VERSION_FOUND)) { ESP_LOGW(TAG, "Settings partition needs erase, erasing..."); ESP_ERROR_CHECK(nvs_flash_erase_partition("settings")); - Error = nvs_flash_init_partition("settings"); + + nvs_flash_init_partition("settings"); } else if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize settings partition: %d!", Error); + return Error; } - _State.Mutex = xSemaphoreCreateMutex(); - if (_State.Mutex == NULL) { + _Settings_Manager_State.Mutex = xSemaphoreCreateMutex(); + if (_Settings_Manager_State.Mutex == NULL) { ESP_LOGE(TAG, "Failed to create mutex!"); return ESP_ERR_NO_MEM; } - Error = nvs_open_from_partition("settings", CONFIG_SETTINGS_NAMESPACE, NVS_READWRITE, &_State.NVS_Handle); + Error = nvs_open_from_partition("settings", CONFIG_SETTINGS_NAMESPACE, NVS_READWRITE, + &_Settings_Manager_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to open NVS handle: %d!", Error); - vSemaphoreDelete(_State.Mutex); + vSemaphoreDelete(_Settings_Manager_State.Mutex); return Error; } - _State.isInitialized = true; - - /* Copy the read-only data */ - sprintf(_State.Info.FirmwareVersion, "%u.%u.%u", PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, - PYROVISION_VERSION_BUILD); - sprintf(_State.Info.Manufacturer, "%s", CONFIG_DEVICE_MANUFACTURER); + _Settings_Manager_State.isInitialized = true; - xSemaphoreTake(_State.Mutex, portMAX_DELAY); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); /* Get the serial from NVS. Use a temporary variable to prevent alignment errors. */ - Error = nvs_get_u16(_State.NVS_Handle, "serial", &Serial); - _State.Info.Serial = Serial; - + Error = nvs_get_u16(_Settings_Manager_State.NVS_Handle, "serial", &Serial); if (Error != ESP_OK) { ESP_LOGW(TAG, "Failed to get serial number from NVS: %d!. Using 0", Error); - _State.Info.Serial = 0; + Serial = 0; + } + + xSemaphoreGive(_Settings_Manager_State.Mutex); + + /* Copy the read-only data */ + sprintf(_Settings_Manager_State.Info.FirmwareVersion, "%u.%u.%u", PYROVISION_VERSION_MAJOR, PYROVISION_VERSION_MINOR, + PYROVISION_VERSION_BUILD); + sprintf(_Settings_Manager_State.Info.Manufacturer, "%s", CONFIG_DEVICE_MANUFACTURER); + sprintf(_Settings_Manager_State.Info.Name, "%s", CONFIG_DEVICE_NAME); + sprintf(_Settings_Manager_State.Info.Serial, "%u", Serial); + sprintf(_Settings_Manager_State.Info.SDK, "%s", IDF_VER); + + /* Get application description with version info */ + const esp_app_desc_t *p_AppDesc = esp_app_get_description(); + sprintf(_Settings_Manager_State.Info.Commit, "%s", p_AppDesc->version); + ESP_LOGI(TAG, "Firmware Version: %s", p_AppDesc->version); + ESP_LOGI(TAG, "Firmware Date: %s %s", p_AppDesc->date, p_AppDesc->time); + ESP_LOGI(TAG, "Firmware IDF: %s", p_AppDesc->idf_ver); + + /* Read bootloader information */ + const esp_partition_t *p_BootloaderPartition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, + ESP_PARTITION_SUBTYPE_APP_FACTORY, + NULL); + if (p_BootloaderPartition != NULL) { + Error = esp_ota_get_partition_description(p_BootloaderPartition, &_Settings_Manager_State.Info.Bootloader); + if (Error == ESP_OK) { + ESP_LOGD(TAG, "Bootloader version: %s", _Settings_Manager_State.Info.Bootloader.version); + ESP_LOGD(TAG, "Bootloader date: %s %s", _Settings_Manager_State.Info.Bootloader.date, + _Settings_Manager_State.Info.Bootloader.time); + ESP_LOGD(TAG, "Bootloader IDF version: %s", _Settings_Manager_State.Info.Bootloader.idf_ver); + } else { + ESP_LOGW(TAG, "Failed to read bootloader description: %d!", Error); + } + } else { + ESP_LOGW(TAG, "Bootloader partition not found"); } - xSemaphoreGive(_State.Mutex); /* Load the settings from the NVS */ - Error = SettingsManager_Load(&_State.Settings); + Error = SettingsManager_Load(&_Settings_Manager_State.Settings); if (Error != ESP_OK) { ESP_LOGI(TAG, "No settings found, using factory defaults"); /* Try to load default settings from JSON first (on first boot) */ - if (SettingsManager_LoadDefaultsFromJSON(&_State) != ESP_OK) { + if (SettingsManager_LoadDefaultsFromJSON(&_Settings_Manager_State) != ESP_OK) { ESP_LOGW(TAG, "Failed to load default settings from JSON, using built-in defaults"); /* Use built-in defaults */ - SettingsManager_InitDefaults(&_State); + SettingsManager_InitDefaults(&_Settings_Manager_State); } /* Save the default settings to NVS */ SettingsManager_Save(); /* Load the JSON presets into the settings structure */ - SettingsManager_Load(&_State.Settings); + SettingsManager_Load(&_Settings_Manager_State.Settings); } ESP_LOGI(TAG, "Settings Manager initialized"); - esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_LOADED, &_State.Settings, sizeof(App_Settings_t), portMAX_DELAY); + esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_LOADED, &_Settings_Manager_State.Settings, sizeof(App_Settings_t), + portMAX_DELAY); return ESP_OK; } esp_err_t SettingsManager_Deinit(void) { - if (_State.isInitialized == false) { + if (_Settings_Manager_State.isInitialized == false) { return ESP_OK; } - nvs_close(_State.NVS_Handle); - vSemaphoreDelete(_State.Mutex); + nvs_close(_Settings_Manager_State.NVS_Handle); + vSemaphoreDelete(_Settings_Manager_State.Mutex); - _State.isInitialized = false; + _Settings_Manager_State.isInitialized = false; ESP_LOGI(TAG, "Settings Manager deinitialized"); @@ -177,80 +213,98 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) esp_err_t Error; size_t RequiredSize; - if (_State.isInitialized == false) { + if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } else if (p_Settings == NULL) { return ESP_ERR_INVALID_ARG; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); - Error = nvs_get_blob(_State.NVS_Handle, "settings", NULL, &RequiredSize); - if (Error == ESP_ERR_NVS_NOT_FOUND) { - xSemaphoreGive(_State.Mutex); + /* Get the settings version from NVS. Continue loading if the version numbers match. */ + Error = nvs_get_u32(_Settings_Manager_State.NVS_Handle, "version", &p_Settings->Version); + if ((Error == ESP_OK) && (p_Settings->Version == SETTINGS_VERSION)) { + Error = nvs_get_blob(_Settings_Manager_State.NVS_Handle, "settings", NULL, &RequiredSize); + if (Error == ESP_ERR_NVS_NOT_FOUND) { + ESP_LOGW(TAG, "Settings not found in NVS!"); - return ESP_ERR_NVS_NOT_FOUND; - } else if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to get settings size: %d!", Error); - xSemaphoreGive(_State.Mutex); - return Error; - } + Error = ESP_ERR_NVS_NOT_FOUND; - if (RequiredSize != sizeof(App_Settings_t)) { - ESP_LOGW(TAG, "Settings size mismatch (expected %u, got %u), erasing and using defaults", - sizeof(App_Settings_t), RequiredSize); + goto SettingsManager_Load_Exit; + } else if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to get settings size: %d!", Error); - /* Erase the old settings */ - nvs_erase_key(_State.NVS_Handle, "settings"); - nvs_commit(_State.NVS_Handle); + xSemaphoreGive(_Settings_Manager_State.Mutex); - xSemaphoreGive(_State.Mutex); + goto SettingsManager_Load_Exit; + } - return ESP_ERR_INVALID_SIZE; - } + if (RequiredSize != sizeof(App_Settings_t)) { + ESP_LOGW(TAG, "Settings size mismatch (expected %u, got %u), erasing and using defaults", + sizeof(App_Settings_t), RequiredSize); - Error = nvs_get_blob(_State.NVS_Handle, "settings", &_State.Settings, &RequiredSize); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to read settings: %d!", Error); - xSemaphoreGive(_State.Mutex); + /* Erase the old settings */ + nvs_erase_key(_Settings_Manager_State.NVS_Handle, "settings"); + nvs_commit(_Settings_Manager_State.NVS_Handle); - return Error; - } + Error = ESP_ERR_INVALID_SIZE; + + goto SettingsManager_Load_Exit; + } - memcpy(p_Settings, &_State.Settings, sizeof(App_Settings_t)); + Error = nvs_get_blob(_Settings_Manager_State.NVS_Handle, "settings", &_Settings_Manager_State.Settings, &RequiredSize); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to read settings: %d!", Error); - xSemaphoreGive(_State.Mutex); + goto SettingsManager_Load_Exit; + } - ESP_LOGD(TAG, "Settings loaded from NVS"); + memcpy(p_Settings, &_Settings_Manager_State.Settings, sizeof(App_Settings_t)); - return ESP_OK; + ESP_LOGD(TAG, "Settings loaded from NVS"); + + Error = ESP_OK; + } + /* We reach this case when we can no read a settings version because it does not exist or does not match */ + else { + ESP_LOGI(TAG, "Settings version mismatch or not found in NVS (expected %u, got %u), erasing and using defaults", + SETTINGS_VERSION, p_Settings->Version); + + Error = ESP_ERR_INVALID_VERSION; + } + +SettingsManager_Load_Exit: + xSemaphoreGive(_Settings_Manager_State.Mutex); + + return Error; } esp_err_t SettingsManager_Save(void) { esp_err_t Error; - if (_State.isInitialized == false) { + if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); - Error = nvs_set_blob(_State.NVS_Handle, "settings", &_State.Settings, sizeof(App_Settings_t)); + Error = nvs_set_blob(_Settings_Manager_State.NVS_Handle, "settings", &_Settings_Manager_State.Settings, + sizeof(App_Settings_t)); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to write settings: %d!", Error); - xSemaphoreGive(_State.Mutex); + xSemaphoreGive(_Settings_Manager_State.Mutex); return Error; } - Error = nvs_commit(_State.NVS_Handle); + Error = nvs_commit(_Settings_Manager_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to commit settings: %d!", Error); - xSemaphoreGive(_State.Mutex); + xSemaphoreGive(_Settings_Manager_State.Mutex); return Error; } - xSemaphoreGive(_State.Mutex); + xSemaphoreGive(_Settings_Manager_State.Mutex); ESP_LOGI(TAG, "Settings saved to NVS"); @@ -259,165 +313,168 @@ esp_err_t SettingsManager_Save(void) return ESP_OK; } -esp_err_t SettingsManager_GetInfo(App_Settings_Info_t* p_Settings) +esp_err_t SettingsManager_GetInfo(App_Settings_Info_t *p_Settings) { if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; - } else if (_State.isInitialized == false) { + } else if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Info, sizeof(App_Settings_Info_t)); - xSemaphoreGive(_State.Mutex); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_Settings_Manager_State.Info, sizeof(App_Settings_Info_t)); + xSemaphoreGive(_Settings_Manager_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings) +esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t *p_Settings) { if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; - } else if (_State.isInitialized == false) { + } else if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Settings.Lepton, sizeof(App_Settings_Lepton_t)); - xSemaphoreGive(_State.Mutex); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_Settings_Manager_State.Settings.Lepton, sizeof(App_Settings_Lepton_t)); + xSemaphoreGive(_Settings_Manager_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings, SettingsManager_Setting_t* p_ChangedSetting) +esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t *p_Settings, SettingsManager_Setting_t *p_ChangedSetting) { - return SettingsManager_Update(p_Settings, &_State.Settings.Lepton, sizeof(App_Settings_Lepton_t), + return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.Lepton, sizeof(App_Settings_Lepton_t), SETTINGS_EVENT_LEPTON_CHANGED, p_ChangedSetting); } -esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t* p_Settings) +esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t *p_Settings) { if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; - } else if (_State.isInitialized == false) { + } else if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Settings.WiFi, sizeof(App_Settings_WiFi_t)); - xSemaphoreGive(_State.Mutex); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_Settings_Manager_State.Settings.WiFi, sizeof(App_Settings_WiFi_t)); + xSemaphoreGive(_Settings_Manager_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t* p_Settings) +esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t *p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.WiFi, sizeof(App_Settings_WiFi_t), + return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.WiFi, sizeof(App_Settings_WiFi_t), SETTINGS_EVENT_WIFI_CHANGED); } -esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t* p_Settings) +esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t *p_Settings) { if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; - } else if (_State.isInitialized == false) { + } else if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Settings.Provisioning, sizeof(App_Settings_Provisioning_t)); - xSemaphoreGive(_State.Mutex); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_Settings_Manager_State.Settings.Provisioning, sizeof(App_Settings_Provisioning_t)); + xSemaphoreGive(_Settings_Manager_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t* p_Settings) +esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t *p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.Provisioning, sizeof(App_Settings_Provisioning_t), + return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.Provisioning, + sizeof(App_Settings_Provisioning_t), SETTINGS_EVENT_PROVISIONING_CHANGED); } -esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t* p_Settings) +esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t *p_Settings) { if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; - } else if (_State.isInitialized == false) { + } else if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Settings.Display, sizeof(App_Settings_Display_t)); - xSemaphoreGive(_State.Mutex); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_Settings_Manager_State.Settings.Display, sizeof(App_Settings_Display_t)); + xSemaphoreGive(_Settings_Manager_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t* p_Settings) +esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t *p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.Display, sizeof(App_Settings_Display_t), + return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.Display, sizeof(App_Settings_Display_t), SETTINGS_EVENT_DISPLAY_CHANGED); } -esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t* p_Settings) +esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t *p_Settings) { if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; - } else if (_State.isInitialized == false) { + } else if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Settings.HTTPServer, sizeof(App_Settings_HTTP_Server_t)); - xSemaphoreGive(_State.Mutex); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_Settings_Manager_State.Settings.HTTPServer, sizeof(App_Settings_HTTP_Server_t)); + xSemaphoreGive(_Settings_Manager_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t* p_Settings) +esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t *p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.HTTPServer, sizeof(App_Settings_HTTP_Server_t), + return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.HTTPServer, + sizeof(App_Settings_HTTP_Server_t), SETTINGS_EVENT_HTTP_SERVER_CHANGED); } -esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t* p_Settings) +esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t *p_Settings) { if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; - } else if (_State.isInitialized == false) { + } else if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Settings.VISAServer, sizeof(App_Settings_VISA_Server_t)); - xSemaphoreGive(_State.Mutex); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_Settings_Manager_State.Settings.VISAServer, sizeof(App_Settings_VISA_Server_t)); + xSemaphoreGive(_Settings_Manager_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t* p_Settings) +esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t *p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.VISAServer, sizeof(App_Settings_VISA_Server_t), + return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.VISAServer, + sizeof(App_Settings_VISA_Server_t), SETTINGS_EVENT_VISA_SERVER_CHANGED); } -esp_err_t SettingsManager_GetSystem(App_Settings_System_t* p_Settings) +esp_err_t SettingsManager_GetSystem(App_Settings_System_t *p_Settings) { if ( p_Settings == NULL ) { return ESP_ERR_INVALID_ARG; - } else if (_State.isInitialized == false) { + } else if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } - xSemaphoreTake(_State.Mutex, portMAX_DELAY); - memcpy(p_Settings, &_State.Settings.System, sizeof(App_Settings_System_t)); - xSemaphoreGive(_State.Mutex); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + memcpy(p_Settings, &_Settings_Manager_State.Settings.System, sizeof(App_Settings_System_t)); + xSemaphoreGive(_Settings_Manager_State.Mutex); return ESP_OK; } -esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t* p_Settings) +esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t *p_Settings) { - return SettingsManager_Update(p_Settings, &_State.Settings.System, sizeof(App_Settings_System_t), + return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.System, sizeof(App_Settings_System_t), SETTINGS_EVENT_SYSTEM_CHANGED); } @@ -425,37 +482,43 @@ esp_err_t SettingsManager_ResetToDefaults(void) { esp_err_t Error; - if (_State.isInitialized == false) { + if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; } ESP_LOGW(TAG, "Resetting settings to factory defaults"); - xSemaphoreTake(_State.Mutex, portMAX_DELAY); + xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); - Error = nvs_erase_key(_State.NVS_Handle, "settings"); + Error = nvs_erase_key(_Settings_Manager_State.NVS_Handle, "settings"); if (Error != ESP_OK && Error != ESP_ERR_NVS_NOT_FOUND) { ESP_LOGE(TAG, "Failed to erase settings: %d!", Error); - xSemaphoreGive(_State.Mutex); + + xSemaphoreGive(_Settings_Manager_State.Mutex); + return Error; } - Error = nvs_commit(_State.NVS_Handle); + Error = nvs_commit(_Settings_Manager_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to commit erase: %d!", Error); - xSemaphoreGive(_State.Mutex); + + xSemaphoreGive(_Settings_Manager_State.Mutex); + return Error; } /* Reset config_loaded flag to allow reloading default config */ - Error = nvs_set_u8(_State.NVS_Handle, "config_loaded", false); + Error = nvs_set_u8(_Settings_Manager_State.NVS_Handle, "config_loaded", false); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to set config_loaded flag: %d!", Error); - xSemaphoreGive(_State.Mutex); + + xSemaphoreGive(_Settings_Manager_State.Mutex); + return Error; } - xSemaphoreGive(_State.Mutex); + xSemaphoreGive(_Settings_Manager_State.Mutex); /* Reboot the ESP to allow reloading the settings config */ esp_restart(); diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h index 3303344..a10792a 100644 --- a/main/Application/Manager/Settings/settingsManager.h +++ b/main/Application/Manager/Settings/settingsManager.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Persistent settings management using NVS storage. + * File info: Settings Manager definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,24 +29,57 @@ #include "settingsTypes.h" -/** @brief Initialize the Settings Manager and load all settings from NVS into the Settings Manager RAM and into the provided structure. - * @return ESP_OK on success +/** @brief Initialize the Settings Manager and load settings from NVS. + * Opens NVS namespace, loads stored settings into RAM, or loads defaults + * if no settings exist. Creates event handlers for settings changes. + * @note Must be called after NVS flash initialization. + * Default settings loaded from JSON or hardcoded fallback. + * Call this before any other SettingsManager functions. + * @warning Not thread-safe during initialization. + * @return ESP_OK on success + * ESP_ERR_NVS_NOT_FOUND if NVS namespace doesn't exist (first boot) + * ESP_ERR_NO_MEM if memory allocation fails + * ESP_ERR_INVALID_STATE if already initialized + * ESP_FAIL if NVS initialization fails */ esp_err_t SettingsManager_Init(void); -/** @brief Deinitialize the Settings Manager. - * @return ESP_OK on success +/** @brief Deinitialize the Settings Manager. + * Closes NVS handle and frees all resources. Unsaved settings in RAM + * are lost. + * @note Call SettingsManager_Save() first to persist changes. + * @warning All unsaved settings changes are lost permanently. + * @return ESP_OK on success + * ESP_FAIL if NVS close fails */ esp_err_t SettingsManager_Deinit(void); -/** @brief Load all settings from NVS into the Settings Manager RAM and into the provided structure. This function overwrites all unsaved settings in RAM. +/** @brief Load all settings from NVS into RAM. + * Reloads settings from NVS, overwriting any unsaved changes in RAM. + * Use this to discard uncommitted changes. + * @note This overwrites all unsaved settings in RAM. + * Version mismatch triggers default settings reload. + * @warning All uncommitted changes are lost! * @param p_Settings Pointer to settings structure to populate - * @return ESP_OK on success, ESP_ERR_NVS_NOT_FOUND if no settings exist + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Settings is NULL + * ESP_ERR_NVS_NOT_FOUND if no settings exist in NVS + * ESP_ERR_INVALID_VERSION if version mismatch + * ESP_ERR_INVALID_SIZE if size mismatch (corrupted) + * ESP_FAIL on other NVS errors */ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings); -/** @brief Save all RAM settings to NVS. - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Save all RAM settings to NVS. + * Writes current settings from RAM to non-volatile storage. Changes + * become permanent and survive power cycles. + * @note Call this after any Update functions to persist changes. + * NVS has limited write cycles (~100k) - avoid excessive saves. + * Posts SETTINGS_EVENT_SAVED event on success. + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not initialized + * ESP_ERR_NVS_NOT_ENOUGH_SPACE if NVS is full + * ESP_FAIL if NVS write fails */ esp_err_t SettingsManager_Save(void); @@ -54,13 +87,13 @@ esp_err_t SettingsManager_Save(void); * @param p_Settings Pointer to Info structure to populate * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_GetInfo(App_Settings_Info_t* p_Settings); +esp_err_t SettingsManager_GetInfo(App_Settings_Info_t *p_Settings); /** @brief Get the Lepton settings from the Settings Manager RAM. * @param p_Settings Pointer to System settings structure to populate * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings); +esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t *p_Settings); /** @brief Update Lepton settings in the Settings Manager RAM. * This function triggers the SETTINGS_EVENT_LEPTON_CHANGED event. @@ -68,85 +101,86 @@ esp_err_t SettingsManager_GetLepton(App_Settings_Lepton_t* p_Settings); * @param p_ChangedSetting Optional pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t* p_Settings, SettingsManager_Setting_t* p_ChangedSetting = NULL); +esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t *p_Settings, + SettingsManager_Setting_t *p_ChangedSetting = NULL); /** @brief Get the WiFi settings from the Settings Manager RAM. * @param p_Settings Pointer to WiFi settings structure to populate * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t* p_Settings); +esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t *p_Settings); /** @brief Update WiFi settings in the Settings Manager RAM. * This function triggers the SETTINGS_EVENT_WIFI_CHANGED event. * @param p_Settings Pointer to WiFi settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t* p_Settings); +esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t *p_Settings); /** @brief Get the Provisioning settings from the Settings Manager RAM. * @param p_Settings Pointer to Provisioning settings structure to populate * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t* p_Settings); +esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t *p_Settings); /** @brief Update Provisioning settings in the Settings Manager RAM. * This function triggers the SETTINGS_EVENT_PROVISIONING_CHANGED event. * @param p_Settings Pointer to Provisioning settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t* p_Settings); +esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t *p_Settings); /** @brief Get the Display settings from the Settings Manager RAM. * @param p_Settings Pointer to Display settings structure to populate * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t* p_Settings); +esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t *p_Settings); /** @brief Update Display settings in the Settings Manager RAM. * This function triggers the SETTINGS_EVENT_DISPLAY_CHANGED event. * @param p_Settings Pointer to Display settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t* p_Settings); +esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t *p_Settings); /** @brief Get the HTTP Server settings from the Settings Manager RAM. * @param p_Settings Pointer to HTTP Server settings structure to populate * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t* p_Settings); +esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t *p_Settings); /** @brief Update HTTP Server settings in the Settings Manager RAM. * This function triggers the SETTINGS_EVENT_HTTP_SERVER_CHANGED event. * @param p_Settings Pointer to HTTP Server settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t* p_Settings); +esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t *p_Settings); /** @brief Get the VISA Server settings from the Settings Manager RAM. * @param p_Settings Pointer to VISA Server settings structure to populate * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t* p_Settings); +esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t *p_Settings); /** @brief Update VISA Server settings in the Settings Manager RAM. * This function triggers the SETTINGS_EVENT_VISA_SERVER_CHANGED event. * @param p_Settings Pointer to VISA Server settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t* p_Settings); +esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t *p_Settings); /** @brief Get the system settings from the Settings Manager RAM. * @param p_Settings Pointer to System settings structure to populate * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_GetSystem(App_Settings_System_t* p_Settings); +esp_err_t SettingsManager_GetSystem(App_Settings_System_t *p_Settings); /** @brief Update System settings in the Settings Manager RAM. * This function triggers the SETTINGS_EVENT_SYSTEM_CHANGED event. * @param p_Settings Pointer to System settings structure * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t* p_Settings); +esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t *p_Settings); /** @brief Reset all settings to factory defaults. * Erases NVS partition and reloads defaults. diff --git a/main/Application/Manager/Settings/settingsTypes.h b/main/Application/Manager/Settings/settingsTypes.h index 26e1f2c..f88dfbe 100644 --- a/main/Application/Manager/Settings/settingsTypes.h +++ b/main/Application/Manager/Settings/settingsTypes.h @@ -1,9 +1,9 @@ /* - * settings_types.h + * settingsTypes.h * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Settings Manager event types and definitions. + * File info: Common type definitions for the Settings Manager component. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,17 +24,25 @@ #ifndef SETTINGS_TYPES_H_ #define SETTINGS_TYPES_H_ +#include +#include +#include +#include + #include #include #include -#include +/** @brief Version number for the NVS based settings structure. + * NOTE: Migration isnt suppored yet! + */ +#define SETTINGS_VERSION 1 /** @brief Settings Manager events base. */ ESP_EVENT_DECLARE_BASE(SETTINGS_EVENTS); -/** @brief Settings event identifiers. +/** @brief Settings Manager event identifiers. */ enum { SETTINGS_EVENT_LOADED, /**< Settings loaded from NVS. */ @@ -47,7 +55,7 @@ enum { Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_DISPLAY_CHANGED, /**< Display settings changed. Data contains SettingsManager_Setting_t. */ - SETTINGS_EVENT_HTTP_SERVER_CHANGED, /**< HTTP server settings changed. + SETTINGS_EVENT_HTTP_SERVER_CHANGED, /**< HTTP server settings changed. Data contains SettingsManager_Setting_t. */ SETTINGS_EVENT_VISA_SERVER_CHANGED, /**< VISA server settings changed. Data contains SettingsManager_Setting_t. */ @@ -97,7 +105,21 @@ typedef struct { uint16_t h; /**< Height of the ROI. */ } App_Settings_ROI_t; -/** @brief Lepton camera settings. +/** @brief Device informations. + * NOTE: This structure is not covered by the settings version number because it is not stored in the NVS. + */ +typedef struct { + char FirmwareVersion[16]; /**< Firmware version string, null-terminated. */ + char Manufacturer[32]; /**< Manufacturer string, null-terminated. */ + char Name[32]; /**< Device name string, null-terminated. */ + char Serial[16]; /**< Device serial number string, null-terminated. */ + char SDK[16]; /**< Firmware SDK version string, null-terminated. */ + char Commit[32]; /**< Firmware commit hash string, null-terminated. */ + esp_app_desc_t Bootloader; /**< Bootloader information. */ +} App_Settings_Info_t; + +/** @brief Lepton camera settings. + * NOTE: This structure is covered by the settings version number because it is stored in the NVS. */ typedef struct { App_Settings_ROI_t ROI[4]; /**< Camera ROIs. */ @@ -106,7 +128,8 @@ typedef struct { uint8_t CurrentEmissivity; /**< Currently selected emissivity value in the range from 0 to 100. */ } __attribute__((packed)) App_Settings_Lepton_t; -/** @brief WiFi settings. +/** @brief WiFi settings. + * NOTE: This structure is covered by the settings version number because it is stored in the NVS. */ typedef struct { char SSID[33]; /**< WiFi SSID. */ @@ -116,29 +139,24 @@ typedef struct { uint16_t RetryInterval; /**< Interval between connection retries in milliseconds. */ } __attribute__((packed)) App_Settings_WiFi_t; -/** @brief Provisioning settings. +/** @brief Provisioning settings. + * NOTE: This structure is covered by the settings version number because it is stored in the NVS. */ typedef struct { char Name[32]; /**< Device name for provisioning. */ uint32_t Timeout; /**< Provisioning timeout in seconds. */ } __attribute__((packed)) App_Settings_Provisioning_t; -/** @brief Device informations. - */ -typedef struct { - char FirmwareVersion[16]; /**< Firmware version string. */ - char Manufacturer[16]; /**< Manufacturer string. */ - uint16_t Serial; /**< Device serial number. */ -} __attribute__((packed)) App_Settings_Info_t; - -/** @brief Display settings. +/** @brief Display settings. + * NOTE: This structure is covered by the settings version number because it is stored in the NVS. */ typedef struct { uint8_t Brightness; /**< Display brightness (0-100%). */ - uint16_t Timeout; /**< Screen timeout in seconds (0=never). */ + uint16_t Timeout; /**< Screen timeout in seconds (0 = never). */ } __attribute__((packed)) App_Settings_Display_t; -/** @brief HTTP server settings. +/** @brief HTTP server settings. + * NOTE: This structure is covered by the settings version number because it is stored in the NVS. */ typedef struct { uint16_t Port; /**< HTTP server port. */ @@ -146,13 +164,15 @@ typedef struct { uint8_t MaxClients; /**< Maximum number of simultaneous clients. */ } __attribute__((packed)) App_Settings_HTTP_Server_t; -/** @brief VISA server settings. +/** @brief VISA server settings. + * NOTE: This structure is covered by the settings version number because it is stored in the NVS. */ typedef struct { uint16_t Port; /**< VISA server port. */ } __attribute__((packed)) App_Settings_VISA_Server_t; -/** @brief System settings. +/** @brief System settings. + * NOTE: This structure is covered by the settings version number because it is stored in the NVS. */ typedef struct { bool SDCard_AutoMount; /**< Automatically mount SD card. */ @@ -165,7 +185,7 @@ typedef struct { /** @brief Complete application settings structure. */ typedef struct { - App_Settings_Info_t Info; /**< General device information. */ + uint32_t Version; /**< Settings version number. */ App_Settings_Lepton_t Lepton; /**< Lepton camera settings. */ App_Settings_WiFi_t WiFi; /**< WiFi settings. */ App_Settings_Provisioning_t Provisioning; /**< Provisioning settings. */ @@ -173,6 +193,6 @@ typedef struct { App_Settings_HTTP_Server_t HTTPServer; /**< HTTP server settings. */ App_Settings_VISA_Server_t VISAServer; /**< VISA server settings. */ App_Settings_System_t System; /**< System settings. */ -} __attribute__((packed)) App_Settings_t; +} App_Settings_t; #endif /* SETTINGS_TYPES_H_ */ diff --git a/main/Application/Manager/Time/timeManager.cpp b/main/Application/Manager/Time/timeManager.cpp index 52c1166..4e99acd 100644 --- a/main/Application/Manager/Time/timeManager.cpp +++ b/main/Application/Manager/Time/timeManager.cpp @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Unified time management with SNTP and RTC backup. + * File info: Time Manager implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,26 +24,24 @@ #include #include #include -#include #include #include #include "timeManager.h" -#include "../Devices/RTC/rtc.h" +#include "../Devices/devicesManager.h" ESP_EVENT_DEFINE_BASE(TIME_EVENTS); -#define TIME_MANAGER_SYNC_INTERVAL_SEC 3600 /* Sync every hour */ +#define TIME_MANAGER_SYNC_INTERVAL_SEC 3600 /* Sync every hour */ #define TIME_MANAGER_RTC_BACKUP_INTERVAL_SEC 300 /* Save to RTC every 5 minutes */ -#define TIME_MANAGER_VALID_YEAR_MIN 2025 /* Minimum valid year */ +#define TIME_MANAGER_VALID_YEAR_MIN 2025 /* Minimum valid year */ typedef struct { bool isInitialized; bool hasRTC; bool hasNetwork; bool timeSynchronized; - i2c_master_dev_handle_t RTC_Handle; TimeManager_Source_t activeSource; time_t lastSNTP_Sync; time_t lastRTC_Sync; @@ -55,7 +53,7 @@ typedef struct { static TimeManager_State_t _TimeManager_State; -static const char *TAG = "time-manager"; +static const char *TAG = "Time-Manager"; /** @brief SNTP time synchronization notification callback. * @param tv Pointer to the synchronized time value @@ -83,7 +81,7 @@ static void TimeManager_SNTP_Sync_Callback(struct timeval *tv) if (_TimeManager_State.hasRTC) { esp_err_t Error; - Error = RTC_SetTime(&Timeinfo); + Error = DevicesManager_SetTime(&Timeinfo); if (Error == ESP_OK) { _TimeManager_State.lastRTC_Backup = Now; ESP_LOGD(TAG, "Time backed up to RTC"); @@ -123,7 +121,7 @@ static void TimeManager_Sync_Timer_Callback(void *p_Arg) struct tm Timeinfo; localtime_r(&Now, &Timeinfo); - if (RTC_SetTime(&Timeinfo) == ESP_OK) { + if (DevicesManager_SetTime(&Timeinfo) == ESP_OK) { ESP_LOGD(TAG, "Periodic RTC backup"); _TimeManager_State.lastRTC_Backup = Now; @@ -136,6 +134,7 @@ static void TimeManager_Sync_Timer_Callback(void *p_Arg) esp_err_t TimeManager_Init(void *p_RTC_Handle) { esp_err_t Error; + struct tm RtcTime; if (_TimeManager_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); @@ -146,43 +145,34 @@ esp_err_t TimeManager_Init(void *p_RTC_Handle) memset(&_TimeManager_State, 0, sizeof(TimeManager_State_t)); - /* Store RTC handle if available */ - if (p_RTC_Handle != NULL) { - esp_err_t RtcError; - struct tm RtcTime; - - _TimeManager_State.RTC_Handle = *(i2c_master_dev_handle_t *)p_RTC_Handle; - _TimeManager_State.hasRTC = true; - ESP_LOGD(TAG, "RTC available for time backup"); - - /* Try to load time from RTC */ - RtcError = RTC_GetTime(&RtcTime); - if (RtcError == ESP_OK) { - /* Validate RTC time (check if year is reasonable) */ - if ((RtcTime.tm_year + 1900) >= TIME_MANAGER_VALID_YEAR_MIN) { - /* Set system time from RTC */ - time_t T = mktime(&RtcTime); - struct timeval Tv = {.tv_sec = T, .tv_usec = 0}; - - settimeofday(&Tv, NULL); - - _TimeManager_State.activeSource = TIME_SOURCE_RTC; - _TimeManager_State.timeSynchronized = true; - _TimeManager_State.lastRTC_Sync = T; - _TimeManager_State.rtcSyncCount++; - - ESP_LOGD(TAG, "System time initialized from RTC: %04d-%02d-%02d %02d:%02d:%02d", - RtcTime.tm_year + 1900, RtcTime.tm_mon + 1, RtcTime.tm_mday, - RtcTime.tm_hour, RtcTime.tm_min, RtcTime.tm_sec); - } else { - ESP_LOGW(TAG, "RTC time invalid (year: %d), waiting for SNTP", - RtcTime.tm_year + 1900); - } + _TimeManager_State.hasRTC = true; + ESP_LOGD(TAG, "RTC available for time backup"); + + /* Try to load time from RTC */ + Error = DevicesManager_GetTime(&RtcTime); + if (Error == ESP_OK) { + /* Validate RTC time (check if year is reasonable) */ + if ((RtcTime.tm_year + 1900) >= TIME_MANAGER_VALID_YEAR_MIN) { + /* Set system time from RTC */ + time_t T = mktime(&RtcTime); + struct timeval Tv = {.tv_sec = T, .tv_usec = 0}; + + settimeofday(&Tv, NULL); + + _TimeManager_State.activeSource = TIME_SOURCE_RTC; + _TimeManager_State.timeSynchronized = true; + _TimeManager_State.lastRTC_Sync = T; + _TimeManager_State.rtcSyncCount++; + + ESP_LOGD(TAG, "System time initialized from RTC: %04d-%02d-%02d %02d:%02d:%02d", + RtcTime.tm_year + 1900, RtcTime.tm_mon + 1, RtcTime.tm_mday, + RtcTime.tm_hour, RtcTime.tm_min, RtcTime.tm_sec); } else { - ESP_LOGW(TAG, "Failed to read time from RTC: %d!", RtcError); + ESP_LOGW(TAG, "RTC time invalid (year: %d), waiting for SNTP", + RtcTime.tm_year + 1900); } } else { - ESP_LOGD(TAG, "No RTC available, SNTP will be primary time source"); + ESP_LOGW(TAG, "Failed to read time from RTC: %d!", Error); } /* Set timezone to UTC by default */ @@ -201,6 +191,7 @@ esp_err_t TimeManager_Init(void *p_RTC_Handle) Error = esp_timer_create(&TimerArgs, &_TimeManager_State.syncTimer); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to create sync timer: %d!", Error); + return Error; } @@ -208,7 +199,9 @@ esp_err_t TimeManager_Init(void *p_RTC_Handle) Error = esp_timer_start_periodic(_TimeManager_State.syncTimer, 60 * 1000000ULL); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to start sync timer: %d!", Error); + esp_timer_delete(_TimeManager_State.syncTimer); + return Error; } @@ -255,12 +248,13 @@ esp_err_t TimeManager_OnNetworkConnected(void) /* Restart SNTP to immediately try to sync time */ esp_sntp_restart(); } else { + ESP_LOGD(TAG, "SNTP initialized"); + /* First time init */ esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); esp_sntp_setservername(0, "pool.ntp.org"); sntp_set_time_sync_notification_cb(TimeManager_SNTP_Sync_Callback); esp_sntp_init(); - ESP_LOGD(TAG, "SNTP initialized"); } return ESP_OK; diff --git a/main/Application/Manager/Time/timeManager.h b/main/Application/Manager/Time/timeManager.h index be4d056..c294d8d 100644 --- a/main/Application/Manager/Time/timeManager.h +++ b/main/Application/Manager/Time/timeManager.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Unified time management with SNTP and RTC backup. + * File info: Time Manager definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,11 +24,7 @@ #ifndef TIME_MANAGER_H_ #define TIME_MANAGER_H_ -#include -#include -#include - -#include "time_types.h" +#include "timeTypes.h" /** @brief Time source types. */ @@ -52,73 +48,137 @@ typedef struct { } TimeManager_Status_t; /** @brief Initialize the Time Manager. + * Initializes time management subsystem with RTC as backup time source + * and prepares SNTP synchronization (starts when network connected). + * @note Call this after DevicesManager_Init() for RTC support. + * SNTP starts automatically when network connects. + * Default timezone is UTC - use TimeManager_SetTimezone(). * @param p_RTC_Handle Pointer to RTC device handle (NULL if RTC not available) * @return ESP_OK on success + * ESP_ERR_NO_MEM if memory allocation fails + * ESP_FAIL if initialization fails */ esp_err_t TimeManager_Init(void *p_RTC_Handle); -/** @brief Deinitialize the Time Manager. - * @return ESP_OK on success +/** @brief Deinitialize the Time Manager. + * Stops SNTP synchronization and frees all allocated resources. + * @note Time functions become unavailable after this. + * System time reverts to 1970-01-01 00:00:00 UTC. + * @return ESP_OK on success + * ESP_FAIL if cleanup fails */ esp_err_t TimeManager_Deinit(void); -/** @brief Called when network connection is established. - * Starts SNTP synchronization. - * @return ESP_OK on success +/** @brief Called when network connection is established. + * Starts SNTP synchronization to obtain accurate time from internet. + * Time is automatically synced to system clock and RTC. + * @note This is called automatically by NetworkManager. + * SNTP sync happens periodically (typically every hour). + * First sync may take a few seconds. + * @return ESP_OK on success + * ESP_FAIL if SNTP start fails */ esp_err_t TimeManager_OnNetworkConnected(void); -/** @brief Called when network connection is lost. - * Switches to RTC as time source. - * @return ESP_OK on success +/** @brief Called when network connection is lost. + * Stops SNTP synchronization and switches to RTC as backup time source. + * System time continues from last synchronized value. + * @note This is called automatically by NetworkManager. + * RTC maintains time accuracy (typical drift: ±20ppm). + * @return ESP_OK on success + * ESP_FAIL if operation fails */ esp_err_t TimeManager_OnNetworkDisconnected(void); -/** @brief Get the current time (from best available source). - * @param p_Time Pointer to store the time - * @param p_Source Optional pointer to store the time source +/** @brief Get the current time from best available source. + * Returns current time from the most reliable source available: + * Priority: SNTP (if connected) > RTC > System clock + * @note Time is in configured timezone (default: UTC). + * p_Source helps determine time reliability. + * @param p_Time Pointer to tm structure to store the time + * @param p_Source Optional pointer to store the time source used (can be NULL) * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Time is NULL + * ESP_ERR_INVALID_STATE if no time source available */ esp_err_t TimeManager_GetTime(struct tm *p_Time, TimeManager_Source_t *p_Source); /** @brief Get the current time as UNIX timestamp. - * @param p_Time Pointer to store the timestamp - * @param p_Source Optional pointer to store the time source + * Returns seconds since 1970-01-01 00:00:00 UTC (UNIX epoch). + * @note Timestamp is always in UTC regardless of timezone setting. + * Useful for time calculations and comparisons. + * @param p_Time Pointer to store the timestamp (time_t) + * @param p_Source Optional pointer to store the time source used (can be NULL) * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Time is NULL + * ESP_ERR_INVALID_STATE if no time source available */ esp_err_t TimeManager_GetTimestamp(time_t *p_Time, TimeManager_Source_t *p_Source); -/** @brief Get the time manager status. - * @param p_Status Pointer to store the status +/** @brief Get the time manager status and statistics. + * Returns detailed status including active source, availability of + * SNTP/RTC, last sync times, and sync counters. + * @note Useful for diagnostics and status display. + * Shows which time sources are available and when last synced. + * @param p_Status Pointer to TimeManager_Status_t structure to populate * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Status is NULL */ esp_err_t TimeManager_GetStatus(TimeManager_Status_t *p_Status); -/** @brief Force a time synchronization from SNTP (if available). - * @return ESP_OK on success +/** @brief Force a time synchronization from SNTP. + * Immediately triggers an SNTP query to synchronize system time. + * Only works when network is connected. + * @note Sync happens asynchronously - may take several seconds. + * System time is updated automatically when sync completes. + * RTC is also updated with synchronized time. + * @return ESP_OK if sync request initiated + * ESP_ERR_INVALID_STATE if network not connected + * ESP_FAIL if SNTP not available */ esp_err_t TimeManager_ForceSync(void); -/** @brief Check if time is synchronized and reliable. - * @return true if time is synchronized from SNTP or RTC +/** @brief Check if time is synchronized and reliable. + * Returns true if time has been synchronized from SNTP or is being + * maintained by RTC. False if only system clock (unreliable). + * @note Use this to determine if timestamps can be trusted. + * Time is reliable after first SNTP sync or RTC read. + * @return true if time is synchronized from SNTP or RTC + * false if time is from unsynchronized system clock */ bool TimeManager_IsTimeSynchronized(void); /** @brief Format the current time as string. - * @param p_Buffer Buffer to store the formatted time - * @param Size Buffer size - * @param Format Time format string (strftime format) + * Formats current time using strftime() format string. Useful for + * display and logging purposes. + * @note Time is formatted in configured timezone. + * Common formats: ISO 8601: "%Y-%m-%dT%H:%M:%S%z" + * @param p_Buffer Buffer to store the formatted time string + * @param Size Buffer size in bytes (including null terminator) + * @param Format Time format string in strftime() format + * Examples: "%Y-%m-%d %H:%M:%S", "%A, %B %d, %Y" * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Buffer or Format is NULL + * ESP_ERR_INVALID_ARG if Size is 0 + * ESP_ERR_INVALID_STATE if no time source available */ esp_err_t TimeManager_GetTimeString(char *p_Buffer, size_t Size, const char *Format); /** @brief Set the timezone for time display. + * Configures the timezone used for local time display. System time + * is stored in UTC internally and converted for display. + * @note Format: std offset [dst [offset],start[/time],end[/time]] + * Changes take effect immediately for all time queries. + * Default timezone is UTC if not set. * @param p_Timezone Timezone string in POSIX format * Examples: - * - "UTC-0" for UTC + * - "UTC+0" or "UTC-0" for UTC * - "CET-1CEST,M3.5.0,M10.5.0/3" for Central European Time * - "EST5EDT,M3.2.0,M11.1.0" for US Eastern Time + * - "JST-9" for Japan Standard Time * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Timezone is NULL + * ESP_FAIL if timezone string is invalid */ esp_err_t TimeManager_SetTimezone(const char *p_Timezone); diff --git a/main/Application/Manager/Time/time_types.h b/main/Application/Manager/Time/timeTypes.h similarity index 87% rename from main/Application/Manager/Time/time_types.h rename to main/Application/Manager/Time/timeTypes.h index b5a308a..e2edf03 100644 --- a/main/Application/Manager/Time/time_types.h +++ b/main/Application/Manager/Time/timeTypes.h @@ -1,9 +1,9 @@ /* - * time_types.h + * timeTypes.h * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Time Manager event types and definitions. + * File info: Common type definitions for the Time Manager component. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,8 +24,15 @@ #ifndef TIME_TYPES_H_ #define TIME_TYPES_H_ +#include #include +#include + +#include +#include +#include + /** @brief Time Manager events base. */ ESP_EVENT_DECLARE_BASE(TIME_EVENTS); diff --git a/main/Application/Manager/USB/descriptors.cpp b/main/Application/Manager/USB/descriptors.cpp new file mode 100644 index 0000000..a64c0c8 --- /dev/null +++ b/main/Application/Manager/USB/descriptors.cpp @@ -0,0 +1,46 @@ +/* + * descriptors.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: USB Descriptors implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include "descriptors.h" + +static tusb_desc_device_t const Desc_Device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, // USB 2.0 + .bDeviceClass = 0x00, // Defined in interface descriptor + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = CONFIG_USB_VID, + .idProduct = CONFIG_USB_PID, + .bcdDevice = 0x0100, // Device release 1.0 + .iManufacturer = 0x01, // Index of manufacturer string + .iProduct = 0x02, // Index of product string + .iSerialNumber = 0x03, // Index of serial number string + .bNumConfigurations = 0x01, // One configuration +}; + +uint8_t const *get_Desc_Device(void) +{ + return (uint8_t const *)&Desc_Device; +} \ No newline at end of file diff --git a/main/Application/Manager/USB/descriptors.h b/main/Application/Manager/USB/descriptors.h new file mode 100644 index 0000000..8214fa4 --- /dev/null +++ b/main/Application/Manager/USB/descriptors.h @@ -0,0 +1,45 @@ +/* + * descriptors.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: USB Descriptors definition. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef DESCRIPTORS_H_ +#define DESCRIPTORS_H_ + +#include + +/** @brief String Descriptor Index + */ +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_UVC_CONTROL, + STRID_UVC_STREAMING, +}; + +/** @brief Get the device descriptor. This is used by the USB Manager to provide the device descriptor to TinyUSB. + * @return Pointer to the device descriptor structure. + */ +uint8_t const *get_Desc_Device(void); + +#endif /* DESCRIPTORS_H_ */ diff --git a/main/Application/Manager/USB/usbManager.cpp b/main/Application/Manager/USB/usbManager.cpp new file mode 100644 index 0000000..e2c7b1e --- /dev/null +++ b/main/Application/Manager/USB/usbManager.cpp @@ -0,0 +1,332 @@ +/* + * usbManager.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: USB Manager implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "usbManager.h" +#include "descriptors.h" +#include "../Memory/memoryManager.h" + +ESP_EVENT_DEFINE_BASE(USB_EVENTS); + +static const char *TAG = "USB-Manager"; + +/** @brief USB Manager internal state. + */ +typedef struct { + bool isInitialized; /**< Initialization state. */ + bool isDeinitializing; /**< Deinitialization in progress. */ + bool isUSBMounted; /**< USB host has mounted device. */ + USB_Manager_Config_t Config; /**< Current configuration. */ + tinyusb_msc_storage_handle_t Storage; /**< Storage handle. */ + TaskHandle_t DeinitTask; /**< Deinit task handle. */ + tusb_desc_device_t DeviceDescriptor; /**< Custom device descriptor. */ + const char *StringDescriptors[4]; /**< String descriptor pointers. */ +} USB_Manager_State_t; + +static USB_Manager_State_t _USB_Manager_State; + +esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) +{ + esp_err_t Error; + + if (p_Config == NULL) { + ESP_LOGE(TAG, "Invalid configuration pointer!"); + + return ESP_ERR_INVALID_ARG; + } else if (_USB_Manager_State.isInitialized) { + ESP_LOGW(TAG, "USB Manager already initialized!"); + + return ESP_ERR_INVALID_STATE; + } else if (p_Config->MountPoint == NULL) { + ESP_LOGE(TAG, "Mount point is NULL!"); + + return ESP_ERR_INVALID_ARG; + } + + /* Wait for any pending deinitialization to complete */ + if (_USB_Manager_State.isDeinitializing) { + ESP_LOGD(TAG, "Waiting for previous deinit to complete..."); + + uint8_t WaitCount = 0; + while ((_USB_Manager_State.isDeinitializing) && (WaitCount < 100)) { + vTaskDelay(100 / portTICK_PERIOD_MS); + WaitCount++; + } + + if (_USB_Manager_State.isDeinitializing) { + ESP_LOGE(TAG, "Previous deinit still running - cannot initialize!"); + + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGD(TAG, "Previous deinit completed, proceeding with init"); + + /* Additional delay to ensure cleanup is complete */ + vTaskDelay(500 / portTICK_PERIOD_MS); + } + + /* Detect active storage type from MemoryManager */ + MemoryManager_Location_t StorageLocation = MemoryManager_GetStorageLocation(); + const char *p_StorageTypeName = (StorageLocation == MEMORY_LOCATION_SD_CARD) ? "SD Card (FAT32)" : + "Internal Flash (FAT32)"; + + ESP_LOGD(TAG, "Initializing USB Manager..."); + + memset(&_USB_Manager_State, 0, sizeof(USB_Manager_State_t)); + + ESP_LOGD(TAG, " Storage type: %s (auto-detected)", p_StorageTypeName); + ESP_LOGD(TAG, " Mount point: %s", p_Config->MountPoint); + + /* Lock filesystem for USB access */ + Error = MemoryManager_LockFilesystem(); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to lock filesystem: %d!", Error); + } + + memcpy(&_USB_Manager_State.Config, p_Config, sizeof(USB_Manager_Config_t)); + + /* Configure the Device Descriptor */ + memcpy(&_USB_Manager_State.DeviceDescriptor, get_Desc_Device(), sizeof(tusb_desc_device_t)); + + /* Configure the String Descriptors */ + _USB_Manager_State.StringDescriptors[0] = NULL; // 0: Language (set by TinyUSB) + _USB_Manager_State.StringDescriptors[1] = p_Config->Manufacturer; // 1: Manufacturer + _USB_Manager_State.StringDescriptors[2] = p_Config->Product; // 2: Product + _USB_Manager_State.StringDescriptors[3] = p_Config->SerialNumber; // 3: Serial Number + + ESP_LOGD(TAG, "USB Descriptors:"); + ESP_LOGD(TAG, " VID:PID = 0x%04X:0x%04X", _USB_Manager_State.DeviceDescriptor.idVendor, + _USB_Manager_State.DeviceDescriptor.idProduct); + ESP_LOGD(TAG, " Manufacturer: %s", p_Config->Manufacturer ? p_Config->Manufacturer : "(null)"); + ESP_LOGD(TAG, " Product: %s", p_Config->Product ? p_Config->Product : "(null)"); + ESP_LOGD(TAG, " Serial: %s", p_Config->SerialNumber ? p_Config->SerialNumber : "(null)"); + + ESP_LOGD(TAG, "Initializing TinyUSB..."); + + tinyusb_config_t USB_Config = TINYUSB_DEFAULT_CONFIG(); + + /* Override with custom descriptors */ + USB_Config.descriptor.device = &_USB_Manager_State.DeviceDescriptor; + USB_Config.descriptor.string = _USB_Manager_State.StringDescriptors; + USB_Config.descriptor.string_count = 4; + + Error = tinyusb_driver_install(&USB_Config); + if (Error != ESP_OK) { + if (Error == ESP_ERR_INVALID_STATE) { + ESP_LOGD(TAG, "TinyUSB driver already installed, reusing..."); + } else { + ESP_LOGE(TAG, "Failed to install TinyUSB driver: %d!", Error); + + return Error; + } + } + + /* Clean up old storage handle if it still exists from previous session */ + if (_USB_Manager_State.Storage != NULL) { + ESP_LOGD(TAG, "Cleaning up old storage handle from previous session..."); + + Error = tinyusb_msc_delete_storage(_USB_Manager_State.Storage); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to delete old storage: %d (continuing anyway)!", Error); + } + + _USB_Manager_State.Storage = NULL; + + vTaskDelay(200 / portTICK_PERIOD_MS); + } + + /* Initialize MSC storage based on detected storage location */ + if (StorageLocation == MEMORY_LOCATION_SD_CARD) { + sdmmc_card_t *p_Card = NULL; + + /* Configure SD card MSC */ + ESP_LOGD(TAG, "Configuring SD Card MSC..."); + + /* Get SD card handle from MemoryManager */ + Error = MemoryManager_GetSDCardHandle(&p_Card); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to get SD card handle: %d!", Error); + + return Error; + } + + ESP_LOGD(TAG, "Using SD card from MemoryManager"); + + tinyusb_msc_storage_config_t Storage_Config; + memset(&Storage_Config, 0, sizeof(tinyusb_msc_storage_config_t)); + Storage_Config.medium.card = p_Card; + + Error = tinyusb_msc_new_storage_sdmmc(&Storage_Config, &_USB_Manager_State.Storage); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to create SD card storage: %d!", Error); + + return Error; + } + } else if (StorageLocation == MEMORY_LOCATION_INTERNAL) { + wl_handle_t WL_Handle; + + /* Configure SPI flash (FAT32 with Wear Leveling) MSC */ + ESP_LOGD(TAG, "Configuring internal flash MSC..."); + + /* Get existing wear leveling handle from MemoryManager */ + Error = MemoryManager_GetWearLevelingHandle(&WL_Handle); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to get wear leveling handle: %d!", Error); + + return Error; + } + + ESP_LOGD(TAG, "Using existing wear leveling handle: %d", WL_Handle); + + tinyusb_msc_storage_config_t Storage_Config; + memset(&Storage_Config, 0, sizeof(tinyusb_msc_storage_config_t)); + Storage_Config.medium.wl_handle = WL_Handle; + + Error = tinyusb_msc_new_storage_spiflash(&Storage_Config, &_USB_Manager_State.Storage); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to create internal flash storage: %d!", Error); + + return Error; + } + } else { + ESP_LOGE(TAG, "Unknown storage location: %d!", StorageLocation); + + return ESP_ERR_INVALID_ARG; + } + + ESP_LOGD(TAG, "USB Mass Storage Device ready"); + ESP_LOGD(TAG, " WARNING: Do not access filesystem from application while USB is connected!"); + + ESP_LOGI(TAG, "Connecting to USB bus..."); + if (tud_connect()) { + ESP_LOGI(TAG, "USB connection established"); + } else { + ESP_LOGW(TAG, "tud_connect() returned false (may already be connected)"); + } + + _USB_Manager_State.isInitialized = true; + + esp_event_post(USB_EVENTS, USB_EVENT_INITIALIZED, NULL, 0, portMAX_DELAY); + + /* Assume mounted after successful init */ + _USB_Manager_State.isUSBMounted = true; + + return ESP_OK; +} + +/** @brief Background task for safe USB deinitialization. + * @note This task runs the deinitialization sequence asynchronously + * to avoid blocking the GUI task during the lengthy USB shutdown. + * Storage is NOT deleted to prevent crashes from pending USB callbacks. + * @param p_Param Task parameters (unused) + */ +static void Task_USB_Deinit(void *p_Param) +{ + esp_err_t Error; + + ESP_LOGD(TAG, "USB deinit task started"); + + ESP_LOGI(TAG, "Disconnecting from USB bus..."); + if (tud_disconnect()) { + ESP_LOGI(TAG, "USB disconnect initiated successfully"); + } else { + ESP_LOGW(TAG, "Failed to initiate USB disconnect"); + } + + vTaskDelay(500 / portTICK_PERIOD_MS); + + ESP_LOGD(TAG, "Storage kept alive to prevent callback crashes"); + + Error = MemoryManager_UnlockFilesystem(); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "Failed to unlock filesystem: %d!", Error); + } else { + ESP_LOGD(TAG, "Filesystem unlocked for application"); + } + + _USB_Manager_State.isDeinitializing = false; + _USB_Manager_State.DeinitTask = NULL; + + esp_event_post(USB_EVENTS, USB_EVENT_UNINITIALIZED, NULL, 0, portMAX_DELAY); + + ESP_LOGD(TAG, "USB Manager deinitialized successfully"); + + vTaskDelete(NULL); +} + +esp_err_t USBManager_Deinit(void) +{ + if (_USB_Manager_State.isInitialized == false) { + ESP_LOGW(TAG, "USB Manager not initialized!"); + + return ESP_ERR_INVALID_STATE; + } else if (_USB_Manager_State.isDeinitializing) { + ESP_LOGW(TAG, "USB Manager is already deinitializing!"); + + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGD(TAG, "Starting USB deinitialization..."); + + _USB_Manager_State.isInitialized = false; + _USB_Manager_State.isDeinitializing = true; + + /* Create background task to handle the lengthy USB shutdown process */ + BaseType_t Result = xTaskCreate( + Task_USB_Deinit, + "Task_USB_Deinit", + 4096, + NULL, + 1, + &_USB_Manager_State.DeinitTask + ); + + if (Result != pdPASS) { + ESP_LOGE(TAG, "Failed to create USB deinit task!"); + + _USB_Manager_State.isDeinitializing = false; + _USB_Manager_State.isInitialized = true; + + return ESP_FAIL; + } + + ESP_LOGD(TAG, "USB deinitialization task started (async)"); + + return ESP_OK; +} + +bool USBManager_IsInitialized(void) +{ + return _USB_Manager_State.isInitialized; +} diff --git a/main/Application/Manager/USB/usbManager.h b/main/Application/Manager/USB/usbManager.h new file mode 100644 index 0000000..43b288c --- /dev/null +++ b/main/Application/Manager/USB/usbManager.h @@ -0,0 +1,62 @@ +/* + * usbManager.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: USB Manager definition. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef USB_MANAGER_H_ +#define USB_MANAGER_H_ + +#include "usbTypes.h" + +/** @brief Initialize the USB Manager and expose storage as USB Mass Storage Device. + * This function initializes the TinyUSB stack, configures the USB descriptors, + * and exposes the specified storage media (SD card or LittleFS) as a USB MSC device. + * The storage must be mounted before calling this function. + * @note Storage must be mounted at p_Config->p_MountPoint before calling this function. + * This function blocks and starts the TinyUSB task. + * @warning While USB MSC is active, the filesystem should not be accessed from the application + * to avoid data corruption. The PC has exclusive access. + * Not thread-safe during initialization. Call once from main task. + * @param p_Config Pointer to USB manager configuration structure + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Config is NULL or contains invalid parameters + * ESP_ERR_INVALID_STATE if already initialized + * ESP_FAIL if USB initialization fails + */ +esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config); + +/** @brief Deinitialize the USB Manager and stop USB Mass Storage Device. + * Stops the TinyUSB stack and releases all resources. After calling this function, + * the storage is no longer accessible via USB. + * @note After deinitializing, the filesystem can be safely accessed by the application again. + * @warning Ensure the PC has safely ejected the USB drive before calling this function. + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not initialized + */ +esp_err_t USBManager_Deinit(void); + +/** @brief Check if USB Manager is initialized and active. + * @return true if USB MSC is active + * false if not initialized + */ +bool USBManager_IsInitialized(void); + +#endif /* USB_MANAGER_H_ */ diff --git a/main/Application/Manager/USB/usbTypes.h b/main/Application/Manager/USB/usbTypes.h new file mode 100644 index 0000000..b39e5f6 --- /dev/null +++ b/main/Application/Manager/USB/usbTypes.h @@ -0,0 +1,53 @@ +/* + * usbTypes.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Common type definitions for the USB Manager component. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef USB_TYPES_H_ +#define USB_TYPES_H_ + +#include +#include + +#include + +/** @brief USB Manager events base. + */ +ESP_EVENT_DECLARE_BASE(USB_EVENTS); + +/** @brief USB Manager event IDs. + */ +typedef enum { + USB_EVENT_INITIALIZED, /**< USB subsystem initialized and ready. */ + USB_EVENT_UNINITIALIZED /**< USB subsystem uninitialized and stopped. */ +} USB_Event_ID_t; + +/** @brief USB Manager configuration structure. + * @note Storage type is automatically detected from MemoryManager. + */ +typedef struct { + const char *MountPoint; /**< Mount point of the storage (must match MemoryManager mount point). */ + char *Manufacturer; /**< USB manufacturer string. */ + char *Product; /**< USB product name string. */ + char *SerialNumber; /**< USB serial number string. */ +} USB_Manager_Config_t; + +#endif /* USB_TYPES_H_ */ diff --git a/main/Application/Manager/managers.h b/main/Application/Manager/managers.h index 901698b..3e1f970 100644 --- a/main/Application/Manager/managers.h +++ b/main/Application/Manager/managers.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: + * File info: Central header for all manager modules (Network, Devices, Time, Memory, Settings). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,8 @@ #include "Network/networkManager.h" #include "Devices/devicesManager.h" #include "Time/timeManager.h" -#include "SD/sdManager.h" +#include "Memory/memoryManager.h" #include "Settings/settingsManager.h" +#include "USB/usbManager.h" #endif /* MANAGERS_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/Camera/cameraTask.cpp b/main/Application/Tasks/Camera/cameraTask.cpp new file mode 100644 index 0000000..d97e10c --- /dev/null +++ b/main/Application/Tasks/Camera/cameraTask.cpp @@ -0,0 +1,179 @@ +/* + * cameraTask.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Camera task implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "cameraTask.h" +#include "Application/application.h" + +#define CAMERA_TASK_STOP_REQUEST BIT0 + +ESP_EVENT_DEFINE_BASE(CAMERA_EVENTS); + +typedef struct { + bool isInitialized; + bool isRunning; + TaskHandle_t TaskHandle; + EventGroupHandle_t EventGroup; +} Camera_Task_State_t; + +static Camera_Task_State_t _Camera_Task_State; + +static const char *TAG = "cameraTask"; + +/** @brief Camera task main loop. + * @param p_Parameters Pointer to App_Context_t structure + */ +static void Task_Camera(void *p_Parameters) +{ + esp_task_wdt_add(NULL); + + ESP_LOGD(TAG, "Camera task started on core %d", xPortGetCoreID()); + + while (_Camera_Task_State.isRunning) { + + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + ESP_LOGD(TAG, "Camera task shutting down"); + //CameraManager_Deinit(); + + _Camera_Task_State.TaskHandle = NULL; + + esp_task_wdt_delete(NULL); + vTaskDelete(NULL); +} + +esp_err_t Camera_Task_Init(void) +{ + esp_err_t Error; + + Error = ESP_OK; + + if (_Camera_Task_State.isInitialized) { + ESP_LOGW(TAG, "Already initialized"); + + return ESP_OK; + } + + /* Create event group */ + _Camera_Task_State.EventGroup = xEventGroupCreate(); + if (_Camera_Task_State.EventGroup == NULL) { + ESP_LOGE(TAG, "Failed to create event group!"); + + return ESP_ERR_NO_MEM; + } + + //Error = CameraManager_Init(); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize Camera Manager: 0x%x!", Error); + + return Error; + } + + _Camera_Task_State.isInitialized = true; + + return ESP_OK; +} + +void Camera_Task_Deinit(void) +{ + if (_Camera_Task_State.isInitialized == false) { + return; + } + + //CameraManager_Deinit(); + + if (_Camera_Task_State.EventGroup != NULL) { + vEventGroupDelete(_Camera_Task_State.EventGroup); + _Camera_Task_State.EventGroup = NULL; + } + + _Camera_Task_State.isInitialized = false; + + return; +} + +esp_err_t Camera_Task_Start(App_Context_t *p_AppContext) +{ + BaseType_t ret; + + if (p_AppContext == NULL) { + return ESP_ERR_INVALID_ARG; + } else if (_Camera_Task_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } else if (_Camera_Task_State.isRunning) { + ESP_LOGW(TAG, "Task already running"); + return ESP_OK; + } + + _Camera_Task_State.isRunning = true; + + ESP_LOGD(TAG, "Starting Camera Task"); + + ret = xTaskCreatePinnedToCore( + Task_Camera, + "Task_Camera", + CONFIG_CAMERA_TASK_STACKSIZE, + p_AppContext, + CONFIG_CAMERA_TASK_PRIO, + &_Camera_Task_State.TaskHandle, + CONFIG_CAMERA_TASK_CORE + ); + + if (ret != pdPASS) { + ESP_LOGE(TAG, "Failed to create Camera Task: %d!", ret); + + return ESP_ERR_NO_MEM; + } + + return ESP_OK; +} + +esp_err_t Camera_Task_Stop(void) +{ + if (_Camera_Task_State.isRunning == false) { + return ESP_OK; + } + + ESP_LOGD(TAG, "Stopping Camera Task"); + + xEventGroupSetBits(_Camera_Task_State.EventGroup, CAMERA_TASK_STOP_REQUEST); + + return ESP_OK; +} + +bool Camera_Task_IsRunning(void) +{ + return _Camera_Task_State.isRunning; +} \ No newline at end of file diff --git a/main/Application/Tasks/Camera/cameraTask.h b/main/Application/Tasks/Camera/cameraTask.h new file mode 100644 index 0000000..6e2b51f --- /dev/null +++ b/main/Application/Tasks/Camera/cameraTask.h @@ -0,0 +1,58 @@ +/* + * cameraTask.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Camera task definition. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef CAMERA_TASK_H_ +#define CAMERA_TASK_H_ + +#include +#include + +#include + +#include "Application/application.h" + +/** @brief Initializes the camera task. + * @return ESP_OK on success, error code otherwise + */ +esp_err_t Camera_Task_Init(void); + +/** @brief Deinitializes the camera task. + */ +void Camera_Task_Deinit(void); + +/** @brief Starts the camera task. + * @return ESP_OK on success, error code otherwise + */ +esp_err_t Camera_Task_Start(App_Context_t *p_AppContext); + +/** @brief Stops the camera task. + * @return ESP_OK on success, error code otherwise + */ +esp_err_t Camera_Task_Stop(void); + +/** @brief Checks if the camera task is running. + * @return false if the task is not running, true if it is running + */ +bool Camera_Task_IsRunning(void); + +#endif /* CAMERA_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/Devices/devicesTask.cpp b/main/Application/Tasks/Devices/devicesTask.cpp index 5c0a71e..f2fb3ff 100644 --- a/main/Application/Tasks/Devices/devicesTask.cpp +++ b/main/Application/Tasks/Devices/devicesTask.cpp @@ -35,7 +35,7 @@ #include "devicesTask.h" #include "Application/application.h" -#include "Application/Manager/Time/time_types.h" +#include "Application/Manager/Time/timeTypes.h" #define DEVICES_TASK_STOP_REQUEST BIT0 #define DEVICES_TASK_TIME_SYNCED BIT1 @@ -52,9 +52,9 @@ typedef struct { struct timeval TimeOfDay; } Devices_Task_State_t; -static Devices_Task_State_t _DevicesTask_State; +static Devices_Task_State_t _Devices_Task_State; -static const char *TAG = "devices_task"; +static const char *TAG = "Devices-Task"; /** @brief Event handler for GUI events. * @param p_HandlerArgs Handler argument @@ -67,7 +67,7 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int ESP_LOGD(TAG, "GUI event received: ID=%d", ID); } -/** @brief Devices task main loop. +/** @brief Devices task main loop. * @param p_Parameters Pointer to App_Context_t structure */ static void Task_Devices(void *p_Parameters) @@ -78,25 +78,25 @@ static void Task_Devices(void *p_Parameters) ESP_LOGD(TAG, "Devices task started on core %d", xPortGetCoreID()); - while (_DevicesTask_State.isRunning) { + while (_Devices_Task_State.isRunning) { EventBits_t EventBits; esp_task_wdt_reset(); - EventBits = xEventGroupGetBits(_DevicesTask_State.EventGroup); + EventBits = xEventGroupGetBits(_Devices_Task_State.EventGroup); if (EventBits & DEVICES_TASK_STOP_REQUEST) { ESP_LOGD(TAG, "Stop request received"); - _DevicesTask_State.isRunning = false; + _Devices_Task_State.isRunning = false; - xEventGroupClearBits(_DevicesTask_State.EventGroup, DEVICES_TASK_STOP_REQUEST); + xEventGroupClearBits(_Devices_Task_State.EventGroup, DEVICES_TASK_STOP_REQUEST); break; } Now = esp_timer_get_time() / 1000; - if ((Now - _DevicesTask_State.LastBatteryUpdate) >= 1000) { + if ((Now - _Devices_Task_State.LastBatteryUpdate) >= 1000) { App_Devices_Battery_t BatteryInfo; ESP_LOGD(TAG, "Updating battery voltage..."); @@ -107,7 +107,7 @@ static void Task_Devices(void *p_Parameters) ESP_LOGE(TAG, "Failed to read battery voltage!"); } - _DevicesTask_State.LastBatteryUpdate = esp_timer_get_time() / 1000; + _Devices_Task_State.LastBatteryUpdate = esp_timer_get_time() / 1000; } vTaskDelay(10 / portTICK_PERIOD_MS); @@ -116,48 +116,48 @@ static void Task_Devices(void *p_Parameters) ESP_LOGD(TAG, "Devices task shutting down"); DevicesManager_Deinit(); - _DevicesTask_State.TaskHandle = NULL; + _Devices_Task_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); vTaskDelete(NULL); } -/** @brief Initialize the devices task. - * @return ESP_OK on success, error code otherwise - */ -esp_err_t DevicesTask_Init(void) +esp_err_t Devices_Task_Init(void) { esp_err_t Error; - if (_DevicesTask_State.isInitialized) { + if (_Devices_Task_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; } /* Create event group */ - _DevicesTask_State.EventGroup = xEventGroupCreate(); - if (_DevicesTask_State.EventGroup == NULL) { + _Devices_Task_State.EventGroup = xEventGroupCreate(); + if (_Devices_Task_State.EventGroup == NULL) { ESP_LOGE(TAG, "Failed to create event group!"); + return ESP_ERR_NO_MEM; } Error = DevicesManager_Init(); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize Devices Manager: 0x%x!", Error); + return Error; } /* Use the event loop to receive control signals from other tasks */ esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL); - _DevicesTask_State.isInitialized = true; + _Devices_Task_State.isInitialized = true; return ESP_OK; } -void DevicesTask_Deinit(void) +void Devices_Task_Deinit(void) { - if (_DevicesTask_State.isInitialized == false) { + if (_Devices_Task_State.isInitialized == false) { return; } @@ -165,30 +165,31 @@ void DevicesTask_Deinit(void) DevicesManager_Deinit(); - if (_DevicesTask_State.EventGroup != NULL) { - vEventGroupDelete(_DevicesTask_State.EventGroup); - _DevicesTask_State.EventGroup = NULL; + if (_Devices_Task_State.EventGroup != NULL) { + vEventGroupDelete(_Devices_Task_State.EventGroup); + _Devices_Task_State.EventGroup = NULL; } - _DevicesTask_State.isInitialized = false; + _Devices_Task_State.isInitialized = false; return; } -esp_err_t DevicesTask_Start(App_Context_t *p_AppContext) +esp_err_t Devices_Task_Start(App_Context_t *p_AppContext) { BaseType_t ret; if (p_AppContext == NULL) { return ESP_ERR_INVALID_ARG; - } else if (_DevicesTask_State.isInitialized == false) { + } else if (_Devices_Task_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_DevicesTask_State.isRunning) { + } else if (_Devices_Task_State.isRunning) { ESP_LOGW(TAG, "Task already running"); + return ESP_OK; } - _DevicesTask_State.isRunning = true; + _Devices_Task_State.isRunning = true; ESP_LOGD(TAG, "Starting Devices Task"); @@ -198,32 +199,33 @@ esp_err_t DevicesTask_Start(App_Context_t *p_AppContext) CONFIG_DEVICES_TASK_STACKSIZE, p_AppContext, CONFIG_DEVICES_TASK_PRIO, - &_DevicesTask_State.TaskHandle, + &_Devices_Task_State.TaskHandle, CONFIG_DEVICES_TASK_CORE ); if (ret != pdPASS) { ESP_LOGE(TAG, "Failed to create Devices Task: %d!", ret); + return ESP_ERR_NO_MEM; } return ESP_OK; } -esp_err_t DevicesTask_Task_Stop(void) +esp_err_t Devices_Task_Stop(void) { - if (_DevicesTask_State.isRunning == false) { + if (_Devices_Task_State.isRunning == false) { return ESP_OK; } ESP_LOGD(TAG, "Stopping Devices Task"); - xEventGroupSetBits(_DevicesTask_State.EventGroup, DEVICES_TASK_STOP_REQUEST); + xEventGroupSetBits(_Devices_Task_State.EventGroup, DEVICES_TASK_STOP_REQUEST); return ESP_OK; } -bool DevicesTask_Task_isRunning(void) +bool Devices_Task_IsRunning(void) { - return _DevicesTask_State.isRunning; + return _Devices_Task_State.isRunning; } \ No newline at end of file diff --git a/main/Application/Tasks/Devices/devicesTask.h b/main/Application/Tasks/Devices/devicesTask.h index 3eddb6f..3fc14e1 100644 --- a/main/Application/Tasks/Devices/devicesTask.h +++ b/main/Application/Tasks/Devices/devicesTask.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Devices task for peripheral monitoring and management. + * File info: Devices task definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +21,8 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ -#ifndef DEVICESTASK_H_ -#define DEVICESTASK_H_ +#ifndef DEVICES_TASK_H_ +#define DEVICES_TASK_H_ #include #include @@ -34,25 +34,25 @@ /** @brief Initializes the devices task. * @return ESP_OK on success, error code otherwise */ -esp_err_t DevicesTask_Init(void); +esp_err_t Devices_Task_Init(void); /** @brief Deinitializes the devices task. */ -void DevicesTask_Deinit(void); +void Devices_Task_Deinit(void); /** @brief Starts the devices task. * @return ESP_OK on success, error code otherwise */ -esp_err_t DevicesTask_Start(App_Context_t *p_AppContext); +esp_err_t Devices_Task_Start(App_Context_t *p_AppContext); /** @brief Stops the devices task. * @return ESP_OK on success, error code otherwise */ -esp_err_t DevicesTask_Stop(void); +esp_err_t Devices_Task_Stop(void); /** @brief Checks if the devices task is running. * @return false if the task is not running, true if it is running */ -bool DevicesTask_isRunning(void); +bool Devices_Task_IsRunning(void); -#endif /* DEVICESTASK_H_ */ \ No newline at end of file +#endif /* DEVICES_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c b/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c index 4544656..4fcb8b3 100644 --- a/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c +++ b/main/Application/Tasks/GUI/Export/fonts/ui_font_fa.c @@ -17094,8 +17094,7 @@ static const uint16_t unicode_list_30[] = { }; /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = -{ +static const lv_font_fmt_txt_cmap_t cmaps[] = { { .range_start = 32, .range_length = 16, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY diff --git a/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c b/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c index f3cf13a..04881e1 100644 --- a/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c +++ b/main/Application/Tasks/GUI/Export/images/ui_img_logo_80x44_png.c @@ -6,124 +6,124 @@ #include "../ui.h" #ifndef LV_ATTRIBUTE_MEM_ALIGN - #define LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN #endif // IMAGE DATA: assets/Logo_80x44.png const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_logo_80x44_png_data[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0xFD,0x23,0xFD,0x45,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xE4,0xFB,0x40,0xFC,0xA0,0xFC,0x47,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0xFB,0x22,0xFB,0xA0,0xFB,0x00,0xFC,0x80,0xFC,0xCA,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFD,0x23,0xFD,0x43,0xFD,0x43,0xFD,0x4D,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xFA,0xA1,0xFA,0x20,0xFB,0xA0,0xFB,0xE0,0xFB,0x40,0xFC,0xAC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFD,0x00,0xFD,0x00,0xFD,0x20,0xFD,0xEF,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xFC,0xC3,0xF9,0x01,0xFA,0x81,0xFA,0x20,0xFB,0x80,0xFB,0xC0,0xFB,0x00,0xFC,0x87,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0xFC,0xA0,0xFC,0xA0,0xFC,0xE0,0xFC,0xAE,0xFD,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xFA,0x02,0xF9,0x62,0xF9,0xE1,0xF9,0x80,0xFA, - 0x00,0xFB,0x60,0xFB,0xA0,0xFB,0xE0,0xFB,0x64,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0xFC,0x81,0xFC,0x81,0xFC,0xC1,0xFC,0x8F,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0xF9,0x63,0xF8,0xE2,0xF8,0x62,0xF9,0xC1,0xF9,0x60,0xFA,0xE0,0xFA,0x80,0xFB,0xC0,0xFB,0x40,0xFC,0x81,0xFC,0x00,0x00,0xCF,0xFD,0xC7,0xFD,0xE4,0xFD,0x8A,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0xFA,0x84,0xF8,0x03,0xF8,0x63,0xF8,0xE2,0xF8,0x42,0xF9,0xC1,0xF9,0x40,0xFA,0xC0,0xFA,0x60,0xFB,0xA0,0xFB,0x20,0xFC,0x80,0xFC,0xE0,0xFC,0x20,0xFD,0x60,0xFD,0xC1,0xFD,0xC9,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xFD,0xA1,0xFD,0xA1,0xFD,0xA4,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xFC,0xE7,0xF8,0x04,0xF8,0x04,0xF8,0x03,0xF8,0x43,0xF8,0xC2,0xF8,0x41,0xF9,0xC0,0xF9,0x20,0xFA,0x80,0xFA,0xE0,0xFA,0x00,0xFB,0x60,0xFB,0xA0,0xFB,0xA0,0xFC,0xE0,0xFC,0x20,0xFD,0xA1,0xFD,0x0B,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xA6,0xFD,0x80,0xFD,0x60,0xFD,0x63,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xF9,0xAB,0xF8,0x28,0xF8,0x06,0xF8,0x05,0xF8,0x05,0xF8,0x04,0xF8,0x43,0xF8,0xA2,0xF8,0x21,0xF9,0xA0,0xF9,0x00,0xFA, - 0x60,0xFA,0xA0,0xFA,0xC0,0xFA,0x00,0xFB,0x40,0xFB,0x60,0xFC,0xC0,0xFC,0x00,0xFD,0x81,0xFD,0x4D,0xFE,0x00,0x00,0x00,0x00,0x2A,0xFE,0x25,0xFE,0x25,0xFE,0x25,0xFE,0x6D,0xFE,0x87,0xFD,0x41,0xFD,0x21,0xFD,0x23,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xBC,0x5F,0xB3,0x1F,0xC3,0xBF,0xCB,0x3F,0xDC,0x9F,0xF4,0x3D,0xFC,0x7B,0xFB,0x97,0xFA, - 0xD4,0xF9,0x31,0xF9,0xAF,0xF8,0x2E,0xF8,0x0C,0xF8,0x0A,0xF8,0x09,0xF8,0x07,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x43,0xF8,0xA2,0xF8,0x21,0xF9,0xA0,0xF9,0x00,0xFA,0x40,0xFA,0x80,0xFA,0xA0,0xFA,0xC0,0xFA,0xE0,0xFA,0x20,0xFC,0xA0,0xFC,0xE0,0xFC,0x40,0xFD,0x62,0xFC,0xA2,0xFB,0xC2,0xFB,0x81,0xFD,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x67,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,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,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xC3,0xBF,0xC2,0x7F,0xCA,0x1F,0xE2,0x7D,0xF9,0xD9,0xF8,0x76,0xF8,0x53,0xF8,0x31,0xF8,0x0F,0xF8,0x2E,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x62,0xF8,0xE1,0xF8,0x20,0xFA,0x60,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x40,0xFA,0x60,0xFA,0x40,0xFB,0x80,0xFC,0xC0,0xFC,0x00,0xFD,0x20,0xFC,0xA0,0xFB,0xA0,0xFB,0x40,0xFD,0x40,0xFE,0x40,0xFE,0x40,0xFE,0x87,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x7F,0xCB,0x1F,0xE2,0x7E,0xF9,0xFA,0xF8,0x96,0xF8,0x74,0xF8,0x31,0xF8,0x30,0xF8,0x2E,0xF8,0x2D,0xF8,0x2B,0xF8,0x0A,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x61,0xF8,0xA1,0xF8,0x00,0xF9,0xC0,0xF9,0xA0,0xFA,0xC0,0xFA,0x80,0xFA,0x00,0xFA,0x20,0xFA,0x60,0xFA,0x20,0xFC,0x80,0xFC,0xA0,0xFC,0xE0,0xFB,0xA0,0xFB,0xC0,0xFB,0x40,0xFD,0x40,0xFE,0x40,0xFE,0x40,0xFE, - 0x87,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xFD,0x03,0xFD,0x03,0xFD,0xE3,0xFC,0x30,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xEF,0x1F,0xDF,0x7F,0xEF,0x3F,0xDF,0x7F,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xFE,0xFE,0xF9,0x1B,0xF9,0xB7,0xF8,0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x2A,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x41,0xF8,0x00,0xF9,0x80,0xF9,0xC0,0xF9, - 0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x00,0xFA,0x40,0xFA,0x20,0xFB,0x20,0xFB,0x40,0xFB,0x20,0xFC,0xA0,0xFC,0x00,0xFD,0x00,0xFD,0xC0,0xFC,0xE0,0xFC,0x40,0xFD,0xC7,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFC,0xE0,0xFC,0xC0,0xFC,0xC0,0xFC,0x0C,0xFD,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xDF,0xFF,0x7F,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0xDF,0xFF,0xBF,0xF7,0x9F,0xF7,0x9F,0xF7,0xDF,0xFF,0xDE,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xF9,0xD8,0xF8, - 0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x09,0xF8,0x08,0xF8,0x07,0xF8,0x05,0xF8,0xE5,0xFA,0x44,0xFA,0x41,0xF8,0x40,0xF9,0xE0,0xF9,0x44,0xFB,0x85,0xFC,0x60,0xF9,0x80,0xF9,0xA0,0xF9,0xC0,0xF9,0x87,0xFE,0x24,0xFD,0x60,0xFA,0xA0,0xFA,0xE0,0xFB,0xA0,0xFC,0xE0,0xFC,0xC0,0xFC,0xA0,0xFC,0xC0,0xFC,0x20,0xFD,0x84,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0xFC,0xA0,0xFC,0x80,0xFC,0x80,0xFC,0xCC,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xEF,0xDF,0xFF,0xDF,0xFF,0x5F,0xD7,0x7F,0xDF,0xBF,0xE7, - 0xBF,0xE7,0xBF,0xE7,0xBF,0xE7,0x9F,0xE7,0x7F,0xD7,0xDF,0xB6,0xBF,0xF7,0x9E,0xFF,0x9F,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x98,0xF9,0x75,0xF8,0x52,0xF8,0x30,0xF8,0x2F,0xF8,0x2D,0xF8,0x2B,0xF8,0x0A,0xF8,0x08,0xF8,0x07,0xF8,0x06,0xF8,0x68,0xFD,0x89,0xFF,0x83,0xFA,0x20,0xF9,0xA0,0xF9,0xE4,0xFB,0xE9,0xFF,0x25,0xFD,0x60,0xF9,0x80,0xF9,0x80,0xF9,0xA6,0xFE,0xC7,0xFF,0x82,0xFB,0xA0,0xFA,0xC0,0xFB,0x60,0xFC,0x80,0xFC,0xA0,0xFC,0xC0,0xFC,0xE0,0xFC,0x20,0xFD,0x84,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,0xFC,0x62,0xFC,0x62,0xFC,0x42,0xFC,0x51,0xFD,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,0xDF,0xFF,0xDF,0xFF,0xBF,0xFF,0xBF,0xFF,0x3F,0xD7,0xBF,0xE7,0xBF,0xEF,0x9F,0xE7,0x5F,0xD7,0x3F,0xE7,0x5F,0xF7,0xFF,0xD6,0xFF,0xCE,0x5F,0xD7,0x7F,0xE7,0x7F,0xE7,0x1F,0xC7,0xBF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x7E,0xFF,0xF5,0xF8,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0x2D,0xF8,0x2C,0xF8,0x0A,0xF8,0x08,0xF8,0x27,0xF8,0x26,0xF8,0x47,0xFD,0xE7,0xFF,0xE4,0xFD,0x80,0xF8,0x60,0xF8,0x63,0xFB,0xE8,0xFF,0x06,0xFF,0x40,0xF9,0x40,0xF9,0x40,0xF9,0xC6,0xFE,0xE7,0xFF,0x24,0xFD,0xE0,0xFA,0xE0,0xFA,0x20,0xFB,0x80,0xFB,0x20,0xFC,0x00,0xFD,0x20,0xFD,0x60,0xFD, - 0x82,0xFD,0xC2,0xFD,0xE2,0xFD,0x22,0xFE,0x49,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,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBF,0xF7,0x5F,0xD7,0x7F,0xDF,0x3F,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x9F,0xEF,0xDF,0xBE,0xFF,0x64,0xFF,0xC6,0x7F,0xDF,0x7F,0xD7,0x9F,0xF7,0xDE,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0xFC,0x74,0xF8,0x31,0xF8,0x10,0xF8,0x0E,0xF8,0x2C,0xF8,0x0A,0xF8,0x09,0xF8,0x07,0xF8,0x26,0xF8,0x65,0xFE,0xC5,0xFF,0x64,0xFE,0x60,0xF8,0x40,0xF8,0x04,0xFD, - 0xE6,0xFF,0x26,0xFF,0x40,0xF9,0x20,0xF9,0x41,0xFA,0xA6,0xFF,0xE7,0xFF,0xA3,0xFC,0xE0,0xFA,0xC0,0xFA,0x00,0xFB,0x40,0xFB,0x20,0xFC,0x00,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x80,0xFD,0xA0,0xFD,0x00,0xFE,0x47,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0x9F,0xEF,0x5F,0xCF,0x7F,0xD7,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0x7F,0xEF,0xBF,0xAE,0x3F,0x5D,0x3F,0x2C,0x7F,0x6B,0xBF,0xE7,0x7F,0xD7,0x5F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, - 0xFF,0xFF,0xB5,0xF9,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x47,0xFA,0x45,0xFF,0xA5,0xFF,0x03,0xFD,0x60,0xF8,0xE0,0xF8,0x04,0xFF,0xC5,0xFF,0x24,0xFE,0x20,0xF9,0xE0,0xF8,0xA4,0xFD,0xA5,0xFF,0x45,0xFF,0x00,0xFA,0x20,0xFA,0xC0,0xFA,0x40,0xFB,0x80,0xFB,0xE0,0xFB,0x60,0xFC,0xA0,0xFC,0xC0,0xFC,0x20,0xFD,0x40,0xFD,0x80,0xFD,0xC0,0xFD,0x27,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xEF,0xBF,0xFF,0x1F,0xC7,0x5F,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xBF,0xF7,0x5F,0xD7,0x3F,0x8E,0xDF,0x24,0xDF,0x1B,0xDF,0x22,0x9F,0x31,0xFF,0xEF,0x3F,0xCF,0xBF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1B,0xFE,0x74,0xF8,0x32,0xF8,0x30,0xF8,0x0E,0xF8,0x0B,0xF8,0x0A,0xF8,0x08,0xF8,0x64,0xFE,0x43,0xFF,0xE3,0xFE,0xA0,0xF8,0x40,0xF8,0x62,0xFD,0x63,0xFF,0x44,0xFF,0x41,0xFA,0x00,0xF9,0x61,0xFB,0x64,0xFF,0x84,0xFF,0x62,0xFC,0x80,0xF9,0xA0,0xF9,0xE0,0xFA,0xA0,0xFB,0xE0,0xFB,0xE0,0xFB,0xA0,0xFB,0x00,0xFC,0x60,0xFC,0x00,0xFD,0x20,0xFD,0x60,0xFD,0xA0,0xFD,0x07,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0xFB,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA, - 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0xDF,0xB6,0x3F,0xCF,0x3F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xBF,0xF7,0x3F,0x5C,0x9F,0x23,0xDF,0x12,0x3F,0x12,0x1F,0x40,0x00,0xF8,0x3F,0xD7,0x9F,0xAE,0x7E,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0xF9,0x33,0xF8,0x31,0xF8,0x2F,0xF8,0x2C,0xF8,0x0A,0xF8,0x66,0xFD,0x22,0xFF,0x22,0xFF,0x41,0xFC,0x41,0xF8,0x21,0xFB,0x03,0xFF,0x23,0xFF,0x42,0xFD,0xC0,0xF8,0xE0,0xF8,0x42,0xFE,0x63,0xFF,0x82,0xFE,0x00,0xF9,0x60,0xF9,0x80,0xF9,0xE0,0xFA,0x80,0xFB,0xC0,0xFB,0x40,0xFC,0x60,0xFD,0xA0,0xFD,0xC0,0xFD, - 0x41,0xFE,0x81,0xFE,0xA2,0xFE,0xC1,0xFE,0x82,0xFE,0x63,0xFE,0x83,0xFE,0x23,0xFE,0x02,0xFA,0x02,0xFA,0xE2,0xF9,0x82,0xF9,0x46,0xFA,0x08,0xFB,0xE8,0xFA,0xE8,0xFA,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xE7,0x9F,0xF7,0x7F,0xD7,0xBF,0xB6,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xE7,0x3F,0xDF,0x3F,0xEF,0x5F,0xFF,0xBF,0x2A,0x1F,0x42,0x1F,0xF8,0x1F,0x50,0x5F,0xAD,0x3F,0xCF,0xBF,0xCE,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x17,0xFB,0x53,0xF8,0x51,0xF8,0x2E,0xF8,0x2A,0xF8,0x27,0xF9,0x02,0xFF,0x01,0xFF,0x41,0xFE,0x21,0xF8,0x40,0xF8,0xC1,0xFD,0x02,0xFF,0x82,0xFE, - 0xA0,0xF8,0xE0,0xF8,0x00,0xFB,0x02,0xFF,0x22,0xFF,0x21,0xFC,0xE0,0xF9,0x20,0xFA,0x40,0xFA,0x80,0xFA,0xC0,0xFA,0x00,0xFB,0x60,0xFC,0xC0,0xFE,0xC0,0xFE,0xE0,0xFE,0x61,0xFF,0xE2,0xFF,0xE2,0xFF,0xE2,0xFF,0x81,0xFE,0x40,0xFE,0x40,0xFE,0xE0,0xFD,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x80,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xBE,0xFF,0xDF,0xF7,0xFF,0xBE,0x7F,0xCF,0x9F,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBF,0xF7,0x7F,0xDF,0xFF,0x64,0x3F,0x11,0x9F,0xE6,0xFD,0xFE,0x1F,0xF8,0x1F,0x30,0x1F,0x18,0x1F,0x18,0x7F,0xDF,0x9F,0xB6,0x9F,0xF7,0xFF,0xFF,0xFF,0xFF, - 0xDF,0xFF,0xFF,0xFF,0x7E,0xFF,0x74,0xF8,0x52,0xF8,0x30,0xF8,0x2C,0xF8,0x66,0xFD,0xE1,0xFE,0xE1,0xFE,0x40,0xFC,0x80,0xF8,0xA0,0xF8,0x61,0xFE,0xC1,0xFE,0xC1,0xFD,0xC0,0xF8,0xE0,0xF8,0xE0,0xFB,0xC1,0xFE,0xE1,0xFE,0x60,0xFA,0x40,0xFA,0x80,0xFA,0xA0,0xFA,0x60,0xFA,0x60,0xFA,0x80,0xFA,0x40,0xFC,0xC0,0xFE,0xC0,0xFE,0xC0,0xFE,0x61,0xFF,0xC2,0xFF,0xC2,0xFF,0xC2,0xFF,0x61,0xFE,0x20,0xFE,0x40,0xFE,0xC0,0xFD,0x00,0xFA,0x00,0xFA,0xC0,0xF9,0x80,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x7F,0xF7,0x9F,0xF7,0x1F,0xCF,0x3F,0xCF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xF7, - 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x1F,0x63,0x1F,0x30,0x1F,0x08,0xBF,0xC5,0x7F,0x93,0x1F,0x10,0x1F,0x08,0x5F,0x08,0x3F,0xCF,0x9F,0xDF,0xBF,0xFF,0x3F,0xDF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0xF8,0x53,0xF8,0x31,0xF8,0x2F,0xF8,0xE6,0xFD,0xC2,0xFE,0xA1,0xFE,0x21,0xFC,0x60,0xF8,0xA0,0xF8,0x21,0xFE,0xA1,0xFE,0xE1,0xFD,0xC0,0xF8,0xE0,0xF8,0x20,0xFB,0xA1,0xFE,0xA1,0xFE,0xC0,0xFC,0x20,0xFA,0x60,0xFA,0x80,0xFA,0x60,0xFA,0x40,0xFA,0x80,0xFA,0x00,0xFC,0x40,0xFE,0x40,0xFE,0x40,0xFE,0xC1,0xFE,0x22,0xFF,0x02,0xFF,0x22,0xFF,0x21,0xFE,0xE0,0xFD,0x00,0xFE,0x80,0xFD,0xE0,0xF9,0xC0,0xF9,0xA0,0xF9,0x60,0xF9,0x06,0xFA,0x00,0x00,0x00,0x00,0x00,0x00, - 0x5D,0xFC,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x1F,0x74,0xBF,0xF7,0x5F,0xD7,0xDF,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFF,0x21,0x5F,0x11,0x7F,0x08,0x7F,0x29,0xBF,0x94,0x7F,0x08,0x9F,0x10,0x1F,0x11,0x5F,0x4A,0xBF,0xDF,0x9F,0xF7,0x5F,0xEF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x57,0xF9,0x54,0xF8,0x53,0xF8,0x50,0xF8,0x49,0xFC,0xA1,0xFE,0x81,0xFE,0xA1,0xFD,0x40,0xF8,0x41,0xF8,0x61,0xFD,0x60,0xFE,0x41,0xFE,0x40,0xFB,0xE0,0xF8,0x00,0xF9,0x01,0xFE,0x61,0xFE,0x00,0xFE,0xA0,0xFA,0x80,0xF9,0x80,0xF9,0xA0,0xF9,0xC0,0xFA,0x00,0xFB,0x20,0xFB,0xE0,0xFB,0xA0,0xFC,0xC0,0xFC, - 0x00,0xFD,0x20,0xFD,0x40,0xFD,0x60,0xFD,0xA0,0xFD,0xC0,0xFD,0xC1,0xFD,0x44,0xFD,0x04,0xFA,0xE4,0xF9,0xE4,0xF9,0xC5,0xF9,0x4C,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x3D,0xFC,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x3F,0xBE,0xBF,0xF7,0x1F,0xCF,0xDF,0x8D,0x9F,0xB6,0x7F,0x9E,0x5F,0x8E,0x9F,0x6D,0xBF,0xF7,0xBF,0x9E,0xBF,0xAE,0x3F,0xE7,0xBF,0xF7,0xBF,0xF7,0xFF,0x08,0x9F,0x09,0xDF,0x09,0x1F,0x11,0x5F,0x09,0xBF,0x63,0x1F,0x11,0x7F,0x11,0xDF,0x19,0x9F,0x19,0xBF,0xDF,0x5F,0xE7,0xBF,0xF7,0xFE,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x78,0xF9,0x75,0xF8,0x54,0xF8,0x52,0xF8,0x4F,0xF8,0x23,0xFE,0x20,0xFE,0x00,0xFE,0x41,0xFC,0x01,0xF8,0xE1,0xF9,0x01,0xFE,0x20,0xFE, - 0xC0,0xFD,0x20,0xFA,0x00,0xF9,0x81,0xFB,0x21,0xFE,0x00,0xFE,0x81,0xFD,0x80,0xF9,0x20,0xF9,0x40,0xF9,0xC0,0xFA,0x20,0xFB,0x20,0xFB,0xA0,0xFB,0x60,0xFC,0xA0,0xFC,0xE0,0xFC,0x00,0xFD,0x40,0xFD,0x60,0xFD,0x80,0xFD,0xA0,0xFD,0xC1,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC9,0xFB,0x62,0xFB,0x61,0xFB,0x44,0xFB,0x00,0x00,0xFD,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x5F,0xBE,0x9F,0xFF,0x3F,0xCF,0xBF,0x85,0xBF,0x65,0x1F,0x66,0xDF,0x44,0x9F,0x2B,0x9F,0xEF,0x9F,0x12,0x1F,0x00,0x7F,0x62,0x1F,0x20,0x5F,0x10,0x5F,0x11,0x5F,0x12,0x5F,0x12,0x3F,0x1A,0x7F,0x1A,0xBF,0x53,0x3F,0x1A,0x5F,0x22,0x5F,0x2A,0xDF,0x21,0xBF,0xE7,0x5F,0xDF,0x9F,0xF7,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7A,0xF9,0x97,0xF8,0x75,0xF8,0x53,0xF8,0x51,0xF8,0x4E,0xFA,0xA2,0xFD,0x80,0xFD,0x40,0xFD,0xE1,0xF9,0x00,0xF8,0xA2,0xFB,0xA0,0xFD,0xC0,0xFD,0xE0,0xFC,0x00,0xF9,0x01,0xF8,0x21,0xFC,0xA0,0xFD,0xA0,0xFD,0x60,0xFC,0x20,0xF9,0x40,0xF9,0x60,0xFA,0xA0,0xFA,0xA0,0xFA,0xE0,0xFA,0x60,0xFB,0xC0,0xFB,0x40,0xFC,0x80,0xFC,0xA0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0x20,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xFB,0x20,0xFB,0x20,0xFB,0x43,0xFB,0x00,0x00,0x7C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0x1F,0x53,0x5F,0xF7,0xFF,0xBE,0x9F,0xA6,0x5F,0x34,0x7F,0x24,0x1F,0x23,0x9F,0x19,0x3D,0xFF,0x1F,0x00,0x1F,0x00,0x1F,0x40, - 0x1F,0x10,0xFF,0x10,0x5F,0x12,0xDF,0x12,0x7F,0x12,0xDF,0x1A,0x1F,0x2B,0xDF,0x53,0xFF,0x2A,0xFF,0x2A,0xFF,0x32,0x7F,0x22,0xBF,0xE7,0x9F,0xEF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7B,0xF9,0x98,0xF8,0x76,0xF8,0x75,0xF8,0x53,0xF8,0x51,0xF8,0x4B,0xFB,0x00,0xFD,0x20,0xFD,0x81,0xFC,0x02,0xF8,0x03,0xF8,0x81,0xFC,0x60,0xFD,0x60,0xFD,0x61,0xFB,0x01,0xF8,0x01,0xF8,0xA0,0xFC,0x60,0xFD,0x40,0xFD,0x60,0xF9,0x20,0xF9,0x40,0xF9,0x60,0xF9,0xA0,0xF9,0xE0,0xF9,0x20,0xFA,0xC0,0xFA,0xC0,0xFB,0x00,0xFC,0x40,0xFC,0x60,0xFC,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0xFB,0x01,0xFB,0x01,0xFB,0x24,0xFB,0x00,0x00, - 0x9C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0xDF,0xDE,0x5F,0xEF,0xFF,0xBE,0x3F,0xC7,0x3F,0x33,0x5F,0x22,0x1F,0x41,0x1F,0xF8,0x5B,0xFE,0xFF,0xFD,0x1F,0x00,0x1F,0xF8,0xBF,0x10,0xDF,0x11,0x9F,0x12,0xDF,0x12,0xDF,0x22,0x1F,0x23,0xFF,0x4B,0x7F,0x43,0x5F,0x33,0x5F,0x3B,0x3F,0x3B,0x1F,0xCF,0xBF,0xE7,0xDF,0xFF,0xFF,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xF9,0xDA,0xF8,0xB8,0xF8,0x76,0xF8,0x74,0xF8,0x51,0xF8,0x2F,0xF8,0x83,0xFC,0xE0,0xFC,0xA0,0xFC,0x03,0xF8,0x03,0xF8,0x43,0xF8,0x00,0xFD,0x00,0xFD,0x60,0xFC,0x01,0xF8,0x01,0xF8,0x61,0xFA,0x20,0xFD,0x20,0xFD,0xA0,0xFA,0x00,0xF9,0x20,0xF9,0x60,0xF9,0x80,0xF9,0xC0,0xF9,0x00,0xFA,0xA0,0xFA, - 0xA0,0xFB,0xE0,0xFB,0x20,0xFC,0x40,0xFC,0x60,0xFC,0x80,0xFC,0x80,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xFB,0x00,0x00,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0x7F,0xEF,0x5F,0xA6,0x3F,0xC7,0xBF,0x1A,0xBF,0xAA,0x00,0xF8,0x00,0xF8,0x1F,0xF8,0xBE,0xFE,0x1F,0x6A,0x7F,0x08,0xFF,0x28,0x9F,0x21,0x1F,0x22,0xFF,0x2A,0x7F,0x2B,0xFF,0x43,0x3F,0x54,0x9F,0x43,0x9F,0x43,0x7F,0x43,0x1F,0x43,0x9F,0xE7,0x7F,0xDF,0xBF,0xFF,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xFD,0x1E,0xF9,0xDC,0xF8,0xBA,0xF8,0x97,0xF8,0x75,0xF8,0x73,0xF8,0x70,0xF8,0x06,0xFC,0xA0,0xFC,0x60,0xFC,0x03,0xF8,0x03,0xF8,0x03,0xF8, - 0x80,0xFC,0xC0,0xFC,0x20,0xFC,0x01,0xF8,0x01,0xF8,0x81,0xF8,0xE0,0xFC,0xE0,0xFC,0x80,0xFA,0xE0,0xF8,0x00,0xF9,0x40,0xF9,0xC0,0xF9,0x00,0xFB,0x20,0xFB,0x40,0xFB,0x80,0xFB,0xA0,0xFB,0xE1,0xFB,0x43,0xFC,0x63,0xFC,0x63,0xFC,0x44,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xFB,0x1C,0xFC,0xDF,0xFF,0xFF,0xFF,0xDF,0xFF,0x5F,0xE7,0xFF,0xE6,0x1F,0xBF,0xDF,0x8D,0xBF,0x52,0x00,0xF8,0x1F,0xF8,0x1F,0x20,0xDF,0x51,0xFF,0xEC,0x3F,0xAB,0x9F,0x39,0x5F,0x32,0xDF,0x32,0x3F,0x3B,0x3F,0x64,0x5F,0x64,0xBF,0x53,0xDF,0x53,0x9F,0x53,0x7F,0x53,0x5F,0x3B,0xDF,0xEF,0x3F,0xCF,0x9F,0xF7,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x3F,0xF9,0x1D,0xF9,0xFB,0xF8,0xB9,0xF8,0x97,0xF8,0x94,0xF8,0x71,0xF8,0xA6,0xFB,0x40,0xFC,0x00,0xFC,0x04,0xF8,0x05,0xF8,0x04,0xF8,0x60,0xFC,0x80,0xFC,0xA0,0xFB,0x01,0xF8,0x01,0xF8,0x61,0xF9,0xA0,0xFC,0x80,0xFC,0xE0,0xF8,0x20,0xF9,0x80,0xF9,0xC0,0xF9,0x20,0xFA,0x20,0xFB,0x40,0xFB,0x40,0xFB,0x60,0xFB,0x80,0xFB,0xC2,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xF8,0x60,0xF8,0x60,0xF8,0x60,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0xFB,0xDC,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x5F,0xF7,0x9F,0xFF,0x7F,0xA6,0xFF,0xBE,0x9F,0x1B,0x1F,0x80,0x1F,0x48,0x1F,0x68,0x7F,0x90,0x7F,0x88,0x1F,0xBB, - 0xFF,0xAB,0xDF,0x93,0x1F,0x84,0x3F,0x84,0x9F,0x6B,0xBF,0x73,0x1F,0x7C,0x3F,0x84,0xDF,0x7B,0x3F,0x63,0xDF,0xEF,0xBF,0xEF,0xBF,0xF7,0xBF,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xDA,0x7F,0xF9,0x3E,0xF9,0x1D,0xF9,0xDB,0xF8,0xB9,0xF8,0x96,0xF8,0x73,0xF8,0xA4,0xFB,0x00,0xFC,0x82,0xFB,0x06,0xF8,0x06,0xF8,0x25,0xF9,0x20,0xFC,0x40,0xFC,0x81,0xF9,0x01,0xF8,0x01,0xF8,0x01,0xFB,0x60,0xFC,0xE0,0xFB,0x80,0xF8,0x00,0xFA,0xA0,0xFA,0xC0,0xFA,0xA0,0xFA,0xE0,0xFA,0x00,0xFB,0x00,0xFB,0x20,0xFB,0x20,0xFB,0x42,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xF8,0x20,0xF8,0x20,0xF8,0x40,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x7E,0xFC,0xBD,0xFB,0x7F,0xFE,0xFF,0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xE6,0x7F,0xF7,0xFF,0xBE,0x1F,0xBF,0x1F,0x23,0xBF,0xD8,0x7F,0xF0,0xBF,0xE8,0x5F,0xF1,0x7F,0xF1,0x1F,0xE2,0x1F,0xD2,0x7F,0xBA,0xDF,0xB2,0x3F,0xA3,0x9F,0xA3,0x3F,0xCE,0xDF,0xFF,0xBF,0x9C,0xBF,0xEF,0xFF,0xF7,0x5F,0xDF,0xBF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xCB,0x1F,0xDA,0xBF,0xF1,0x7F,0xF9,0x3E,0xF9,0xFC,0xF8,0xDA,0xF8,0xD8,0xF8,0xB1,0xF9,0xC0,0xFB,0xC0,0xFB,0xA6,0xF9,0x08,0xF8,0x07,0xF8,0x23,0xFB,0xE0,0xFB,0x60,0xFB,0x02,0xF8,0x01,0xF8,0x01,0xF8,0x80,0xFB,0xE0,0xFB,0xE0,0xF9,0x60,0xF8,0x00,0xFA,0xA0,0xFA,0xC0,0xFA,0x60,0xFA,0x80,0xF9,0x80,0xF9,0x80,0xF9, - 0x80,0xF9,0x60,0xF9,0x41,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xF8,0x00,0xF8,0x00,0xF8,0x20,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBE,0xFB,0xFE,0xFB,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xDF,0xFF,0x7F,0xF7,0xBF,0xCE,0x1F,0xC7,0xBF,0xB6,0xBF,0x3A,0x3E,0xF9,0xBB,0xF8,0x1A,0xF9,0x3B,0xF9,0xBC,0xF9,0xFE,0xF9,0x5F,0xF2,0xBF,0xEA,0xFF,0xD2,0x3F,0xCB,0xFF,0xCC,0x5F,0xEF,0x9F,0xE7,0xFF,0xFF,0x9F,0xE7,0xDF,0xFF,0x3F,0xE7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x9F,0xBA,0x3F,0xD2,0xFF,0xE1,0x7F,0xF1,0x5F,0xF9,0x3E,0xF9,0x1C,0xF9,0xD9,0xF8,0x47,0xFB,0xA0,0xFB,0xC6,0xFA,0x2A,0xF8,0x09,0xF8,0x27,0xF9,0x80,0xFB, - 0x60,0xFB,0x82,0xF8,0x02,0xF8,0x02,0xF8,0x20,0xFA,0x40,0xFB,0x60,0xFA,0x41,0xF8,0x41,0xF8,0xC0,0xF9,0x60,0xFA,0x80,0xFA,0x40,0xFA,0x00,0xFA,0x00,0xFA,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x62,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0xF9,0xA6,0xF9,0xA6,0xF9,0xE7,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFC,0xBF,0xFB,0x3F,0xFD,0xDF,0xFF,0xDF,0xFF,0xDE,0xFF,0x7F,0xE7,0xBF,0xFF,0xFF,0xD6,0x1F,0xC7,0xFF,0xC6,0x3F,0x5D,0x3F,0xBA,0x39,0xF9,0xF8,0xF8,0x19,0xF9,0x7B,0xF9,0xDD,0xF9,0x5E,0xFA,0xBF,0xEA,0xDF,0xDA,0x5F,0x73,0xDF,0xF7,0xFF,0xF7,0x9F,0xE7,0xDF,0xFF,0x5F,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xA2,0x7F,0xB2,0x3F,0xC2,0xFF,0xD9,0xDF,0xE9,0x7F,0xF9,0x5F,0xF9,0x3D,0xF9,0x58,0xF9,0x09,0xFB,0xC9,0xFA,0x2E,0xF8,0x0C,0xF8,0x0A,0xF8,0x67,0xF9,0x84,0xFA,0x44,0xF9,0x03,0xF8,0x02,0xF8,0x02,0xF8,0x01,0xF8,0x61,0xF8,0x21,0xF8,0x42,0xF8,0x42,0xF8,0x41,0xF9,0xE0,0xF9,0x40,0xFA,0x80,0xFA,0xC0,0xFA,0x00,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xFA,0x08,0xFA,0xE7,0xF9,0x69,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0xF3,0xBF,0xF3,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x5F,0xE7,0xBF,0xFF,0xBF,0xD6,0xBF,0xBE,0x1F,0xCF,0xFF,0xC6,0xBF,0x8D,0x5F,0x1B, - 0x9F,0xAA,0x1F,0xFA,0x7F,0xEA,0xFF,0x42,0xDF,0xBE,0xFF,0xF7,0xFF,0xF7,0xDF,0xF7,0xBF,0xE7,0xDF,0xF7,0x7F,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x9C,0xBF,0x9A,0x7F,0xAA,0x3F,0xBA,0x1F,0xD2,0xFF,0xE9,0xBF,0xF1,0x7F,0xF9,0x5E,0xF9,0x1B,0xF9,0xB7,0xF8,0x53,0xF8,0x30,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x07,0xF8,0x05,0xF8,0x04,0xF8,0x03,0xF8,0x03,0xF8,0x02,0xF8,0x22,0xF8,0x21,0xF8,0x22,0xF8,0x22,0xF8,0x40,0xF9,0xC0,0xF9,0x00,0xFA,0x60,0xFA,0xA0,0xFA,0xC0,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xF8,0x80,0xF8,0x80,0xF8,0xE3,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,0x7F,0xF5,0x7F,0xEB,0x7F,0xE3,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xBF,0xF7,0x1F,0xEF,0x1F,0xEF,0x7F,0xBE,0xBF,0xBE,0x3F,0xD7,0x7F,0xDF,0x7F,0xE7,0xDF,0xEF,0xDF,0xF7,0xFF,0xF7,0xFF,0xF7,0xFF,0xF7,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF,0xD6,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x8C,0x1F,0x7B,0xDF,0x92,0x7F,0xA2,0x5F,0xB2,0x3F,0xD2,0xFF,0xE9,0xDF,0xF9,0x9F,0xF9,0x7E,0xF9,0x1C,0xF9,0xD8,0xF8,0x74,0xF8,0x30,0xF8,0x0D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x80,0xF8,0x80,0xF8,0x40,0xF8,0x21,0xF8,0x40,0xF8,0x60,0xF8,0x80,0xF8,0xC0,0xF8,0x21,0xF9,0x07,0xFB,0x28,0xFB,0x00,0x00, - 0x00,0x00,0x00,0x00,0x60,0xF8,0x60,0xF8,0x60,0xF8,0xE3,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,0x3F,0xEC,0x5F,0xE3,0x7F,0xDB,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x8D,0x1F,0xEF,0x5F,0xEF,0x1F,0xEF,0xFF,0xCE,0x3F,0xCF,0x7F,0xE7,0x9F,0xE7,0x9F,0xE7,0x9F,0xF7,0xBF,0xFF,0xDF,0xFF,0x7F,0xE7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7C,0x5F,0x5B,0x3F,0x73,0xFF,0x8A,0x9F,0x9A,0x5F,0xB2,0x3F,0xCA,0x1F,0xE2,0x1F,0xFA,0xDF,0xF9,0x7E,0xF9,0x3B,0xF9,0xF8,0xF8,0xB5,0xF8,0x51,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8, - 0x06,0xF8,0x05,0xF8,0x04,0xF8,0x23,0xF8,0x80,0xF8,0xA0,0xF8,0x40,0xF8,0x20,0xF8,0x40,0xF8,0x60,0xF8,0x80,0xF8,0xA0,0xF8,0x23,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xF8,0x20,0xF8,0x20,0xF8,0xC2,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,0x5F,0xDC,0x1F,0xCB,0x3F,0xC3,0xBF,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x5F,0xEF,0x5F,0xB6,0x5F,0xEF,0xBF,0xFF,0xBF,0xFF,0xDF,0xFF,0xDF,0xFF,0x9F,0xE7,0xBF,0x95,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x5B,0x7F,0x4B,0x7F,0x53,0x5F,0x6B, - 0x3F,0x7B,0xFF,0x9A,0x5F,0xAB,0x5F,0xC4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xFC,0xDA,0xFA,0xB6,0xF9,0xF2,0xF8,0x2D,0xF8,0x0B,0xF8,0x09,0xF8,0x08,0xF8,0x07,0xF8,0x06,0xF8,0x05,0xF8,0x24,0xF8,0x61,0xF8,0x81,0xF8,0x21,0xF8,0x20,0xF8,0x20,0xF8,0x60,0xF8,0x60,0xF8,0x60,0xF8,0x4C,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0xFB,0x6D,0xFB,0xCF,0xFB,0x30,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,0xDF,0xD4,0x1F,0xBB,0x1F,0xB3,0x1F,0xB4,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDE,0xFF,0xFF,0xFF,0x9F,0x94,0x1F,0x5B,0x3F,0x4B,0x9F,0x5B,0xDF,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xF9,0xEA,0xF8,0x48,0xF8,0x06,0xF8,0x05,0xF8,0x04,0xF8,0x03,0xF8,0x02,0xF8,0x02,0xF8,0x01,0xF8,0x00,0xF8,0x20,0xF8,0x60,0xF8,0xA1,0xF8,0x8A,0xFA,0x00,0x00,0xE8,0xFA,0x63,0xFA,0x63,0xFA,0x09,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0xAB,0xFF,0xA2,0x1F,0xA3,0x7F,0xAC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5F,0xAD,0xDF,0x7B,0x1F,0xE7,0xFF,0xFF,0x5F,0xEF,0x1F,0xA5,0x1F,0x94,0x9F,0x9B,0x5F,0xAB,0x5F,0xBB,0x3F,0xC3,0x9F,0xD3,0x1F,0xE4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFB,0xA8,0xF9,0xE6,0xF8,0xA4,0xF8,0x63,0xF8,0x63,0xF8,0x62,0xF8,0xA3,0xF8,0x04,0xF9,0x49,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xFA,0x20,0xFA,0x40,0xFA, - 0x85,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xBC,0x3F,0x9B,0xDF,0x82,0x1F,0x73,0x9F,0x73,0xDF,0x94,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xCE,0x5F,0x6C,0xDF,0x4B,0x9F,0x43,0x7F,0x4B,0x7F,0x63,0x5F,0x6B,0x3F,0x73,0x3F,0x83,0x1F,0x93,0xDF,0xA2,0x9F,0xB2,0x5F,0xC2,0x3F,0xD2,0x3F,0xE2,0x3F,0xEA,0x7F,0xFA,0x7D,0xFA,0x3B,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,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,0xFA,0x20,0xFA,0x20,0xFA,0x65,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDF,0xAC,0x5F,0x7B,0x3F,0x63,0x5F,0x53,0x5F,0x4B,0x5F,0x43,0x7F,0x3B,0x7F,0x3B,0x9F,0x33,0x9F,0x33,0x9F,0x2B,0x9F,0x2B,0x9F,0x2B,0x7F,0x2B,0x9F,0x2B,0x9F,0x33,0x9F,0x3B,0x7F,0x4B,0x7F,0x5B,0x7F,0x6B,0x5F,0x73,0x3F,0x83, - 0x1F,0x93,0xFF,0xA2,0xDF,0xB2,0x9F,0xC2,0x9F,0xD2,0x7F,0xE2,0x5F,0xF2,0x3E,0xFA,0xBB,0xF9,0x78,0xF9,0x56,0xF9,0xF4,0xF9,0x56,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,0xCD,0xFB,0xEE,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,0x8C,0xDF,0x5B,0x7F,0x4B, - 0x7F,0x3B,0x7F,0x33,0x9F,0x2B,0x9F,0x2B,0x7F,0x2B,0x9F,0x2B,0x9F,0x2B,0x9F,0x33,0xBF,0x3B,0xDF,0x43,0x1F,0x54,0x5F,0x6C,0x3F,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0xFB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xFD, 0x23, 0xFD, 0x45, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE4, 0xFB, 0x40, 0xFC, 0xA0, 0xFC, 0x47, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xFB, 0x22, 0xFB, 0xA0, 0xFB, 0x00, 0xFC, 0x80, 0xFC, 0xCA, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFD, 0x23, 0xFD, 0x43, 0xFD, 0x43, 0xFD, 0x4D, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFA, 0xA1, 0xFA, 0x20, 0xFB, 0xA0, 0xFB, 0xE0, 0xFB, 0x40, 0xFC, 0xAC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0xEF, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xFC, 0xC3, 0xF9, 0x01, 0xFA, 0x81, 0xFA, 0x20, 0xFB, 0x80, 0xFB, 0xC0, 0xFB, 0x00, 0xFC, 0x87, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0xAE, 0xFD, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFA, 0x02, 0xF9, 0x62, 0xF9, 0xE1, 0xF9, 0x80, 0xFA, + 0x00, 0xFB, 0x60, 0xFB, 0xA0, 0xFB, 0xE0, 0xFB, 0x64, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0xFC, 0x81, 0xFC, 0x81, 0xFC, 0xC1, 0xFC, 0x8F, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xF9, 0x63, 0xF8, 0xE2, 0xF8, 0x62, 0xF9, 0xC1, 0xF9, 0x60, 0xFA, 0xE0, 0xFA, 0x80, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x81, 0xFC, 0x00, 0x00, 0xCF, 0xFD, 0xC7, 0xFD, 0xE4, 0xFD, 0x8A, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFA, 0x84, 0xF8, 0x03, 0xF8, 0x63, 0xF8, 0xE2, 0xF8, 0x42, 0xF9, 0xC1, 0xF9, 0x40, 0xFA, 0xC0, 0xFA, 0x60, 0xFB, 0xA0, 0xFB, 0x20, 0xFC, 0x80, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x60, 0xFD, 0xC1, 0xFD, 0xC9, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA4, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xFC, 0xE7, 0xF8, 0x04, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x43, 0xF8, 0xC2, 0xF8, 0x41, 0xF9, 0xC0, 0xF9, 0x20, 0xFA, 0x80, 0xFA, 0xE0, 0xFA, 0x00, 0xFB, 0x60, 0xFB, 0xA0, 0xFB, 0xA0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0xA1, 0xFD, 0x0B, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xA6, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0x63, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xF9, 0xAB, 0xF8, 0x28, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x43, 0xF8, 0xA2, 0xF8, 0x21, 0xF9, 0xA0, 0xF9, 0x00, 0xFA, + 0x60, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x40, 0xFB, 0x60, 0xFC, 0xC0, 0xFC, 0x00, 0xFD, 0x81, 0xFD, 0x4D, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xFE, 0x25, 0xFE, 0x25, 0xFE, 0x25, 0xFE, 0x6D, 0xFE, 0x87, 0xFD, 0x41, 0xFD, 0x21, 0xFD, 0x23, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xBC, 0x5F, 0xB3, 0x1F, 0xC3, 0xBF, 0xCB, 0x3F, 0xDC, 0x9F, 0xF4, 0x3D, 0xFC, 0x7B, 0xFB, 0x97, 0xFA, + 0xD4, 0xF9, 0x31, 0xF9, 0xAF, 0xF8, 0x2E, 0xF8, 0x0C, 0xF8, 0x0A, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x43, 0xF8, 0xA2, 0xF8, 0x21, 0xF9, 0xA0, 0xF9, 0x00, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0xE0, 0xFA, 0x20, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0x40, 0xFD, 0x62, 0xFC, 0xA2, 0xFB, 0xC2, 0xFB, 0x81, 0xFD, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x67, 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, 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, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xC3, 0xBF, 0xC2, 0x7F, 0xCA, 0x1F, 0xE2, 0x7D, 0xF9, 0xD9, 0xF8, 0x76, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x0F, 0xF8, 0x2E, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x62, 0xF8, 0xE1, 0xF8, 0x20, 0xFA, 0x60, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x40, 0xFA, 0x60, 0xFA, 0x40, 0xFB, 0x80, 0xFC, 0xC0, 0xFC, 0x00, 0xFD, 0x20, 0xFC, 0xA0, 0xFB, 0xA0, 0xFB, 0x40, 0xFD, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0x87, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x7F, 0xCB, 0x1F, 0xE2, 0x7E, 0xF9, 0xFA, 0xF8, 0x96, 0xF8, 0x74, 0xF8, 0x31, 0xF8, 0x30, 0xF8, 0x2E, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x61, 0xF8, 0xA1, 0xF8, 0x00, 0xF9, 0xC0, 0xF9, 0xA0, 0xFA, 0xC0, 0xFA, 0x80, 0xFA, 0x00, 0xFA, 0x20, 0xFA, 0x60, 0xFA, 0x20, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xE0, 0xFB, 0xA0, 0xFB, 0xC0, 0xFB, 0x40, 0xFD, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, + 0x87, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFD, 0x03, 0xFD, 0x03, 0xFD, 0xE3, 0xFC, 0x30, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xEF, 0x1F, 0xDF, 0x7F, 0xEF, 0x3F, 0xDF, 0x7F, 0xE7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xFE, 0xFE, 0xF9, 0x1B, 0xF9, 0xB7, 0xF8, 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x2A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x41, 0xF8, 0x00, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, + 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x00, 0xFA, 0x40, 0xFA, 0x20, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x20, 0xFC, 0xA0, 0xFC, 0x00, 0xFD, 0x00, 0xFD, 0xC0, 0xFC, 0xE0, 0xFC, 0x40, 0xFD, 0xC7, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0x0C, 0xFD, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x7F, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0xDF, 0xFF, 0xBF, 0xF7, 0x9F, 0xF7, 0x9F, 0xF7, 0xDF, 0xFF, 0xDE, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF9, 0xD8, 0xF8, + 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0xE5, 0xFA, 0x44, 0xFA, 0x41, 0xF8, 0x40, 0xF9, 0xE0, 0xF9, 0x44, 0xFB, 0x85, 0xFC, 0x60, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0xC0, 0xF9, 0x87, 0xFE, 0x24, 0xFD, 0x60, 0xFA, 0xA0, 0xFA, 0xE0, 0xFB, 0xA0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0x20, 0xFD, 0x84, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xCC, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0x5F, 0xD7, 0x7F, 0xDF, 0xBF, 0xE7, + 0xBF, 0xE7, 0xBF, 0xE7, 0xBF, 0xE7, 0x9F, 0xE7, 0x7F, 0xD7, 0xDF, 0xB6, 0xBF, 0xF7, 0x9E, 0xFF, 0x9F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0xF9, 0x75, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x68, 0xFD, 0x89, 0xFF, 0x83, 0xFA, 0x20, 0xF9, 0xA0, 0xF9, 0xE4, 0xFB, 0xE9, 0xFF, 0x25, 0xFD, 0x60, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xA6, 0xFE, 0xC7, 0xFF, 0x82, 0xFB, 0xA0, 0xFA, 0xC0, 0xFB, 0x60, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x84, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xFC, 0x62, 0xFC, 0x62, 0xFC, 0x42, 0xFC, 0x51, 0xFD, 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, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0x3F, 0xD7, 0xBF, 0xE7, 0xBF, 0xEF, 0x9F, 0xE7, 0x5F, 0xD7, 0x3F, 0xE7, 0x5F, 0xF7, 0xFF, 0xD6, 0xFF, 0xCE, 0x5F, 0xD7, 0x7F, 0xE7, 0x7F, 0xE7, 0x1F, 0xC7, 0xBF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7E, 0xFF, 0xF5, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x2D, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x27, 0xF8, 0x26, 0xF8, 0x47, 0xFD, 0xE7, 0xFF, 0xE4, 0xFD, 0x80, 0xF8, 0x60, 0xF8, 0x63, 0xFB, 0xE8, 0xFF, 0x06, 0xFF, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0xC6, 0xFE, 0xE7, 0xFF, 0x24, 0xFD, 0xE0, 0xFA, 0xE0, 0xFA, 0x20, 0xFB, 0x80, 0xFB, 0x20, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x60, 0xFD, + 0x82, 0xFD, 0xC2, 0xFD, 0xE2, 0xFD, 0x22, 0xFE, 0x49, 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, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x5F, 0xD7, 0x7F, 0xDF, 0x3F, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x9F, 0xEF, 0xDF, 0xBE, 0xFF, 0x64, 0xFF, 0xC6, 0x7F, 0xDF, 0x7F, 0xD7, 0x9F, 0xF7, 0xDE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0xFC, 0x74, 0xF8, 0x31, 0xF8, 0x10, 0xF8, 0x0E, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x26, 0xF8, 0x65, 0xFE, 0xC5, 0xFF, 0x64, 0xFE, 0x60, 0xF8, 0x40, 0xF8, 0x04, 0xFD, + 0xE6, 0xFF, 0x26, 0xFF, 0x40, 0xF9, 0x20, 0xF9, 0x41, 0xFA, 0xA6, 0xFF, 0xE7, 0xFF, 0xA3, 0xFC, 0xE0, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x40, 0xFB, 0x20, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0x00, 0xFE, 0x47, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x9F, 0xEF, 0x5F, 0xCF, 0x7F, 0xD7, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0x7F, 0xEF, 0xBF, 0xAE, 0x3F, 0x5D, 0x3F, 0x2C, 0x7F, 0x6B, 0xBF, 0xE7, 0x7F, 0xD7, 0x5F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, + 0xFF, 0xFF, 0xB5, 0xF9, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x47, 0xFA, 0x45, 0xFF, 0xA5, 0xFF, 0x03, 0xFD, 0x60, 0xF8, 0xE0, 0xF8, 0x04, 0xFF, 0xC5, 0xFF, 0x24, 0xFE, 0x20, 0xF9, 0xE0, 0xF8, 0xA4, 0xFD, 0xA5, 0xFF, 0x45, 0xFF, 0x00, 0xFA, 0x20, 0xFA, 0xC0, 0xFA, 0x40, 0xFB, 0x80, 0xFB, 0xE0, 0xFB, 0x60, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0x20, 0xFD, 0x40, 0xFD, 0x80, 0xFD, 0xC0, 0xFD, 0x27, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xEF, 0xBF, 0xFF, 0x1F, 0xC7, 0x5F, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x5F, 0xD7, 0x3F, 0x8E, 0xDF, 0x24, 0xDF, 0x1B, 0xDF, 0x22, 0x9F, 0x31, 0xFF, 0xEF, 0x3F, 0xCF, 0xBF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0xFE, 0x74, 0xF8, 0x32, 0xF8, 0x30, 0xF8, 0x0E, 0xF8, 0x0B, 0xF8, 0x0A, 0xF8, 0x08, 0xF8, 0x64, 0xFE, 0x43, 0xFF, 0xE3, 0xFE, 0xA0, 0xF8, 0x40, 0xF8, 0x62, 0xFD, 0x63, 0xFF, 0x44, 0xFF, 0x41, 0xFA, 0x00, 0xF9, 0x61, 0xFB, 0x64, 0xFF, 0x84, 0xFF, 0x62, 0xFC, 0x80, 0xF9, 0xA0, 0xF9, 0xE0, 0xFA, 0xA0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xA0, 0xFB, 0x00, 0xFC, 0x60, 0xFC, 0x00, 0xFD, 0x20, 0xFD, 0x60, 0xFD, 0xA0, 0xFD, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0xDF, 0xB6, 0x3F, 0xCF, 0x3F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x3F, 0x5C, 0x9F, 0x23, 0xDF, 0x12, 0x3F, 0x12, 0x1F, 0x40, 0x00, 0xF8, 0x3F, 0xD7, 0x9F, 0xAE, 0x7E, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xF9, 0x33, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0x2C, 0xF8, 0x0A, 0xF8, 0x66, 0xFD, 0x22, 0xFF, 0x22, 0xFF, 0x41, 0xFC, 0x41, 0xF8, 0x21, 0xFB, 0x03, 0xFF, 0x23, 0xFF, 0x42, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0x42, 0xFE, 0x63, 0xFF, 0x82, 0xFE, 0x00, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0xE0, 0xFA, 0x80, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x60, 0xFD, 0xA0, 0xFD, 0xC0, 0xFD, + 0x41, 0xFE, 0x81, 0xFE, 0xA2, 0xFE, 0xC1, 0xFE, 0x82, 0xFE, 0x63, 0xFE, 0x83, 0xFE, 0x23, 0xFE, 0x02, 0xFA, 0x02, 0xFA, 0xE2, 0xF9, 0x82, 0xF9, 0x46, 0xFA, 0x08, 0xFB, 0xE8, 0xFA, 0xE8, 0xFA, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xE7, 0x9F, 0xF7, 0x7F, 0xD7, 0xBF, 0xB6, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xE7, 0x3F, 0xDF, 0x3F, 0xEF, 0x5F, 0xFF, 0xBF, 0x2A, 0x1F, 0x42, 0x1F, 0xF8, 0x1F, 0x50, 0x5F, 0xAD, 0x3F, 0xCF, 0xBF, 0xCE, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0xFB, 0x53, 0xF8, 0x51, 0xF8, 0x2E, 0xF8, 0x2A, 0xF8, 0x27, 0xF9, 0x02, 0xFF, 0x01, 0xFF, 0x41, 0xFE, 0x21, 0xF8, 0x40, 0xF8, 0xC1, 0xFD, 0x02, 0xFF, 0x82, 0xFE, + 0xA0, 0xF8, 0xE0, 0xF8, 0x00, 0xFB, 0x02, 0xFF, 0x22, 0xFF, 0x21, 0xFC, 0xE0, 0xF9, 0x20, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x60, 0xFC, 0xC0, 0xFE, 0xC0, 0xFE, 0xE0, 0xFE, 0x61, 0xFF, 0xE2, 0xFF, 0xE2, 0xFF, 0xE2, 0xFF, 0x81, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0xE0, 0xFD, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x80, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, 0xDF, 0xF7, 0xFF, 0xBE, 0x7F, 0xCF, 0x9F, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x7F, 0xDF, 0xFF, 0x64, 0x3F, 0x11, 0x9F, 0xE6, 0xFD, 0xFE, 0x1F, 0xF8, 0x1F, 0x30, 0x1F, 0x18, 0x1F, 0x18, 0x7F, 0xDF, 0x9F, 0xB6, 0x9F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xFF, 0xFF, 0x7E, 0xFF, 0x74, 0xF8, 0x52, 0xF8, 0x30, 0xF8, 0x2C, 0xF8, 0x66, 0xFD, 0xE1, 0xFE, 0xE1, 0xFE, 0x40, 0xFC, 0x80, 0xF8, 0xA0, 0xF8, 0x61, 0xFE, 0xC1, 0xFE, 0xC1, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0xE0, 0xFB, 0xC1, 0xFE, 0xE1, 0xFE, 0x60, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x80, 0xFA, 0x40, 0xFC, 0xC0, 0xFE, 0xC0, 0xFE, 0xC0, 0xFE, 0x61, 0xFF, 0xC2, 0xFF, 0xC2, 0xFF, 0xC2, 0xFF, 0x61, 0xFE, 0x20, 0xFE, 0x40, 0xFE, 0xC0, 0xFD, 0x00, 0xFA, 0x00, 0xFA, 0xC0, 0xF9, 0x80, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x7F, 0xF7, 0x9F, 0xF7, 0x1F, 0xCF, 0x3F, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x1F, 0x63, 0x1F, 0x30, 0x1F, 0x08, 0xBF, 0xC5, 0x7F, 0x93, 0x1F, 0x10, 0x1F, 0x08, 0x5F, 0x08, 0x3F, 0xCF, 0x9F, 0xDF, 0xBF, 0xFF, 0x3F, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0xF8, 0x53, 0xF8, 0x31, 0xF8, 0x2F, 0xF8, 0xE6, 0xFD, 0xC2, 0xFE, 0xA1, 0xFE, 0x21, 0xFC, 0x60, 0xF8, 0xA0, 0xF8, 0x21, 0xFE, 0xA1, 0xFE, 0xE1, 0xFD, 0xC0, 0xF8, 0xE0, 0xF8, 0x20, 0xFB, 0xA1, 0xFE, 0xA1, 0xFE, 0xC0, 0xFC, 0x20, 0xFA, 0x60, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x40, 0xFA, 0x80, 0xFA, 0x00, 0xFC, 0x40, 0xFE, 0x40, 0xFE, 0x40, 0xFE, 0xC1, 0xFE, 0x22, 0xFF, 0x02, 0xFF, 0x22, 0xFF, 0x21, 0xFE, 0xE0, 0xFD, 0x00, 0xFE, 0x80, 0xFD, 0xE0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF9, 0x60, 0xF9, 0x06, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5D, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x1F, 0x74, 0xBF, 0xF7, 0x5F, 0xD7, 0xDF, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xF7, 0xFF, 0x21, 0x5F, 0x11, 0x7F, 0x08, 0x7F, 0x29, 0xBF, 0x94, 0x7F, 0x08, 0x9F, 0x10, 0x1F, 0x11, 0x5F, 0x4A, 0xBF, 0xDF, 0x9F, 0xF7, 0x5F, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0xF9, 0x54, 0xF8, 0x53, 0xF8, 0x50, 0xF8, 0x49, 0xFC, 0xA1, 0xFE, 0x81, 0xFE, 0xA1, 0xFD, 0x40, 0xF8, 0x41, 0xF8, 0x61, 0xFD, 0x60, 0xFE, 0x41, 0xFE, 0x40, 0xFB, 0xE0, 0xF8, 0x00, 0xF9, 0x01, 0xFE, 0x61, 0xFE, 0x00, 0xFE, 0xA0, 0xFA, 0x80, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0xC0, 0xFA, 0x00, 0xFB, 0x20, 0xFB, 0xE0, 0xFB, 0xA0, 0xFC, 0xC0, 0xFC, + 0x00, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0xA0, 0xFD, 0xC0, 0xFD, 0xC1, 0xFD, 0x44, 0xFD, 0x04, 0xFA, 0xE4, 0xF9, 0xE4, 0xF9, 0xC5, 0xF9, 0x4C, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0xBF, 0xF7, 0x1F, 0xCF, 0xDF, 0x8D, 0x9F, 0xB6, 0x7F, 0x9E, 0x5F, 0x8E, 0x9F, 0x6D, 0xBF, 0xF7, 0xBF, 0x9E, 0xBF, 0xAE, 0x3F, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xFF, 0x08, 0x9F, 0x09, 0xDF, 0x09, 0x1F, 0x11, 0x5F, 0x09, 0xBF, 0x63, 0x1F, 0x11, 0x7F, 0x11, 0xDF, 0x19, 0x9F, 0x19, 0xBF, 0xDF, 0x5F, 0xE7, 0xBF, 0xF7, 0xFE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0xF9, 0x75, 0xF8, 0x54, 0xF8, 0x52, 0xF8, 0x4F, 0xF8, 0x23, 0xFE, 0x20, 0xFE, 0x00, 0xFE, 0x41, 0xFC, 0x01, 0xF8, 0xE1, 0xF9, 0x01, 0xFE, 0x20, 0xFE, + 0xC0, 0xFD, 0x20, 0xFA, 0x00, 0xF9, 0x81, 0xFB, 0x21, 0xFE, 0x00, 0xFE, 0x81, 0xFD, 0x80, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0xC0, 0xFA, 0x20, 0xFB, 0x20, 0xFB, 0xA0, 0xFB, 0x60, 0xFC, 0xA0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0xC1, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0xFB, 0x62, 0xFB, 0x61, 0xFB, 0x44, 0xFB, 0x00, 0x00, 0xFD, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x5F, 0xBE, 0x9F, 0xFF, 0x3F, 0xCF, 0xBF, 0x85, 0xBF, 0x65, 0x1F, 0x66, 0xDF, 0x44, 0x9F, 0x2B, 0x9F, 0xEF, 0x9F, 0x12, 0x1F, 0x00, 0x7F, 0x62, 0x1F, 0x20, 0x5F, 0x10, 0x5F, 0x11, 0x5F, 0x12, 0x5F, 0x12, 0x3F, 0x1A, 0x7F, 0x1A, 0xBF, 0x53, 0x3F, 0x1A, 0x5F, 0x22, 0x5F, 0x2A, 0xDF, 0x21, 0xBF, 0xE7, 0x5F, 0xDF, 0x9F, 0xF7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7A, 0xF9, 0x97, 0xF8, 0x75, 0xF8, 0x53, 0xF8, 0x51, 0xF8, 0x4E, 0xFA, 0xA2, 0xFD, 0x80, 0xFD, 0x40, 0xFD, 0xE1, 0xF9, 0x00, 0xF8, 0xA2, 0xFB, 0xA0, 0xFD, 0xC0, 0xFD, 0xE0, 0xFC, 0x00, 0xF9, 0x01, 0xF8, 0x21, 0xFC, 0xA0, 0xFD, 0xA0, 0xFD, 0x60, 0xFC, 0x20, 0xF9, 0x40, 0xF9, 0x60, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xE0, 0xFA, 0x60, 0xFB, 0xC0, 0xFB, 0x40, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x20, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x43, 0xFB, 0x00, 0x00, 0x7C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0x1F, 0x53, 0x5F, 0xF7, 0xFF, 0xBE, 0x9F, 0xA6, 0x5F, 0x34, 0x7F, 0x24, 0x1F, 0x23, 0x9F, 0x19, 0x3D, 0xFF, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x40, + 0x1F, 0x10, 0xFF, 0x10, 0x5F, 0x12, 0xDF, 0x12, 0x7F, 0x12, 0xDF, 0x1A, 0x1F, 0x2B, 0xDF, 0x53, 0xFF, 0x2A, 0xFF, 0x2A, 0xFF, 0x32, 0x7F, 0x22, 0xBF, 0xE7, 0x9F, 0xEF, 0xBF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7B, 0xF9, 0x98, 0xF8, 0x76, 0xF8, 0x75, 0xF8, 0x53, 0xF8, 0x51, 0xF8, 0x4B, 0xFB, 0x00, 0xFD, 0x20, 0xFD, 0x81, 0xFC, 0x02, 0xF8, 0x03, 0xF8, 0x81, 0xFC, 0x60, 0xFD, 0x60, 0xFD, 0x61, 0xFB, 0x01, 0xF8, 0x01, 0xF8, 0xA0, 0xFC, 0x60, 0xFD, 0x40, 0xFD, 0x60, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0xA0, 0xF9, 0xE0, 0xF9, 0x20, 0xFA, 0xC0, 0xFA, 0xC0, 0xFB, 0x00, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0xFB, 0x01, 0xFB, 0x01, 0xFB, 0x24, 0xFB, 0x00, 0x00, + 0x9C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0xDF, 0xDE, 0x5F, 0xEF, 0xFF, 0xBE, 0x3F, 0xC7, 0x3F, 0x33, 0x5F, 0x22, 0x1F, 0x41, 0x1F, 0xF8, 0x5B, 0xFE, 0xFF, 0xFD, 0x1F, 0x00, 0x1F, 0xF8, 0xBF, 0x10, 0xDF, 0x11, 0x9F, 0x12, 0xDF, 0x12, 0xDF, 0x22, 0x1F, 0x23, 0xFF, 0x4B, 0x7F, 0x43, 0x5F, 0x33, 0x5F, 0x3B, 0x3F, 0x3B, 0x1F, 0xCF, 0xBF, 0xE7, 0xDF, 0xFF, 0xFF, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xF9, 0xDA, 0xF8, 0xB8, 0xF8, 0x76, 0xF8, 0x74, 0xF8, 0x51, 0xF8, 0x2F, 0xF8, 0x83, 0xFC, 0xE0, 0xFC, 0xA0, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x43, 0xF8, 0x00, 0xFD, 0x00, 0xFD, 0x60, 0xFC, 0x01, 0xF8, 0x01, 0xF8, 0x61, 0xFA, 0x20, 0xFD, 0x20, 0xFD, 0xA0, 0xFA, 0x00, 0xF9, 0x20, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, 0x00, 0xFA, 0xA0, 0xFA, + 0xA0, 0xFB, 0xE0, 0xFB, 0x20, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xFB, 0x00, 0x00, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0x7F, 0xEF, 0x5F, 0xA6, 0x3F, 0xC7, 0xBF, 0x1A, 0xBF, 0xAA, 0x00, 0xF8, 0x00, 0xF8, 0x1F, 0xF8, 0xBE, 0xFE, 0x1F, 0x6A, 0x7F, 0x08, 0xFF, 0x28, 0x9F, 0x21, 0x1F, 0x22, 0xFF, 0x2A, 0x7F, 0x2B, 0xFF, 0x43, 0x3F, 0x54, 0x9F, 0x43, 0x9F, 0x43, 0x7F, 0x43, 0x1F, 0x43, 0x9F, 0xE7, 0x7F, 0xDF, 0xBF, 0xFF, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFD, 0x1E, 0xF9, 0xDC, 0xF8, 0xBA, 0xF8, 0x97, 0xF8, 0x75, 0xF8, 0x73, 0xF8, 0x70, 0xF8, 0x06, 0xFC, 0xA0, 0xFC, 0x60, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x03, 0xF8, + 0x80, 0xFC, 0xC0, 0xFC, 0x20, 0xFC, 0x01, 0xF8, 0x01, 0xF8, 0x81, 0xF8, 0xE0, 0xFC, 0xE0, 0xFC, 0x80, 0xFA, 0xE0, 0xF8, 0x00, 0xF9, 0x40, 0xF9, 0xC0, 0xF9, 0x00, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0xE1, 0xFB, 0x43, 0xFC, 0x63, 0xFC, 0x63, 0xFC, 0x44, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFB, 0x1C, 0xFC, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x5F, 0xE7, 0xFF, 0xE6, 0x1F, 0xBF, 0xDF, 0x8D, 0xBF, 0x52, 0x00, 0xF8, 0x1F, 0xF8, 0x1F, 0x20, 0xDF, 0x51, 0xFF, 0xEC, 0x3F, 0xAB, 0x9F, 0x39, 0x5F, 0x32, 0xDF, 0x32, 0x3F, 0x3B, 0x3F, 0x64, 0x5F, 0x64, 0xBF, 0x53, 0xDF, 0x53, 0x9F, 0x53, 0x7F, 0x53, 0x5F, 0x3B, 0xDF, 0xEF, 0x3F, 0xCF, 0x9F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x3F, 0xF9, 0x1D, 0xF9, 0xFB, 0xF8, 0xB9, 0xF8, 0x97, 0xF8, 0x94, 0xF8, 0x71, 0xF8, 0xA6, 0xFB, 0x40, 0xFC, 0x00, 0xFC, 0x04, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x60, 0xFC, 0x80, 0xFC, 0xA0, 0xFB, 0x01, 0xF8, 0x01, 0xF8, 0x61, 0xF9, 0xA0, 0xFC, 0x80, 0xFC, 0xE0, 0xF8, 0x20, 0xF9, 0x80, 0xF9, 0xC0, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x60, 0xFB, 0x80, 0xFB, 0xC2, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xFB, 0xDC, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x5F, 0xF7, 0x9F, 0xFF, 0x7F, 0xA6, 0xFF, 0xBE, 0x9F, 0x1B, 0x1F, 0x80, 0x1F, 0x48, 0x1F, 0x68, 0x7F, 0x90, 0x7F, 0x88, 0x1F, 0xBB, + 0xFF, 0xAB, 0xDF, 0x93, 0x1F, 0x84, 0x3F, 0x84, 0x9F, 0x6B, 0xBF, 0x73, 0x1F, 0x7C, 0x3F, 0x84, 0xDF, 0x7B, 0x3F, 0x63, 0xDF, 0xEF, 0xBF, 0xEF, 0xBF, 0xF7, 0xBF, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xDA, 0x7F, 0xF9, 0x3E, 0xF9, 0x1D, 0xF9, 0xDB, 0xF8, 0xB9, 0xF8, 0x96, 0xF8, 0x73, 0xF8, 0xA4, 0xFB, 0x00, 0xFC, 0x82, 0xFB, 0x06, 0xF8, 0x06, 0xF8, 0x25, 0xF9, 0x20, 0xFC, 0x40, 0xFC, 0x81, 0xF9, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0xFB, 0x60, 0xFC, 0xE0, 0xFB, 0x80, 0xF8, 0x00, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0xE0, 0xFA, 0x00, 0xFB, 0x00, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x42, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0x40, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0xFC, 0xBD, 0xFB, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xE6, 0x7F, 0xF7, 0xFF, 0xBE, 0x1F, 0xBF, 0x1F, 0x23, 0xBF, 0xD8, 0x7F, 0xF0, 0xBF, 0xE8, 0x5F, 0xF1, 0x7F, 0xF1, 0x1F, 0xE2, 0x1F, 0xD2, 0x7F, 0xBA, 0xDF, 0xB2, 0x3F, 0xA3, 0x9F, 0xA3, 0x3F, 0xCE, 0xDF, 0xFF, 0xBF, 0x9C, 0xBF, 0xEF, 0xFF, 0xF7, 0x5F, 0xDF, 0xBF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xCB, 0x1F, 0xDA, 0xBF, 0xF1, 0x7F, 0xF9, 0x3E, 0xF9, 0xFC, 0xF8, 0xDA, 0xF8, 0xD8, 0xF8, 0xB1, 0xF9, 0xC0, 0xFB, 0xC0, 0xFB, 0xA6, 0xF9, 0x08, 0xF8, 0x07, 0xF8, 0x23, 0xFB, 0xE0, 0xFB, 0x60, 0xFB, 0x02, 0xF8, 0x01, 0xF8, 0x01, 0xF8, 0x80, 0xFB, 0xE0, 0xFB, 0xE0, 0xF9, 0x60, 0xF8, 0x00, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x60, 0xFA, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, + 0x80, 0xF9, 0x60, 0xF9, 0x41, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x20, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xFB, 0xFE, 0xFB, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0x7F, 0xF7, 0xBF, 0xCE, 0x1F, 0xC7, 0xBF, 0xB6, 0xBF, 0x3A, 0x3E, 0xF9, 0xBB, 0xF8, 0x1A, 0xF9, 0x3B, 0xF9, 0xBC, 0xF9, 0xFE, 0xF9, 0x5F, 0xF2, 0xBF, 0xEA, 0xFF, 0xD2, 0x3F, 0xCB, 0xFF, 0xCC, 0x5F, 0xEF, 0x9F, 0xE7, 0xFF, 0xFF, 0x9F, 0xE7, 0xDF, 0xFF, 0x3F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x9F, 0xBA, 0x3F, 0xD2, 0xFF, 0xE1, 0x7F, 0xF1, 0x5F, 0xF9, 0x3E, 0xF9, 0x1C, 0xF9, 0xD9, 0xF8, 0x47, 0xFB, 0xA0, 0xFB, 0xC6, 0xFA, 0x2A, 0xF8, 0x09, 0xF8, 0x27, 0xF9, 0x80, 0xFB, + 0x60, 0xFB, 0x82, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x20, 0xFA, 0x40, 0xFB, 0x60, 0xFA, 0x41, 0xF8, 0x41, 0xF8, 0xC0, 0xF9, 0x60, 0xFA, 0x80, 0xFA, 0x40, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x62, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xF9, 0xA6, 0xF9, 0xA6, 0xF9, 0xE7, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0xBF, 0xFB, 0x3F, 0xFD, 0xDF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0x7F, 0xE7, 0xBF, 0xFF, 0xFF, 0xD6, 0x1F, 0xC7, 0xFF, 0xC6, 0x3F, 0x5D, 0x3F, 0xBA, 0x39, 0xF9, 0xF8, 0xF8, 0x19, 0xF9, 0x7B, 0xF9, 0xDD, 0xF9, 0x5E, 0xFA, 0xBF, 0xEA, 0xDF, 0xDA, 0x5F, 0x73, 0xDF, 0xF7, 0xFF, 0xF7, 0x9F, 0xE7, 0xDF, 0xFF, 0x5F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xA2, 0x7F, 0xB2, 0x3F, 0xC2, 0xFF, 0xD9, 0xDF, 0xE9, 0x7F, 0xF9, 0x5F, 0xF9, 0x3D, 0xF9, 0x58, 0xF9, 0x09, 0xFB, 0xC9, 0xFA, 0x2E, 0xF8, 0x0C, 0xF8, 0x0A, 0xF8, 0x67, 0xF9, 0x84, 0xFA, 0x44, 0xF9, 0x03, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x01, 0xF8, 0x61, 0xF8, 0x21, 0xF8, 0x42, 0xF8, 0x42, 0xF8, 0x41, 0xF9, 0xE0, 0xF9, 0x40, 0xFA, 0x80, 0xFA, 0xC0, 0xFA, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xFA, 0x08, 0xFA, 0xE7, 0xF9, 0x69, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xF3, 0xBF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x5F, 0xE7, 0xBF, 0xFF, 0xBF, 0xD6, 0xBF, 0xBE, 0x1F, 0xCF, 0xFF, 0xC6, 0xBF, 0x8D, 0x5F, 0x1B, + 0x9F, 0xAA, 0x1F, 0xFA, 0x7F, 0xEA, 0xFF, 0x42, 0xDF, 0xBE, 0xFF, 0xF7, 0xFF, 0xF7, 0xDF, 0xF7, 0xBF, 0xE7, 0xDF, 0xF7, 0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x9C, 0xBF, 0x9A, 0x7F, 0xAA, 0x3F, 0xBA, 0x1F, 0xD2, 0xFF, 0xE9, 0xBF, 0xF1, 0x7F, 0xF9, 0x5E, 0xF9, 0x1B, 0xF9, 0xB7, 0xF8, 0x53, 0xF8, 0x30, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x07, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x03, 0xF8, 0x02, 0xF8, 0x22, 0xF8, 0x21, 0xF8, 0x22, 0xF8, 0x22, 0xF8, 0x40, 0xF9, 0xC0, 0xF9, 0x00, 0xFA, 0x60, 0xFA, 0xA0, 0xFA, 0xC0, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xF8, 0x80, 0xF8, 0x80, 0xF8, 0xE3, 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, 0x7F, 0xF5, 0x7F, 0xEB, 0x7F, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF7, 0x1F, 0xEF, 0x1F, 0xEF, 0x7F, 0xBE, 0xBF, 0xBE, 0x3F, 0xD7, 0x7F, 0xDF, 0x7F, 0xE7, 0xDF, 0xEF, 0xDF, 0xF7, 0xFF, 0xF7, 0xFF, 0xF7, 0xFF, 0xF7, 0xBF, 0xEF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x8C, 0x1F, 0x7B, 0xDF, 0x92, 0x7F, 0xA2, 0x5F, 0xB2, 0x3F, 0xD2, 0xFF, 0xE9, 0xDF, 0xF9, 0x9F, 0xF9, 0x7E, 0xF9, 0x1C, 0xF9, 0xD8, 0xF8, 0x74, 0xF8, 0x30, 0xF8, 0x0D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x80, 0xF8, 0x80, 0xF8, 0x40, 0xF8, 0x21, 0xF8, 0x40, 0xF8, 0x60, 0xF8, 0x80, 0xF8, 0xC0, 0xF8, 0x21, 0xF9, 0x07, 0xFB, 0x28, 0xFB, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0xE3, 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, 0x3F, 0xEC, 0x5F, 0xE3, 0x7F, 0xDB, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x8D, 0x1F, 0xEF, 0x5F, 0xEF, 0x1F, 0xEF, 0xFF, 0xCE, 0x3F, 0xCF, 0x7F, 0xE7, 0x9F, 0xE7, 0x9F, 0xE7, 0x9F, 0xF7, 0xBF, 0xFF, 0xDF, 0xFF, 0x7F, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7C, 0x5F, 0x5B, 0x3F, 0x73, 0xFF, 0x8A, 0x9F, 0x9A, 0x5F, 0xB2, 0x3F, 0xCA, 0x1F, 0xE2, 0x1F, 0xFA, 0xDF, 0xF9, 0x7E, 0xF9, 0x3B, 0xF9, 0xF8, 0xF8, 0xB5, 0xF8, 0x51, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, + 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x23, 0xF8, 0x80, 0xF8, 0xA0, 0xF8, 0x40, 0xF8, 0x20, 0xF8, 0x40, 0xF8, 0x60, 0xF8, 0x80, 0xF8, 0xA0, 0xF8, 0x23, 0xF9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0xC2, 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, 0x5F, 0xDC, 0x1F, 0xCB, 0x3F, 0xC3, 0xBF, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x5F, 0xEF, 0x5F, 0xB6, 0x5F, 0xEF, 0xBF, 0xFF, 0xBF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x9F, 0xE7, 0xBF, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x5B, 0x7F, 0x4B, 0x7F, 0x53, 0x5F, 0x6B, + 0x3F, 0x7B, 0xFF, 0x9A, 0x5F, 0xAB, 0x5F, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xFC, 0xDA, 0xFA, 0xB6, 0xF9, 0xF2, 0xF8, 0x2D, 0xF8, 0x0B, 0xF8, 0x09, 0xF8, 0x08, 0xF8, 0x07, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x24, 0xF8, 0x61, 0xF8, 0x81, 0xF8, 0x21, 0xF8, 0x20, 0xF8, 0x20, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x60, 0xF8, 0x4C, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xFB, 0x6D, 0xFB, 0xCF, 0xFB, 0x30, 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, 0xDF, 0xD4, 0x1F, 0xBB, 0x1F, 0xB3, 0x1F, 0xB4, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0x9F, 0x94, 0x1F, 0x5B, 0x3F, 0x4B, 0x9F, 0x5B, 0xDF, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xF9, 0xEA, 0xF8, 0x48, 0xF8, 0x06, 0xF8, 0x05, 0xF8, 0x04, 0xF8, 0x03, 0xF8, 0x02, 0xF8, 0x02, 0xF8, 0x01, 0xF8, 0x00, 0xF8, 0x20, 0xF8, 0x60, 0xF8, 0xA1, 0xF8, 0x8A, 0xFA, 0x00, 0x00, 0xE8, 0xFA, 0x63, 0xFA, 0x63, 0xFA, 0x09, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xAB, 0xFF, 0xA2, 0x1F, 0xA3, 0x7F, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xAD, 0xDF, 0x7B, 0x1F, 0xE7, 0xFF, 0xFF, 0x5F, 0xEF, 0x1F, 0xA5, 0x1F, 0x94, 0x9F, 0x9B, 0x5F, 0xAB, 0x5F, 0xBB, 0x3F, 0xC3, 0x9F, 0xD3, 0x1F, 0xE4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xFB, 0xA8, 0xF9, 0xE6, 0xF8, 0xA4, 0xF8, 0x63, 0xF8, 0x63, 0xF8, 0x62, 0xF8, 0xA3, 0xF8, 0x04, 0xF9, 0x49, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xFA, 0x20, 0xFA, 0x40, 0xFA, + 0x85, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xBC, 0x3F, 0x9B, 0xDF, 0x82, 0x1F, 0x73, 0x9F, 0x73, 0xDF, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xCE, 0x5F, 0x6C, 0xDF, 0x4B, 0x9F, 0x43, 0x7F, 0x4B, 0x7F, 0x63, 0x5F, 0x6B, 0x3F, 0x73, 0x3F, 0x83, 0x1F, 0x93, 0xDF, 0xA2, 0x9F, 0xB2, 0x5F, 0xC2, 0x3F, 0xD2, 0x3F, 0xE2, 0x3F, 0xEA, 0x7F, 0xFA, 0x7D, 0xFA, 0x3B, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x65, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xAC, 0x5F, 0x7B, 0x3F, 0x63, 0x5F, 0x53, 0x5F, 0x4B, 0x5F, 0x43, 0x7F, 0x3B, 0x7F, 0x3B, 0x9F, 0x33, 0x9F, 0x33, 0x9F, 0x2B, 0x9F, 0x2B, 0x9F, 0x2B, 0x7F, 0x2B, 0x9F, 0x2B, 0x9F, 0x33, 0x9F, 0x3B, 0x7F, 0x4B, 0x7F, 0x5B, 0x7F, 0x6B, 0x5F, 0x73, 0x3F, 0x83, + 0x1F, 0x93, 0xFF, 0xA2, 0xDF, 0xB2, 0x9F, 0xC2, 0x9F, 0xD2, 0x7F, 0xE2, 0x5F, 0xF2, 0x3E, 0xFA, 0xBB, 0xF9, 0x78, 0xF9, 0x56, 0xF9, 0xF4, 0xF9, 0x56, 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, 0xCD, 0xFB, 0xEE, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x8C, 0xDF, 0x5B, 0x7F, 0x4B, + 0x7F, 0x3B, 0x7F, 0x33, 0x9F, 0x2B, 0x9F, 0x2B, 0x7F, 0x2B, 0x9F, 0x2B, 0x9F, 0x2B, 0x9F, 0x33, 0xBF, 0x3B, 0xDF, 0x43, 0x1F, 0x54, 0x5F, 0x6C, 0x3F, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + //alpha channel data: - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0xAC,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x9A,0xEF,0xFD,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xD9,0xFE,0xFE,0xFE,0x53,0x00,0x00,0x00,0x00,0x6C,0xA9,0xAA,0xAB,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xF7,0xFE,0xFE,0xFE,0xFD,0x48,0x00,0x00,0x00,0x00,0xA2,0xFE,0xFE,0xFD,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xC6,0xFE,0xFD,0xFD,0xFE,0xFE,0xFD,0x6D,0x00,0x00,0x00,0x00,0xA1,0xFE,0xFE,0xFD,0x3C,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xE4,0xFD,0xFE,0xFD, - 0xFE,0xFE,0xFE,0xFE,0xA3,0x00,0x00,0x00,0x00,0x8A,0xD6,0xD5,0xD4,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xF5,0xFE,0xFC,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xEA,0x00,0x37,0x6E,0xAA,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0xC8,0xFA,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xF9,0xFC,0xFE,0xFE,0x5D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0xD7,0xD9,0xA4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xA2,0xEC,0xFA,0xFB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x4C,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x7D,0xFE,0xFE,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,0x68,0xA9,0xDA,0xE9,0xF2,0xF8,0xFA,0xFB,0xFD,0xFD,0xFD,0xFE, - 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x44,0x00,0x00,0x55,0x87,0x88,0x8B,0x43,0x6F,0xE5,0xE3,0xA8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x62,0x67,0x53,0x41,0x37,0x37,0x42,0x53, - 0x66,0x80,0xA0,0xC1,0xD1,0xD8,0xDE,0xE5,0xEE,0xF6,0xF8,0xFA,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xD0,0xCE,0xD0,0xE4,0xFE,0xFE,0xFE,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,0x00,0x00,0x69,0x9E,0xBB, - 0xC8,0xCE,0xCC,0xC1,0xA6,0x79,0x00,0x00,0x00,0x60,0x8D,0xA1,0x96,0x90,0x98,0xA1,0xAA,0xB3,0xBE,0xC7,0xCE,0xD3,0xDA,0xE1,0xE9,0xF1,0xF7,0xF8,0xFB,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAF,0xE9,0xFC,0xFB,0xF4,0xEA,0xE8,0xEA,0xF1,0xF6,0xF7,0xEC,0xBD,0x5F,0x1E,0x1E,0x53,0x85,0x8C,0x97,0xA1,0xAB,0xB2,0xBB,0xC2,0xC8,0xCD,0xD5,0xDD,0xE4,0xED,0xF3,0xF7,0xFB,0xFD,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, - 0x71,0x00,0x00,0x00,0x7F,0xBE,0xBE,0xBF,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xE8,0xF6,0xDB,0xA8,0x69,0x2D,0x25,0x2D,0x26,0x29,0x5E,0x99,0xCE,0xEE,0xEB,0xB2,0x3C,0x1E,0x26,0x6C,0x91,0x9C,0xA7,0xAF,0xB7,0xBD,0xC3,0xCA,0xD0,0xD7,0xDE,0xE8,0xF0,0xF5,0xFA,0xFC,0xFE,0xFD, - 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0x6F,0x00,0x00,0x00,0xA9,0xFE,0xFE,0xFD,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0xD8,0xF2,0xC4,0x70,0x31,0x4C,0x4D,0x4F,0x49,0x48,0x45,0x4B,0x4D,0x48,0x27,0x69,0xC2,0xE4,0xD9,0x71,0x1E,0x1E,0x64,0x97, - 0xA3,0xAC,0xB3,0xB9,0xBF,0xC6,0xCC,0xD2,0xDA,0xE3,0xED,0xF4,0xFA,0xFD,0xFE,0xFD,0xFC,0xFC,0xFD,0xFD,0xFE,0xFD,0xF6,0xF2,0xFB,0xFD,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0x9D,0x00,0x00,0x00,0xA9,0xFE,0xFE,0xFD,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xEF,0xE6,0x89,0x2C,0x4E,0x4B,0x2E,0x3F,0x4A, - 0x4F,0x4C,0x48,0x40,0x31,0x21,0x34,0x42,0x28,0x86,0xDD,0xE2,0x84,0x1E,0x1E,0x6E,0x9E,0xA8,0xAE,0xB4,0xBA,0xC0,0xC5,0xCC,0xD3,0xDC,0xEC,0xFC,0xEE,0xFA,0xFD,0xFD,0xFE,0xEC,0xF5,0xFC,0xFD,0xFD,0xFD,0xDC,0xF3,0xFC,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xA9,0x00,0x00,0x00,0x87,0xC9,0xC9,0xC7,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x99,0xEF,0xD8,0x5B,0x42,0x4B,0x34,0x52,0x58,0x41,0x2C,0x29,0x27,0x1E,0x1E,0x26,0x31,0x31,0x21,0x38,0x39,0x61,0xD3,0xDC,0x7A,0x1E,0x20,0x80,0xA1,0xA9,0xAD,0xB3,0xB9,0xBF,0xC5,0xCD,0xD4,0xE5,0xFE,0xE4,0xE8,0xFA,0xFB,0xFE,0xEF,0xDF,0xFA,0xFD,0xFD,0xFE,0xE1,0xEA,0xFC,0xFC,0xFD,0xFD,0xFC,0xFD,0xFC, - 0xE0,0xCA,0xCB,0xCC,0x5D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xE7,0xD7,0x4A,0x4B,0x3C,0x42,0x52,0x35,0x7B,0xBF,0xAA,0x95,0x6D,0x49,0x35,0x22,0x10,0x16,0x2E,0x28,0x29,0x3B,0x55,0xD2,0xD6,0x56,0x1E,0x35,0x96,0xA3,0xA8,0xAD,0xB3,0xB9,0xC0,0xC7,0xCE,0xEB,0xFE,0xE4,0xD7,0xF5,0xF7, - 0xFE,0xEE,0xD4,0xF6,0xFC,0xFE,0xFE,0xDE,0xE8,0xFC,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFB,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xF0,0xF0,0xE6,0x00,0x00,0x00,0x00,0xD1,0xE0,0x66,0x3C,0x39,0x3F,0x44,0x4B,0xD1,0xFE,0xFF,0xE6,0x95,0x66,0x43,0x2F,0x20,0x17,0x11,0x07,0x20,0x2C,0x24,0x3B,0x68,0xD4,0xB8,0x1F, - 0x1E,0x67,0x9B,0xA0,0xA7,0xAD,0xB4,0xBA,0xC1,0xCB,0xFA,0xFD,0xD1,0xD3,0xF0,0xFA,0xFD,0xDC,0xD3,0xF5,0xFB,0xFE,0xF5,0xDA,0xF0,0xFB,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFD,0xFD,0xFC,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xFE,0xFE,0xF0,0x00,0x00,0x00,0x8F,0xE9,0x9F,0x26,0x3C,0x36,0x3D,0x45,0xE9,0xFF,0xFF,0xFF,0xF1, - 0x8F,0x5A,0x38,0x26,0x1A,0x14,0x11,0x0E,0x05,0x1C,0x28,0x2E,0x2C,0x9E,0xD2,0x7B,0x1E,0x26,0x8C,0x99,0xA0,0xA6,0xAD,0xB3,0xB8,0xE9,0xFE,0xED,0xC1,0xDF,0xF6,0xFE,0xF7,0xC3,0xDE,0xF8,0xFD,0xFD,0xE5,0xE6,0xF9,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFC,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0xFE,0xFE,0xF0, - 0x00,0x00,0x00,0xD2,0xD7,0x35,0x43,0x27,0x3D,0x27,0xB3,0xFD,0xFE,0xFE,0xFE,0xD1,0x9F,0x81,0x5A,0x37,0x11,0x10,0x0E,0x0B,0x04,0x01,0x20,0x21,0x35,0x3C,0xC4,0xB5,0x1E,0x1E,0x6A,0x91,0x98,0xA0,0xA4,0xA3,0xC4,0xFE,0xFB,0xB0,0xC1,0xEA,0xFE,0xFE,0xCC,0xC5,0xEC,0xFB,0xFE,0xE8,0xE0,0xF2,0xFD,0xFD,0xFE,0xFE,0xFD,0xFD,0xFD,0xFE, - 0xFE,0xFD,0xFD,0xFC,0xC4,0xB9,0xBA,0xBB,0xC1,0xC3,0xC5,0xC8,0x78,0x6C,0x6A,0x65,0x00,0x00,0x6C,0xE3,0xA1,0x28,0x33,0x38,0x24,0x7E,0xB4,0xD1,0xF0,0xEC,0xE7,0xC7,0x88,0x54,0x36,0x2B,0x2A,0x17,0x06,0x04,0x01,0x03,0x06,0x28,0x20,0x2F,0x97,0xC1,0x5F,0x1E,0x42,0x79,0x74,0x75,0x76,0x77,0xF0,0xFE,0xCE,0x99,0xC9,0xF0,0xFE,0xEF, - 0xBE,0xDA,0xF1,0xFE,0xFE,0xCF,0xEB,0xFC,0xFE,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0xA2,0xDE,0x5F,0x3C,0x24,0x35,0x1B,0x90,0x97,0x98,0x93,0xBD,0xA1,0x81,0x5A,0x32,0x1B,0x10,0x0E,0x1D,0x17,0x01,0x05,0x0A,0x09,0x20,0x22,0x38,0x62,0xBC, - 0x8B,0x1E,0x1F,0x5E,0x61,0x67,0x6D,0x9C,0xFE,0xFE,0xAE,0xB7,0xC6,0xF5,0xFE,0xDF,0xD1,0xED,0xF6,0xFE,0xFE,0xC5,0xF1,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0x7E,0x00,0x00,0x00,0x00,0x00,0xBB,0xD2,0x20,0x3C,0x2B,0x27,0x44,0x77,0x73,0x71,0x81,0x82,0x5F,0x35, - 0xC9,0xEE,0x66,0x10,0x05,0x11,0x1F,0x07,0x0B,0x13,0x1A,0x15,0x2A,0x37,0x1F,0xB4,0x9D,0x1E,0x1E,0x55,0x5E,0x61,0x66,0xA4,0xFE,0xFE,0xB4,0xB7,0xC4,0xF5,0xFE,0xE7,0xD0,0xED,0xF3,0xFE,0xFE,0xD5,0xEF,0xFD,0xFD,0xFD,0xFE,0xFE,0xFD,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFC,0xFE,0xFE,0xFE,0xFE,0x7F,0x00,0x00,0x00, - 0x58,0x00,0xC8,0xBE,0x10,0x39,0x2D,0x1B,0x49,0x54,0x4E,0x49,0x73,0x39,0x29,0x4E,0xF2,0xF8,0x6A,0x2A,0x18,0x14,0x1D,0x22,0x13,0x1E,0x28,0x0E,0x31,0x34,0x27,0xA5,0xAA,0x1E,0x1E,0x4D,0x5C,0x5D,0x62,0x81,0xFC,0xFE,0xD6,0xA1,0xB3,0xDF,0xFE,0xFC,0xD5,0xE0,0xE1,0xEF,0xFE,0xF8,0xE2,0xF1,0xF9,0xFC,0xFE,0xFD,0xFD,0xFD,0xFE,0xFE, - 0xFE,0xFD,0xFD,0xFD,0xFD,0xFE,0xF9,0xA7,0xA1,0x9C,0x96,0x8F,0x48,0x00,0x00,0x00,0x7C,0x00,0xCD,0xB2,0x1A,0x2F,0x2D,0x12,0x1D,0x1F,0x1D,0x1A,0x43,0x20,0x06,0x29,0x44,0x4A,0x23,0x37,0x3A,0x16,0x2F,0x32,0x20,0x2B,0x35,0x19,0x34,0x33,0x33,0x9B,0xAF,0x1F,0x1E,0x4B,0x5C,0x5D,0x61,0x62,0xCC,0xFE,0xFC,0xA9,0x9D,0xB0,0xF2,0xFE, - 0xF7,0xD8,0xD2,0xAC,0xF7,0xFE,0xF5,0xD7,0xF2,0xFA,0xFE,0xFD,0xFD,0xFD,0xFE,0xFD,0xFD,0xFD,0xFD,0xFD,0xFC,0xFD,0xF3,0x00,0x00,0x00,0x00,0x5D,0xD4,0xD5,0x95,0x00,0x97,0x00,0xCA,0xB1,0x18,0x2B,0x2B,0x11,0x15,0x19,0x17,0x12,0x2C,0x10,0x01,0x0A,0x0D,0x20,0x36,0x4D,0x4C,0x25,0x44,0x46,0x33,0x3D,0x47,0x20,0x39,0x34,0x35,0x98, - 0xAF,0x20,0x1E,0x4D,0x5E,0x60,0x63,0x64,0x69,0xE4,0xFE,0xF4,0x9F,0xAF,0xA1,0xF8,0xFE,0xF0,0xCC,0x9E,0xB4,0xFC,0xFE,0xE3,0xDF,0xF6,0xFC,0xFC,0xFC,0xFB,0xFD,0xFC,0xFD,0xFD,0xFD,0xFD,0xFC,0xFC,0xF0,0x00,0x00,0x00,0x00,0x6E,0xFE,0xFE,0xB1,0x00,0xA5,0x00,0xC0,0xB8,0x10,0x2D,0x28,0x16,0x0F,0x14,0x10,0x0A,0x1E,0x04,0x01,0x04, - 0x1A,0x31,0x4A,0x62,0x3C,0x41,0x54,0x58,0x4B,0x53,0x5D,0x1D,0x42,0x38,0x2F,0x9D,0xAC,0x1F,0x1E,0x55,0x62,0x64,0x66,0x67,0x65,0x7C,0xF7,0xFE,0xC8,0x80,0x86,0xBB,0xFE,0xFE,0xA3,0x99,0x9A,0xD2,0xFE,0xFA,0xD1,0xEA,0xF6,0xF9,0xFC,0xFB,0xFC,0xFC,0xFE,0xFD,0xFD,0xFD,0xFD,0xFD,0xF0,0x00,0x00,0x00,0x00,0x5D,0xDA,0xD9,0x99,0x00, - 0xB8,0x00,0xAE,0xC5,0x1A,0x2E,0x24,0x1E,0x0A,0x0E,0x08,0x01,0x17,0x0C,0x06,0x01,0x16,0x36,0x4A,0x3A,0x35,0x64,0x73,0x5E,0x67,0x6E,0x6B,0x22,0x48,0x3C,0x1F,0xA9,0xA2,0x1E,0x1E,0x5F,0x66,0x68,0x69,0x69,0x69,0x67,0xCC,0xFE,0xEA,0x73,0x89,0x8A,0xF5,0xFE,0xBE,0x93,0x9F,0xA7,0xFD,0xFE,0xD4,0xE1,0xF5,0xF7,0xFB,0xFC,0xFC,0xFC, - 0xFE,0xFD,0xFE,0xFE,0xFE,0xFD,0xF1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCA,0x00,0x95,0xC8,0x5D,0x2D,0x1D,0x29,0x09,0x03,0x02,0x02,0x01,0x1F,0x0C,0x11,0x11,0x15,0x23,0x43,0x67,0x77,0x81,0x7A,0x85,0x8B,0x5F,0x3A,0x41,0x3F,0x3A,0xB1,0x8F,0x1E,0x28,0x69,0x6A,0x6C,0x6C,0x6B,0x6D,0x6C,0xB1,0xFE,0xF2,0x75,0x8A,0x8E, - 0xE5,0xFE,0xC2,0x90,0xA3,0xA2,0xFB,0xFE,0xD1,0xDF,0xF5,0xF7,0xFA,0xFD,0xFD,0xFD,0xFE,0xFD,0xE9,0xAE,0xAC,0xAA,0x9F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0x6D,0x64,0xC3,0x8E,0x21,0x20,0x2C,0x16,0x03,0x02,0x02,0x07,0x09,0x20,0x23,0x23,0x34,0x46,0x5A,0x79,0x85,0x89,0x9B,0xA2,0x97,0x22,0x50,0x2F,0x3A,0x73,0xB2, - 0x71,0x1E,0x4B,0x6C,0x6E,0x6F,0x6F,0x6E,0x70,0x70,0xB7,0xFE,0xE8,0x79,0x8C,0x92,0xE9,0xFE,0xB7,0x96,0xA9,0xAD,0xFD,0xFA,0xC5,0xE2,0xF6,0xF9,0xFB,0xFE,0xFE,0xFE,0xFE,0xFD,0xD7,0x00,0x00,0x00,0x00,0xC7,0xF6,0xF6,0xE1,0x00,0x00,0x00,0x00,0x00,0xA0,0xB0,0x20,0xB1,0xB4,0x23,0x2A,0x1E,0x28,0x09,0x02,0x07,0x0E,0x11,0x12,0x1D, - 0x31,0x41,0x55,0x66,0x6D,0x8B,0xAB,0xB2,0xB8,0x5C,0x44,0x4F,0x3B,0x20,0xA7,0xB5,0x38,0x1E,0x84,0x6E,0x70,0x71,0x72,0x72,0x73,0x76,0xD6,0xFE,0xC4,0x80,0x92,0x9D,0xFB,0xF9,0x9A,0xA1,0xAF,0xCA,0xFE,0xE3,0xC2,0xEB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFD,0xFD,0xD7,0x00,0x00,0x00,0x00,0xCE,0xFD,0xFD,0xE6,0x00,0x00,0x00,0x00,0x00, - 0x54,0xDD,0x29,0x80,0xBE,0x81,0x1F,0x28,0x28,0x24,0x08,0x0D,0x13,0x18,0x1F,0x28,0x30,0x3A,0x4D,0x65,0x81,0x9B,0xCB,0xF5,0x8B,0x3D,0x68,0x39,0x46,0x66,0xBD,0x94,0x1E,0x4E,0xA2,0x7D,0x73,0x74,0x75,0x76,0x76,0x8A,0xF9,0xF5,0x87,0x8F,0x9C,0xCD,0xFE,0xD2,0xA2,0xB1,0xB4,0xEF,0xFA,0xBC,0xCA,0xF2,0xFD,0xFE,0xFC,0xFA,0xFB,0xFD, - 0xFD,0xFC,0xD6,0x00,0x00,0x00,0x00,0xD0,0xFE,0xFD,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x93,0x29,0xB0,0xBA,0x47,0x2F,0x20,0x2D,0x20,0x09,0x14,0x23,0x2D,0x37,0x43,0x4E,0x5D,0x6F,0x86,0xA1,0xB0,0x85,0x41,0x7A,0x48,0x57,0x29,0xAD,0xB8,0x48,0x1E,0x93,0xA5,0x95,0x7A,0x78,0x79,0x7A,0x7C,0xD7,0xFE,0xB0,0x8C,0xA2,0xB0,0xF9, - 0xED,0xAA,0xB3,0xC0,0xD5,0xFC,0xCC,0xBA,0xD7,0xF2,0xFD,0xFD,0xFD,0xFC,0xFA,0xE9,0xE7,0xE6,0xC3,0x00,0x00,0x00,0x00,0x69,0x7A,0x78,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xCF,0x3C,0x65,0xBC,0xA8,0x28,0x35,0x1E,0x29,0x28,0x11,0x12,0x2A,0x42,0x58,0x64,0x70,0x79,0x79,0x63,0x20,0x5F,0x82,0x50,0x5F,0x30,0x96,0xBE,0x86,0x1E, - 0x6E,0xB1,0xA9,0xA2,0x88,0x7E,0x7D,0x7E,0x89,0xD4,0xC3,0x90,0xA2,0xAE,0xBD,0xD9,0xBE,0xBB,0xC4,0xC8,0xC9,0xCA,0xD0,0xC8,0xD1,0xEE,0xFD,0xFD,0xFD,0xFE,0xEA,0x00,0x00,0x00,0x55,0x63,0x6E,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA7,0xAB,0x1E,0x85,0xBA,0x9E,0x23,0x2E,0x20,0x24,0x2E,0x25,0x18,0x11, - 0x19,0x22,0x25,0x16,0x22,0x54,0x78,0x75,0x45,0x62,0x31,0x87,0xC2,0xA7,0x24,0x4A,0xB2,0xB4,0xAE,0xA7,0x9F,0x85,0x80,0x82,0x85,0x8C,0x96,0xA4,0xAD,0xB5,0xBB,0xC3,0xC7,0xC9,0xCB,0xCE,0xD1,0xD0,0xDE,0xCF,0xD5,0xEF,0xFE,0xFE,0xFE,0xFD,0xE8,0x00,0x00,0x00,0xF4,0xFE,0xFE,0xC2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x35,0xBD,0x8C,0x1F,0x91,0xB8,0x9F,0x36,0x25,0x2E,0x1E,0x26,0x34,0x37,0x3C,0x45,0x55,0x68,0x79,0x6A,0x43,0x51,0x56,0x28,0x99,0xC7,0xAE,0x39,0x42,0xB5,0xBD,0xB7,0xB2,0xAC,0xA6,0x97,0x83,0x85,0x8A,0x91,0x9A,0xA6,0xB1,0xBA,0xBF,0xC6,0xCB,0xCD,0xCF,0xD6,0xF2,0xF2,0xEF,0xF1,0xF6,0xF9,0xFC,0xFD,0xD5,0x6C,0x64,0x00, - 0x00,0x00,0xF1,0xFE,0xFE,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xBA,0x83,0x20,0x86,0xB2,0xAA,0x67,0x14,0x2A,0x2F,0x2C,0x25,0x29,0x31,0x35,0x37,0x43,0x4F,0x50,0x36,0x5E,0xBC,0xD0,0xAE,0x3A,0x4A,0xBC,0xC9,0xC1,0xBA,0xB4,0xAD,0xA4,0x9B,0x8D,0x87,0x8E,0x95,0x9B,0xA8,0xB5,0xBE,0xC3,0xC8, - 0xCD,0xD0,0xD3,0xDC,0xFB,0xFD,0xF6,0xF6,0xF9,0xF9,0xFB,0xFD,0xAE,0x00,0x00,0x00,0x00,0x00,0xEF,0xFC,0xFC,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0xB0,0x8C,0x25,0x63,0xA8,0xB4,0xA0,0x6E,0x25,0x1C,0x2C,0x38,0x43,0x49,0x47,0x36,0x18,0x69,0xB2,0xD7,0xD4,0x93,0x24,0x71,0xC3,0xCE,0xBB, - 0x9B,0x79,0x5B,0x37,0x00,0x00,0x00,0x00,0x1C,0x4C,0x69,0x8B,0xB2,0xC2,0xC6,0xCC,0xD0,0xD3,0xD7,0xDF,0xF4,0xF6,0xF3,0xF6,0xF9,0xFA,0xFC,0xE9,0x45,0x00,0x00,0x00,0x00,0x00,0x3D,0x3F,0x3D,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x99,0x99,0x48,0x32,0x81,0xAA,0xB2,0xB2,0xA0,0x8D, - 0x80,0x79,0x7F,0x92,0xAA,0xCC,0xDC,0xD8,0xAE,0x59,0x3E,0x8E,0xA2,0x7D,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x98,0xBB,0xD2,0xD8,0xDD,0xE3,0xE8,0xEC,0xF1,0xF8,0xFB,0xFA,0xD1,0x57,0x00,0x67,0xA7,0xA9,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x9A,0x76,0x3B,0x2A,0x6B,0x92,0xAE,0xBC,0xBF,0xC0,0xC5,0xCC,0xD0,0xBB,0x95,0x54,0x1E,0x32,0x50,0x22,0x1E,0x21,0x36,0x48,0x55,0x59,0x56,0x52,0x49,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x75,0x9A,0xB5,0xC5,0xCA,0xCD,0xC2,0xA5,0x5D,0x00,0x00,0x00,0x9D,0xFE,0xFE, - 0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x71,0x8F,0x7C,0x5D,0x38,0x1F,0x34,0x59,0x66,0x67,0x55,0x27,0x1E,0x1E,0x25,0x45,0x60,0x6E,0x77,0x7D,0x86,0x86,0x85,0x85,0x82,0x7F,0x7C,0x77,0x73,0x6F,0x65,0x58,0x42,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0xFD,0xFC,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2D,0x61,0x81,0x92,0x8D,0x88,0x89,0x8A,0x8A,0x8B,0x8D,0x93,0x9A,0xA1,0xA0,0x9B,0x94,0x8E,0x88,0x83,0x78,0x72, - 0x72,0x70,0x6D,0x69,0x66,0x65,0x63,0x62,0x69,0x71,0x6F,0x5D,0x2D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x62,0x7C, - 0x94,0xA1,0xA8,0xA8,0xA7,0xA4,0x9F,0x92,0x81,0x70,0x5E,0x4A,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xAC, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x9A, 0xEF, 0xFD, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xD9, 0xFE, 0xFE, 0xFE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xA9, 0xAA, 0xAB, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xF7, 0xFE, 0xFE, 0xFE, 0xFD, 0x48, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFE, 0xFE, 0xFD, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xC6, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0x6D, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xFE, 0xFE, 0xFD, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xE4, 0xFD, 0xFE, 0xFD, + 0xFE, 0xFE, 0xFE, 0xFE, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xD6, 0xD5, 0xD4, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xF5, 0xFE, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xEA, 0x00, 0x37, 0x6E, 0xAA, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC8, 0xFA, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xF9, 0xFC, 0xFE, 0xFE, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0xD7, 0xD9, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xA2, 0xEC, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7D, 0xFE, 0xFE, 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, 0x68, 0xA9, 0xDA, 0xE9, 0xF2, 0xF8, 0xFA, 0xFB, 0xFD, 0xFD, 0xFD, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x44, 0x00, 0x00, 0x55, 0x87, 0x88, 0x8B, 0x43, 0x6F, 0xE5, 0xE3, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x62, 0x67, 0x53, 0x41, 0x37, 0x37, 0x42, 0x53, + 0x66, 0x80, 0xA0, 0xC1, 0xD1, 0xD8, 0xDE, 0xE5, 0xEE, 0xF6, 0xF8, 0xFA, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xD0, 0xCE, 0xD0, 0xE4, 0xFE, 0xFE, 0xFE, 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, 0x00, 0x00, 0x69, 0x9E, 0xBB, + 0xC8, 0xCE, 0xCC, 0xC1, 0xA6, 0x79, 0x00, 0x00, 0x00, 0x60, 0x8D, 0xA1, 0x96, 0x90, 0x98, 0xA1, 0xAA, 0xB3, 0xBE, 0xC7, 0xCE, 0xD3, 0xDA, 0xE1, 0xE9, 0xF1, 0xF7, 0xF8, 0xFB, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAF, 0xE9, 0xFC, 0xFB, 0xF4, 0xEA, 0xE8, 0xEA, 0xF1, 0xF6, 0xF7, 0xEC, 0xBD, 0x5F, 0x1E, 0x1E, 0x53, 0x85, 0x8C, 0x97, 0xA1, 0xAB, 0xB2, 0xBB, 0xC2, 0xC8, 0xCD, 0xD5, 0xDD, 0xE4, 0xED, 0xF3, 0xF7, 0xFB, 0xFD, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0x71, 0x00, 0x00, 0x00, 0x7F, 0xBE, 0xBE, 0xBF, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xE8, 0xF6, 0xDB, 0xA8, 0x69, 0x2D, 0x25, 0x2D, 0x26, 0x29, 0x5E, 0x99, 0xCE, 0xEE, 0xEB, 0xB2, 0x3C, 0x1E, 0x26, 0x6C, 0x91, 0x9C, 0xA7, 0xAF, 0xB7, 0xBD, 0xC3, 0xCA, 0xD0, 0xD7, 0xDE, 0xE8, 0xF0, 0xF5, 0xFA, 0xFC, 0xFE, 0xFD, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x6F, 0x00, 0x00, 0x00, 0xA9, 0xFE, 0xFE, 0xFD, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xD8, 0xF2, 0xC4, 0x70, 0x31, 0x4C, 0x4D, 0x4F, 0x49, 0x48, 0x45, 0x4B, 0x4D, 0x48, 0x27, 0x69, 0xC2, 0xE4, 0xD9, 0x71, 0x1E, 0x1E, 0x64, 0x97, + 0xA3, 0xAC, 0xB3, 0xB9, 0xBF, 0xC6, 0xCC, 0xD2, 0xDA, 0xE3, 0xED, 0xF4, 0xFA, 0xFD, 0xFE, 0xFD, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFD, 0xF6, 0xF2, 0xFB, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0x9D, 0x00, 0x00, 0x00, 0xA9, 0xFE, 0xFE, 0xFD, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xEF, 0xE6, 0x89, 0x2C, 0x4E, 0x4B, 0x2E, 0x3F, 0x4A, + 0x4F, 0x4C, 0x48, 0x40, 0x31, 0x21, 0x34, 0x42, 0x28, 0x86, 0xDD, 0xE2, 0x84, 0x1E, 0x1E, 0x6E, 0x9E, 0xA8, 0xAE, 0xB4, 0xBA, 0xC0, 0xC5, 0xCC, 0xD3, 0xDC, 0xEC, 0xFC, 0xEE, 0xFA, 0xFD, 0xFD, 0xFE, 0xEC, 0xF5, 0xFC, 0xFD, 0xFD, 0xFD, 0xDC, 0xF3, 0xFC, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xA9, 0x00, 0x00, 0x00, 0x87, 0xC9, 0xC9, 0xC7, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0xEF, 0xD8, 0x5B, 0x42, 0x4B, 0x34, 0x52, 0x58, 0x41, 0x2C, 0x29, 0x27, 0x1E, 0x1E, 0x26, 0x31, 0x31, 0x21, 0x38, 0x39, 0x61, 0xD3, 0xDC, 0x7A, 0x1E, 0x20, 0x80, 0xA1, 0xA9, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCD, 0xD4, 0xE5, 0xFE, 0xE4, 0xE8, 0xFA, 0xFB, 0xFE, 0xEF, 0xDF, 0xFA, 0xFD, 0xFD, 0xFE, 0xE1, 0xEA, 0xFC, 0xFC, 0xFD, 0xFD, 0xFC, 0xFD, 0xFC, + 0xE0, 0xCA, 0xCB, 0xCC, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xE7, 0xD7, 0x4A, 0x4B, 0x3C, 0x42, 0x52, 0x35, 0x7B, 0xBF, 0xAA, 0x95, 0x6D, 0x49, 0x35, 0x22, 0x10, 0x16, 0x2E, 0x28, 0x29, 0x3B, 0x55, 0xD2, 0xD6, 0x56, 0x1E, 0x35, 0x96, 0xA3, 0xA8, 0xAD, 0xB3, 0xB9, 0xC0, 0xC7, 0xCE, 0xEB, 0xFE, 0xE4, 0xD7, 0xF5, 0xF7, + 0xFE, 0xEE, 0xD4, 0xF6, 0xFC, 0xFE, 0xFE, 0xDE, 0xE8, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFB, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xF0, 0xF0, 0xE6, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xE0, 0x66, 0x3C, 0x39, 0x3F, 0x44, 0x4B, 0xD1, 0xFE, 0xFF, 0xE6, 0x95, 0x66, 0x43, 0x2F, 0x20, 0x17, 0x11, 0x07, 0x20, 0x2C, 0x24, 0x3B, 0x68, 0xD4, 0xB8, 0x1F, + 0x1E, 0x67, 0x9B, 0xA0, 0xA7, 0xAD, 0xB4, 0xBA, 0xC1, 0xCB, 0xFA, 0xFD, 0xD1, 0xD3, 0xF0, 0xFA, 0xFD, 0xDC, 0xD3, 0xF5, 0xFB, 0xFE, 0xF5, 0xDA, 0xF0, 0xFB, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFD, 0xFD, 0xFC, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFE, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0x8F, 0xE9, 0x9F, 0x26, 0x3C, 0x36, 0x3D, 0x45, 0xE9, 0xFF, 0xFF, 0xFF, 0xF1, + 0x8F, 0x5A, 0x38, 0x26, 0x1A, 0x14, 0x11, 0x0E, 0x05, 0x1C, 0x28, 0x2E, 0x2C, 0x9E, 0xD2, 0x7B, 0x1E, 0x26, 0x8C, 0x99, 0xA0, 0xA6, 0xAD, 0xB3, 0xB8, 0xE9, 0xFE, 0xED, 0xC1, 0xDF, 0xF6, 0xFE, 0xF7, 0xC3, 0xDE, 0xF8, 0xFD, 0xFD, 0xE5, 0xE6, 0xF9, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xFE, 0xFE, 0xF0, + 0x00, 0x00, 0x00, 0xD2, 0xD7, 0x35, 0x43, 0x27, 0x3D, 0x27, 0xB3, 0xFD, 0xFE, 0xFE, 0xFE, 0xD1, 0x9F, 0x81, 0x5A, 0x37, 0x11, 0x10, 0x0E, 0x0B, 0x04, 0x01, 0x20, 0x21, 0x35, 0x3C, 0xC4, 0xB5, 0x1E, 0x1E, 0x6A, 0x91, 0x98, 0xA0, 0xA4, 0xA3, 0xC4, 0xFE, 0xFB, 0xB0, 0xC1, 0xEA, 0xFE, 0xFE, 0xCC, 0xC5, 0xEC, 0xFB, 0xFE, 0xE8, 0xE0, 0xF2, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, + 0xFE, 0xFD, 0xFD, 0xFC, 0xC4, 0xB9, 0xBA, 0xBB, 0xC1, 0xC3, 0xC5, 0xC8, 0x78, 0x6C, 0x6A, 0x65, 0x00, 0x00, 0x6C, 0xE3, 0xA1, 0x28, 0x33, 0x38, 0x24, 0x7E, 0xB4, 0xD1, 0xF0, 0xEC, 0xE7, 0xC7, 0x88, 0x54, 0x36, 0x2B, 0x2A, 0x17, 0x06, 0x04, 0x01, 0x03, 0x06, 0x28, 0x20, 0x2F, 0x97, 0xC1, 0x5F, 0x1E, 0x42, 0x79, 0x74, 0x75, 0x76, 0x77, 0xF0, 0xFE, 0xCE, 0x99, 0xC9, 0xF0, 0xFE, 0xEF, + 0xBE, 0xDA, 0xF1, 0xFE, 0xFE, 0xCF, 0xEB, 0xFC, 0xFE, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xDE, 0x5F, 0x3C, 0x24, 0x35, 0x1B, 0x90, 0x97, 0x98, 0x93, 0xBD, 0xA1, 0x81, 0x5A, 0x32, 0x1B, 0x10, 0x0E, 0x1D, 0x17, 0x01, 0x05, 0x0A, 0x09, 0x20, 0x22, 0x38, 0x62, 0xBC, + 0x8B, 0x1E, 0x1F, 0x5E, 0x61, 0x67, 0x6D, 0x9C, 0xFE, 0xFE, 0xAE, 0xB7, 0xC6, 0xF5, 0xFE, 0xDF, 0xD1, 0xED, 0xF6, 0xFE, 0xFE, 0xC5, 0xF1, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xD2, 0x20, 0x3C, 0x2B, 0x27, 0x44, 0x77, 0x73, 0x71, 0x81, 0x82, 0x5F, 0x35, + 0xC9, 0xEE, 0x66, 0x10, 0x05, 0x11, 0x1F, 0x07, 0x0B, 0x13, 0x1A, 0x15, 0x2A, 0x37, 0x1F, 0xB4, 0x9D, 0x1E, 0x1E, 0x55, 0x5E, 0x61, 0x66, 0xA4, 0xFE, 0xFE, 0xB4, 0xB7, 0xC4, 0xF5, 0xFE, 0xE7, 0xD0, 0xED, 0xF3, 0xFE, 0xFE, 0xD5, 0xEF, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0x7F, 0x00, 0x00, 0x00, + 0x58, 0x00, 0xC8, 0xBE, 0x10, 0x39, 0x2D, 0x1B, 0x49, 0x54, 0x4E, 0x49, 0x73, 0x39, 0x29, 0x4E, 0xF2, 0xF8, 0x6A, 0x2A, 0x18, 0x14, 0x1D, 0x22, 0x13, 0x1E, 0x28, 0x0E, 0x31, 0x34, 0x27, 0xA5, 0xAA, 0x1E, 0x1E, 0x4D, 0x5C, 0x5D, 0x62, 0x81, 0xFC, 0xFE, 0xD6, 0xA1, 0xB3, 0xDF, 0xFE, 0xFC, 0xD5, 0xE0, 0xE1, 0xEF, 0xFE, 0xF8, 0xE2, 0xF1, 0xF9, 0xFC, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, + 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, 0xF9, 0xA7, 0xA1, 0x9C, 0x96, 0x8F, 0x48, 0x00, 0x00, 0x00, 0x7C, 0x00, 0xCD, 0xB2, 0x1A, 0x2F, 0x2D, 0x12, 0x1D, 0x1F, 0x1D, 0x1A, 0x43, 0x20, 0x06, 0x29, 0x44, 0x4A, 0x23, 0x37, 0x3A, 0x16, 0x2F, 0x32, 0x20, 0x2B, 0x35, 0x19, 0x34, 0x33, 0x33, 0x9B, 0xAF, 0x1F, 0x1E, 0x4B, 0x5C, 0x5D, 0x61, 0x62, 0xCC, 0xFE, 0xFC, 0xA9, 0x9D, 0xB0, 0xF2, 0xFE, + 0xF7, 0xD8, 0xD2, 0xAC, 0xF7, 0xFE, 0xF5, 0xD7, 0xF2, 0xFA, 0xFE, 0xFD, 0xFD, 0xFD, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFD, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xD4, 0xD5, 0x95, 0x00, 0x97, 0x00, 0xCA, 0xB1, 0x18, 0x2B, 0x2B, 0x11, 0x15, 0x19, 0x17, 0x12, 0x2C, 0x10, 0x01, 0x0A, 0x0D, 0x20, 0x36, 0x4D, 0x4C, 0x25, 0x44, 0x46, 0x33, 0x3D, 0x47, 0x20, 0x39, 0x34, 0x35, 0x98, + 0xAF, 0x20, 0x1E, 0x4D, 0x5E, 0x60, 0x63, 0x64, 0x69, 0xE4, 0xFE, 0xF4, 0x9F, 0xAF, 0xA1, 0xF8, 0xFE, 0xF0, 0xCC, 0x9E, 0xB4, 0xFC, 0xFE, 0xE3, 0xDF, 0xF6, 0xFC, 0xFC, 0xFC, 0xFB, 0xFD, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFC, 0xFC, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x6E, 0xFE, 0xFE, 0xB1, 0x00, 0xA5, 0x00, 0xC0, 0xB8, 0x10, 0x2D, 0x28, 0x16, 0x0F, 0x14, 0x10, 0x0A, 0x1E, 0x04, 0x01, 0x04, + 0x1A, 0x31, 0x4A, 0x62, 0x3C, 0x41, 0x54, 0x58, 0x4B, 0x53, 0x5D, 0x1D, 0x42, 0x38, 0x2F, 0x9D, 0xAC, 0x1F, 0x1E, 0x55, 0x62, 0x64, 0x66, 0x67, 0x65, 0x7C, 0xF7, 0xFE, 0xC8, 0x80, 0x86, 0xBB, 0xFE, 0xFE, 0xA3, 0x99, 0x9A, 0xD2, 0xFE, 0xFA, 0xD1, 0xEA, 0xF6, 0xF9, 0xFC, 0xFB, 0xFC, 0xFC, 0xFE, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xDA, 0xD9, 0x99, 0x00, + 0xB8, 0x00, 0xAE, 0xC5, 0x1A, 0x2E, 0x24, 0x1E, 0x0A, 0x0E, 0x08, 0x01, 0x17, 0x0C, 0x06, 0x01, 0x16, 0x36, 0x4A, 0x3A, 0x35, 0x64, 0x73, 0x5E, 0x67, 0x6E, 0x6B, 0x22, 0x48, 0x3C, 0x1F, 0xA9, 0xA2, 0x1E, 0x1E, 0x5F, 0x66, 0x68, 0x69, 0x69, 0x69, 0x67, 0xCC, 0xFE, 0xEA, 0x73, 0x89, 0x8A, 0xF5, 0xFE, 0xBE, 0x93, 0x9F, 0xA7, 0xFD, 0xFE, 0xD4, 0xE1, 0xF5, 0xF7, 0xFB, 0xFC, 0xFC, 0xFC, + 0xFE, 0xFD, 0xFE, 0xFE, 0xFE, 0xFD, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA, 0x00, 0x95, 0xC8, 0x5D, 0x2D, 0x1D, 0x29, 0x09, 0x03, 0x02, 0x02, 0x01, 0x1F, 0x0C, 0x11, 0x11, 0x15, 0x23, 0x43, 0x67, 0x77, 0x81, 0x7A, 0x85, 0x8B, 0x5F, 0x3A, 0x41, 0x3F, 0x3A, 0xB1, 0x8F, 0x1E, 0x28, 0x69, 0x6A, 0x6C, 0x6C, 0x6B, 0x6D, 0x6C, 0xB1, 0xFE, 0xF2, 0x75, 0x8A, 0x8E, + 0xE5, 0xFE, 0xC2, 0x90, 0xA3, 0xA2, 0xFB, 0xFE, 0xD1, 0xDF, 0xF5, 0xF7, 0xFA, 0xFD, 0xFD, 0xFD, 0xFE, 0xFD, 0xE9, 0xAE, 0xAC, 0xAA, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0x6D, 0x64, 0xC3, 0x8E, 0x21, 0x20, 0x2C, 0x16, 0x03, 0x02, 0x02, 0x07, 0x09, 0x20, 0x23, 0x23, 0x34, 0x46, 0x5A, 0x79, 0x85, 0x89, 0x9B, 0xA2, 0x97, 0x22, 0x50, 0x2F, 0x3A, 0x73, 0xB2, + 0x71, 0x1E, 0x4B, 0x6C, 0x6E, 0x6F, 0x6F, 0x6E, 0x70, 0x70, 0xB7, 0xFE, 0xE8, 0x79, 0x8C, 0x92, 0xE9, 0xFE, 0xB7, 0x96, 0xA9, 0xAD, 0xFD, 0xFA, 0xC5, 0xE2, 0xF6, 0xF9, 0xFB, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xD7, 0x00, 0x00, 0x00, 0x00, 0xC7, 0xF6, 0xF6, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xB0, 0x20, 0xB1, 0xB4, 0x23, 0x2A, 0x1E, 0x28, 0x09, 0x02, 0x07, 0x0E, 0x11, 0x12, 0x1D, + 0x31, 0x41, 0x55, 0x66, 0x6D, 0x8B, 0xAB, 0xB2, 0xB8, 0x5C, 0x44, 0x4F, 0x3B, 0x20, 0xA7, 0xB5, 0x38, 0x1E, 0x84, 0x6E, 0x70, 0x71, 0x72, 0x72, 0x73, 0x76, 0xD6, 0xFE, 0xC4, 0x80, 0x92, 0x9D, 0xFB, 0xF9, 0x9A, 0xA1, 0xAF, 0xCA, 0xFE, 0xE3, 0xC2, 0xEB, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xD7, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xFD, 0xFD, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0xDD, 0x29, 0x80, 0xBE, 0x81, 0x1F, 0x28, 0x28, 0x24, 0x08, 0x0D, 0x13, 0x18, 0x1F, 0x28, 0x30, 0x3A, 0x4D, 0x65, 0x81, 0x9B, 0xCB, 0xF5, 0x8B, 0x3D, 0x68, 0x39, 0x46, 0x66, 0xBD, 0x94, 0x1E, 0x4E, 0xA2, 0x7D, 0x73, 0x74, 0x75, 0x76, 0x76, 0x8A, 0xF9, 0xF5, 0x87, 0x8F, 0x9C, 0xCD, 0xFE, 0xD2, 0xA2, 0xB1, 0xB4, 0xEF, 0xFA, 0xBC, 0xCA, 0xF2, 0xFD, 0xFE, 0xFC, 0xFA, 0xFB, 0xFD, + 0xFD, 0xFC, 0xD6, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFD, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x93, 0x29, 0xB0, 0xBA, 0x47, 0x2F, 0x20, 0x2D, 0x20, 0x09, 0x14, 0x23, 0x2D, 0x37, 0x43, 0x4E, 0x5D, 0x6F, 0x86, 0xA1, 0xB0, 0x85, 0x41, 0x7A, 0x48, 0x57, 0x29, 0xAD, 0xB8, 0x48, 0x1E, 0x93, 0xA5, 0x95, 0x7A, 0x78, 0x79, 0x7A, 0x7C, 0xD7, 0xFE, 0xB0, 0x8C, 0xA2, 0xB0, 0xF9, + 0xED, 0xAA, 0xB3, 0xC0, 0xD5, 0xFC, 0xCC, 0xBA, 0xD7, 0xF2, 0xFD, 0xFD, 0xFD, 0xFC, 0xFA, 0xE9, 0xE7, 0xE6, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x69, 0x7A, 0x78, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xCF, 0x3C, 0x65, 0xBC, 0xA8, 0x28, 0x35, 0x1E, 0x29, 0x28, 0x11, 0x12, 0x2A, 0x42, 0x58, 0x64, 0x70, 0x79, 0x79, 0x63, 0x20, 0x5F, 0x82, 0x50, 0x5F, 0x30, 0x96, 0xBE, 0x86, 0x1E, + 0x6E, 0xB1, 0xA9, 0xA2, 0x88, 0x7E, 0x7D, 0x7E, 0x89, 0xD4, 0xC3, 0x90, 0xA2, 0xAE, 0xBD, 0xD9, 0xBE, 0xBB, 0xC4, 0xC8, 0xC9, 0xCA, 0xD0, 0xC8, 0xD1, 0xEE, 0xFD, 0xFD, 0xFD, 0xFE, 0xEA, 0x00, 0x00, 0x00, 0x55, 0x63, 0x6E, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0xAB, 0x1E, 0x85, 0xBA, 0x9E, 0x23, 0x2E, 0x20, 0x24, 0x2E, 0x25, 0x18, 0x11, + 0x19, 0x22, 0x25, 0x16, 0x22, 0x54, 0x78, 0x75, 0x45, 0x62, 0x31, 0x87, 0xC2, 0xA7, 0x24, 0x4A, 0xB2, 0xB4, 0xAE, 0xA7, 0x9F, 0x85, 0x80, 0x82, 0x85, 0x8C, 0x96, 0xA4, 0xAD, 0xB5, 0xBB, 0xC3, 0xC7, 0xC9, 0xCB, 0xCE, 0xD1, 0xD0, 0xDE, 0xCF, 0xD5, 0xEF, 0xFE, 0xFE, 0xFE, 0xFD, 0xE8, 0x00, 0x00, 0x00, 0xF4, 0xFE, 0xFE, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x35, 0xBD, 0x8C, 0x1F, 0x91, 0xB8, 0x9F, 0x36, 0x25, 0x2E, 0x1E, 0x26, 0x34, 0x37, 0x3C, 0x45, 0x55, 0x68, 0x79, 0x6A, 0x43, 0x51, 0x56, 0x28, 0x99, 0xC7, 0xAE, 0x39, 0x42, 0xB5, 0xBD, 0xB7, 0xB2, 0xAC, 0xA6, 0x97, 0x83, 0x85, 0x8A, 0x91, 0x9A, 0xA6, 0xB1, 0xBA, 0xBF, 0xC6, 0xCB, 0xCD, 0xCF, 0xD6, 0xF2, 0xF2, 0xEF, 0xF1, 0xF6, 0xF9, 0xFC, 0xFD, 0xD5, 0x6C, 0x64, 0x00, + 0x00, 0x00, 0xF1, 0xFE, 0xFE, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xBA, 0x83, 0x20, 0x86, 0xB2, 0xAA, 0x67, 0x14, 0x2A, 0x2F, 0x2C, 0x25, 0x29, 0x31, 0x35, 0x37, 0x43, 0x4F, 0x50, 0x36, 0x5E, 0xBC, 0xD0, 0xAE, 0x3A, 0x4A, 0xBC, 0xC9, 0xC1, 0xBA, 0xB4, 0xAD, 0xA4, 0x9B, 0x8D, 0x87, 0x8E, 0x95, 0x9B, 0xA8, 0xB5, 0xBE, 0xC3, 0xC8, + 0xCD, 0xD0, 0xD3, 0xDC, 0xFB, 0xFD, 0xF6, 0xF6, 0xF9, 0xF9, 0xFB, 0xFD, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xFC, 0xFC, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xB0, 0x8C, 0x25, 0x63, 0xA8, 0xB4, 0xA0, 0x6E, 0x25, 0x1C, 0x2C, 0x38, 0x43, 0x49, 0x47, 0x36, 0x18, 0x69, 0xB2, 0xD7, 0xD4, 0x93, 0x24, 0x71, 0xC3, 0xCE, 0xBB, + 0x9B, 0x79, 0x5B, 0x37, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x4C, 0x69, 0x8B, 0xB2, 0xC2, 0xC6, 0xCC, 0xD0, 0xD3, 0xD7, 0xDF, 0xF4, 0xF6, 0xF3, 0xF6, 0xF9, 0xFA, 0xFC, 0xE9, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x3F, 0x3D, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x99, 0x99, 0x48, 0x32, 0x81, 0xAA, 0xB2, 0xB2, 0xA0, 0x8D, + 0x80, 0x79, 0x7F, 0x92, 0xAA, 0xCC, 0xDC, 0xD8, 0xAE, 0x59, 0x3E, 0x8E, 0xA2, 0x7D, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x98, 0xBB, 0xD2, 0xD8, 0xDD, 0xE3, 0xE8, 0xEC, 0xF1, 0xF8, 0xFB, 0xFA, 0xD1, 0x57, 0x00, 0x67, 0xA7, 0xA9, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x9A, 0x76, 0x3B, 0x2A, 0x6B, 0x92, 0xAE, 0xBC, 0xBF, 0xC0, 0xC5, 0xCC, 0xD0, 0xBB, 0x95, 0x54, 0x1E, 0x32, 0x50, 0x22, 0x1E, 0x21, 0x36, 0x48, 0x55, 0x59, 0x56, 0x52, 0x49, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x75, 0x9A, 0xB5, 0xC5, 0xCA, 0xCD, 0xC2, 0xA5, 0x5D, 0x00, 0x00, 0x00, 0x9D, 0xFE, 0xFE, + 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x71, 0x8F, 0x7C, 0x5D, 0x38, 0x1F, 0x34, 0x59, 0x66, 0x67, 0x55, 0x27, 0x1E, 0x1E, 0x25, 0x45, 0x60, 0x6E, 0x77, 0x7D, 0x86, 0x86, 0x85, 0x85, 0x82, 0x7F, 0x7C, 0x77, 0x73, 0x6F, 0x65, 0x58, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xFD, 0xFC, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x61, 0x81, 0x92, 0x8D, 0x88, 0x89, 0x8A, 0x8A, 0x8B, 0x8D, 0x93, 0x9A, 0xA1, 0xA0, 0x9B, 0x94, 0x8E, 0x88, 0x83, 0x78, 0x72, + 0x72, 0x70, 0x6D, 0x69, 0x66, 0x65, 0x63, 0x62, 0x69, 0x71, 0x6F, 0x5D, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x62, 0x7C, + 0x94, 0xA1, 0xA8, 0xA8, 0xA7, 0xA4, 0x9F, 0x92, 0x81, 0x70, 0x5E, 0x4A, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; const lv_image_dsc_t ui_img_logo_80x44_png = { .header.w = 80, diff --git a/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c b/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c index 0aadb66..fa44d7a 100644 --- a/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c +++ b/main/Application/Tasks/GUI/Export/images/ui_img_text_218x40_png.c @@ -6,286 +6,286 @@ #include "../ui.h" #ifndef LV_ATTRIBUTE_MEM_ALIGN - #define LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN #endif // IMAGE DATA: assets/Text_218x40.png const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_text_218x40_png_data[] = { - 0xE1,0x18,0xE2,0x10,0x02,0x19,0x02,0x11,0xC1,0x00,0xA1,0x00,0xC1,0x08,0x02,0x19,0x22,0x21,0x22,0x19,0x22,0x21,0x22,0x21,0x42,0x21,0x42,0x21,0x02,0x21,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,0xE6,0x08,0xE5,0x10,0xA4,0x00,0x23,0x00,0x23,0x00,0x84,0x00,0xC5,0x10,0x46,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC5,0x10,0x26,0x19,0x46,0x21,0x46,0x21,0x67,0x21,0xA7,0x29,0xA8,0x29,0xE5,0x10,0x92,0x94,0x9A,0xD6,0xFB,0xDE,0xFB,0xDE, - 0xFB,0xDE,0xFB,0xDE,0xDB,0xDE,0x14,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA7,0x31,0x79,0xCE,0x1C,0xE7,0x3C,0xE7,0x5D,0xE7,0x5D,0xEF,0x3D,0xE7,0x39,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xCD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x41,0xDD,0x41,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x61,0xDD,0x62,0xDD,0x61,0xDD,0x02,0xCD,0xA3,0xBC,0xA2,0x93,0xA1,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xBE,0xDB,0xDE,0xDB,0xDE,0xBB,0xD6,0xBB,0xD6,0xDB,0xDE,0xDB,0xDE,0x39,0xC6, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x6B,0x7A,0xCE,0xDB,0xDE,0xDB,0xDE,0xDB,0xDE,0xDB,0xDE,0xFB,0xDE,0xBA,0xD6,0xCC,0x52,0x38,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x73,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xED,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE, - 0x20,0xFE,0x20,0xFE,0x20,0xFE,0x20,0xFE,0x21,0xFE,0x41,0xFE,0x21,0xF6,0xA1,0xE5,0x61,0xB4,0x21,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xEF,0xF0,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xAD,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xDE,0x93,0x8C,0x1C,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x7C,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5D,0xEF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x21,0xFE,0x21,0xFE,0x21,0xFE,0x41,0xFE,0x81,0xE5,0x21,0xAC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x8C,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBA,0xD6,0x00,0x00,0xFB,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x6B,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x00,0xFE,0x20,0xFE,0x20,0xFE,0xE1,0xF5,0x21,0xBC, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x6B,0x1C,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAF,0x73,0x3D,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xD3,0x9C,0x00,0x00,0xB7,0xAD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x4A,0x5D,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0x7A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x81,0xED,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0x00,0xFE,0x61,0xED,0x61,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0x0C,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0xEC,0x5A,0x00,0x00,0x00,0x00,0xB3,0x94, - 0x39,0xC6,0xD3,0x94,0x76,0xAD,0x7A,0xCE,0xF4,0x9C,0x6A,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x73,0x8C,0x7A,0xCE,0xDB,0xD6,0x7A,0xC6,0x5A,0xC6,0x76,0xAD,0x29,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xED,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0x21,0xDD,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x21,0xE5,0x01,0xE5,0x21,0xE5,0xA0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xE0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0x61,0xCC,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7B,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x92,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x00,0xF8,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x59,0xCE,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xED,0xA0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xA1,0xFD,0xC2,0x82,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0x41,0x81,0xA3,0xE1,0xD4,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xC0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x21,0xED,0x62,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x31,0x41,0x6A,0xA2,0xB3,0x82,0xAB,0x61,0x72,0x01,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x41,0xC3,0x7A,0x22,0x93,0x82,0xA3,0x81,0xA3,0x61,0x9B,0x41,0x72,0x81,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x3A,0xFC,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,0xC6,0xE4,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x6B,0xDB,0xDE,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x14,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x42,0xCF,0x73,0xF3,0x9C,0xF4,0x9C,0x14,0xA5,0xD3,0x9C,0xB3,0x94,0x6A,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x08,0x88,0x31,0x6E,0x6B,0xB3,0x94,0xF4,0x9C,0xF4,0x9C,0xB3,0x94,0x31,0x84,0x4A,0x4A,0xAC,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0x00,0x8B,0x01,0x6B,0x00,0x8B,0x01,0x2B,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x52,0xB3,0x94,0x14,0x9D,0x14,0xA5,0xB3,0x94,0x11,0x7C,0xC8,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xED,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0xC1,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x62,0xE1,0xD4,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x82,0xA3,0x22,0xAC,0xA0,0xD4,0xA0,0xD4,0xA0,0xD4,0xA1,0xCC,0xA1,0xCC,0xA1,0xCC,0x61,0xC4,0x03,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xC4,0x81,0xD4,0x81,0xCC,0x60,0xCC, - 0x60,0xCC,0x80,0xCC,0xA0,0xCC,0x22,0xB4,0x00,0x00,0x03,0xAC,0xA1,0xCC,0xA0,0xCC,0xA1,0xCC,0xA1,0xD4,0x80,0xD4,0xE1,0xB3,0x00,0x00,0x00,0x00,0xC2,0x72,0x01,0xB4,0x01,0xE5,0x61,0xF5,0xA1,0xFD,0x81,0xFD,0x60,0xF5,0xA1,0xD4,0x62,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6A,0xC1,0xA3,0xE1,0xD4,0x41,0xED,0xA1,0xF5,0xC1,0xFD,0xC1,0xFD,0xC1,0xFD,0xC1,0xFD,0xA1,0xF5,0x61,0xED,0xC1,0xD4,0xA1,0xA3,0x21,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xDE,0xEF,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x31,0x84,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0xE7,0x2D,0x63,0x00,0x00,0x00,0x00,0x76,0xAD,0x9A,0xCE,0x9A,0xD6,0x9A,0xD6,0xBA,0xD6,0xBA,0xD6,0x9A,0xD6,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4E,0x6B,0x96,0xB5,0xBA,0xD6,0x7D,0xEF,0xBE,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0xDB,0xDE,0x59,0xCE,0xB3,0x94,0x0D,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x7C,0x39,0xC6,0x79,0xCE,0x79,0xCE,0x79,0xCE,0x79,0xCE,0x79,0xCE,0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x7B,0x55,0xA5,0x9A,0xD6, - 0x3D,0xE7,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBF,0xF7,0x7D,0xEF,0xBA,0xD6,0x18,0xC6,0x52,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6A,0x4A,0xB7,0xB5,0x9A,0xCE,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x7A,0xCE,0x14,0xA5,0x00,0x00,0xF0,0x7B,0x76,0xAD,0xDB,0xDE,0x7E,0xEF,0xDF,0xF7,0xDF,0xFF,0xFF,0xFF,0xDF,0xFF,0xBE,0xF7,0x5D,0xE7,0xBB,0xD6,0x35,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xED,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0xA1,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x7A,0x61,0xF5,0x80,0xFD,0x80,0xFD,0x80,0xFD, - 0x80,0xFD,0x80,0xFD,0x80,0xFD,0x42,0xCC,0xE1,0x8A,0x80,0xFD,0x80,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x60,0xF5,0x42,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xDC,0x80,0xFD,0x80,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x80,0xFD,0x81,0xA3,0x00,0x00,0x62,0xC4,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0x80,0xFD,0x80,0xFD,0x00,0xED,0x81,0x08,0xC2,0xAB,0x01,0xE5,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0xC1,0xE4,0x81,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x92,0xE1,0xB3,0x01,0xE5,0x80,0xFD,0x80,0xFD,0xA0,0xFD,0xA0,0xFD,0xA0,0xFD,0xA1,0xFD,0xA1,0xFD,0xA1,0xFD,0xA1,0xFD, - 0xC1,0xFD,0xC1,0xFD,0xA1,0xFD,0x01,0xDD,0x81,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x84,0x7E,0xEF,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x71,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xC6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x79,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xBD,0xFF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x35,0xA5,0xFC,0xDE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0x9E,0xF7,0xDB,0xDE,0x51,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0xEA,0x31,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDB,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xAD,0x3C,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xEF,0xF8,0xBD,0x30,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x4A,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,0xC6,0x92,0x8C,0xBB,0xD6,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xBE,0xF7,0xF8,0xBD,0x00,0x00,0x00,0x00,0x21,0xED,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x60,0xFD,0xA2,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x62,0xA1,0xDC,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x41,0xCC,0xE1,0x9A,0xC1,0xDC,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x21,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x93,0x40,0xF5,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x60,0xFD,0xE1,0xE4,0x41,0x39,0x00,0x00,0x22,0xC4,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x40,0xFD,0xE1,0xEC, - 0xE1,0x8A,0x20,0xF5,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x61,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x49,0x01,0xC4,0x20,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x80,0xFD,0x81,0xFD,0xA1,0xFD,0x61,0xF5,0xE1,0xBB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBA,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xF7,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x29,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x55,0xAD,0x00,0x00,0x00,0x00,0x00,0x00, - 0xD7,0xB5,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x00,0x76,0xAD,0x9E,0xEF,0xDF,0xFF,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,0x5D,0xEF,0x71,0x8C,0x00,0x00,0x00,0x00,0x46,0x21,0x7E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xF8,0xBD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF, - 0xFC,0xDE,0x55,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0x4A,0xBB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0xD6,0xFC,0xDE,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE,0xF7,0xB6,0xB5,0x00,0x00,0x01,0xED,0x60,0xFD,0x60,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0xA2,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x41,0x61,0xD4,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x41,0xD4,0x00,0x00,0xA1,0xB3,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD, - 0x81,0xDC,0x61,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xC4,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x41,0xCC,0x00,0x00,0x00,0x00,0xE1,0xC3,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x01,0xFD,0xA1,0xE4,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0xC1,0xC3,0x00,0x00,0x00,0x00,0x61,0x49,0x01,0xC4,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x60,0xFD,0x61,0xFD,0x61,0xFD,0x41,0xFD,0xC1,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB6,0xB5, - 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDB,0xD6,0x31,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x5B,0x9E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x3D,0xE7,0x2D,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xB5,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xA5,0x7D,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0xDE,0xAB,0x52,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7, - 0xDF,0xFF,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD7,0xBD,0xBE,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0x9A,0xD6,0x2A,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0x52,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1C,0xE7,0x2D,0x63,0xE0,0xEC,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0x20,0xFD,0x81,0x82, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x72,0x61,0xDC,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x20,0xFD,0x01,0xCC,0x00,0x00,0x01,0x62,0xA0,0xEC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0xE0,0xF4,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xDC,0x20,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x22,0x9B,0x00,0x00,0x00,0x00,0xC1,0xBB,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x81,0xB3,0x00,0x00,0x00,0x00, - 0x82,0xAB,0x00,0xF5,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x40,0xFD,0x40,0xFD,0x40,0xFD,0xE0,0xF4,0x81,0x8A,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x7C,0x7D,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9E,0xEF,0x8E,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7A,0xCE,0xBF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x7A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF7,0xBD,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xD6, - 0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0xBA,0xD6,0xFB,0xDE,0x1C,0xDF,0x9A,0xD6,0xDB,0xDE,0x9E,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0xD3,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0x7E,0xEF,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x7D,0xEF,0x7D,0xEF,0xDF,0xF7,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE,0xF7,0x35,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0xAB,0x52,0xBB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF, - 0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x96,0xAD,0xA0,0xEC,0x00,0xFD,0x20,0xFD,0x20,0xFD,0x20,0xFD,0x00,0xFD,0x00,0xFD,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x59,0xA0,0xEC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0xA1,0xC3,0x00,0x00,0x00,0x00,0x41,0xD4,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0x81,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC2,0x82,0xE0,0xEC,0x00,0xFD,0x00,0xFD, - 0x00,0xFD,0x00,0xFD,0x00,0xFD,0x81,0xE4,0x62,0x82,0x00,0x00,0x00,0x00,0xA1,0xBB,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0xA0,0xFC,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC1,0xF4,0xC1,0xEC,0xA1,0xEC,0xA0,0xF4,0xA0,0xF4,0xA1,0x8A,0x00,0x00,0x00,0x00,0x81,0xE4,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x00,0xFD,0xE0,0xFC,0x21,0xD4,0x62,0xAB,0x02,0x9B,0xE2,0x92,0xA1,0xBB,0x81,0xDC,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x00,0xFD,0x01,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xD6,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0xDF,0xF7,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xDB,0xD6,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xBD,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x08,0x00,0x3C,0xE7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x7D,0xEF,0x14,0xA5,0x2D,0x63,0x00,0x00,0x00,0x00,0x88,0x29,0x8C,0x52,0xAF,0x73,0x7A,0xCE,0x3C,0xE7,0xDF,0xF7,0x18,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x21,0x7E,0xEF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xD6,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7, - 0xDF,0xF7,0xDF,0xF7,0x9E,0xF7,0x39,0xC6,0xB3,0x94,0x8A,0x52,0x6A,0x4A,0x72,0x8C,0xF8,0xBD,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFB,0xDE,0xEC,0x5A,0x00,0x00,0x00,0x00,0xAB,0x52,0xDB,0xD6,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xBE,0xF7,0xBB,0xD6,0xD7,0xB5,0xB7,0xB5,0x18,0xBE,0x38,0xC6,0x1C,0xDF,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x59,0xC6,0xA1,0xEC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xC3,0xC0,0xFC,0xC0,0xFC, - 0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x01,0xA3,0x00,0x00,0x00,0x00,0x62,0xA3,0xC0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xE0,0xD3,0x81,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xAB,0x00,0xFD,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0x21,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xBB,0xA0,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xE1,0xD3,0x63,0xB3,0x83,0x72,0x62,0x39,0x61,0x41,0x81,0x82,0x20,0xA3,0xE1,0x51,0x00,0x00,0xC1,0x9A,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x61,0xB3,0x22,0x31,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x01,0x31,0xA1,0xC3,0xC0,0xFC,0xC0,0xFC,0xE0,0xFC,0xE0,0xFC,0xE0,0xFC,0xC0,0xFC,0x80,0xF4,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xAD,0xBE,0xEF,0xBE,0xF7,0xBE,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBA,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0x52,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0x7D,0xEF,0x6E,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xBD,0xDF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0xC5,0x08,0x9E,0xF7,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xFB,0xDE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x8E,0x6B,0xD7,0xB5,0x0C,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0xBA,0xD6,0x0A,0x00,0x00,0x00,0x00,0x00,0xB3,0x94,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBE,0xF7,0x96,0xB5,0x49,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xA5,0x9E,0xEF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0xBE,0xF7,0x92,0x8C,0x00,0x00,0x00,0x00,0xAB,0x52,0xBB,0xD6,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9E,0xEF,0x76,0xAD,0x4E,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x6B,0xDB,0xD6,0xDF,0xF7, - 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x9A,0xCE,0x81,0xEC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0x61,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x49,0x60,0xBB,0x60,0xF4,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xFC,0x60,0xFC,0x20,0xEC,0x01,0x7A,0x00,0x00,0x00,0x00,0xA1,0x51,0x20,0xE4,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xF4,0x20,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xE1,0xCB,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xC0,0xFC,0xA0,0xFC,0xE1,0xA2,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xBB,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC, - 0x40,0xFC,0x60,0xFC,0x60,0xFC,0xA0,0xCB,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xC3,0x80,0xFC,0x80,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x80,0xFC,0x00,0xE4,0x21,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0x69,0x21,0xE4,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x41,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x84,0x7E,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x5D,0xE7,0xCC,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0xB5,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBB,0xD6,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xD7,0xB5,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x18,0xBE,0x00,0x00,0x00,0x00,0x07,0x01,0xBE,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDB,0xD6,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x29,0x7E,0xEF,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0xBE,0xF7,0xBF,0xF7,0xBA,0xD6,0x0A,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0xBE,0xF7,0xBE,0xF7,0xBE,0xEF,0xBE,0xEF,0xBE,0xF7,0xBF,0xF7,0xFC,0xDE,0x8F,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7A,0xCE,0xDF,0xF7, - 0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x79,0xCE,0x00,0x00,0x00,0x00,0x8B,0x52,0xBB,0xD6,0xBF,0xF7,0xDF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xDF,0xF7,0x79,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xAD,0xBE,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0xDF,0xF7,0x3D,0xE7,0x41,0xEC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x62,0xBB,0xC1,0xC3,0xA1,0xC3,0xA0,0xC3,0x81,0xC3,0x80,0xC3,0x80,0xC3,0x61,0xCB,0xE0,0xE3,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x40,0xCB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBB,0x60,0xFC,0x60,0xFC, - 0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xBB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x7A,0x20,0xE4,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0xA0,0xFC,0x80,0xFC,0x00,0xE4,0xC1,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBB,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0xC0,0xE3,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xDB,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xC3,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x61,0xFC,0x81,0xCB,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A,0xCE,0x9E,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xD7,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0xBF,0xF7,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x00,0x5D,0xE7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBE,0xEF,0x9A,0xCE,0x35,0xA5,0x0C,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x21,0x5D,0xE7,0xBE,0xEF, - 0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBA,0xD6,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0xC6,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0x18,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xB5,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x8B,0x4A,0xBB,0xCE,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xEF,0xBF,0xF7,0x7E,0xEF,0xF4,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x4A,0x3C,0xDF,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xF7,0xBF,0xEF,0x3D,0xE7,0x01,0xEC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC, - 0x60,0xFC,0x60,0xFC,0x60,0xFC,0x60,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xC0,0xF3,0x01,0x8A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x82,0x20,0xF4,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x60,0xFC,0xA0,0xD3,0x81,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0x92,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x80,0xFC,0x60,0xFC,0x61,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xBB,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x40,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xC1,0xE3,0x20,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x01,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xB3,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x40,0xFC,0xA1,0xDB,0x82,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xB7,0xB5,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x32,0xFC,0xD6,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x5D,0xDF,0xF0,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xAD,0xBE,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xF8,0xB5,0x00,0x00,0x00,0x00, - 0x00,0x00,0x9A,0xCE,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0x9E,0xEF,0x5D,0xE7,0xBB,0xD6,0x18,0xBE,0xB3,0x94,0x33,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x21,0x5D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBA,0xCE,0x00,0x00,0x00,0x00,0x87,0x21,0xDB,0xD6,0x7E,0xEF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xEF,0x14,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x9D,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x9E,0xEF,0xBE,0xEF,0xBE,0xEF,0x1C,0xDF,0x00,0x00,0x00,0x00,0x6A,0x42,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF, - 0x9E,0xEF,0x9E,0xEF,0xBE,0xEF,0x3D,0xE7,0xAB,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0xD6,0xBF,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0xBE,0xEF,0x1C,0xDF,0xC1,0xEB,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC1,0xB2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x10,0x81,0xD3,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xF4,0xC1,0x79,0x00,0x00,0x00,0x00,0xE2,0x28,0x81,0xCB,0x60,0xFC,0x60,0xFC, - 0x60,0xFC,0x40,0xFC,0x60,0xFC,0x40,0xF4,0x61,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xBA,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0x60,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xEB,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x81,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xA2,0x20,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x81,0xDB,0xC2,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x73,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x1C,0xD7,0x0A,0x2A, - 0x00,0x00,0x00,0x00,0x93,0x8C,0x5E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9B,0xCE,0xAB,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xA5,0x9E,0xEF,0x9E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x84,0x7D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0xBF,0xEF,0xBF,0xEF,0x9E,0xEF,0xDB,0xD6,0x59,0xC6,0x72,0x8C,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDD,0x64,0x5E,0xE7,0x9E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xBB,0xCE,0x00,0x00,0x00,0x00,0x4A,0x21,0x9A,0xCE,0x5D,0xE7,0x5E,0xE7,0x7E,0xE7, - 0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x76,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x42,0x5D,0xE7,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x1C,0xDF,0xC5,0x08,0x00,0x00,0x4A,0x42,0x9A,0xCE,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x3D,0xDF,0x4A,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xD6,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x1C,0xDF,0xA1,0xE3,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB, - 0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xF3,0xA1,0xBA,0xE1,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xBA,0x00,0xFC,0x00,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x20,0xFC,0x01,0xBB,0x00,0x00,0x00,0x00,0x42,0x51,0xC1,0xDB,0x40,0xFC,0x40,0xFC,0x40,0xFC,0x20,0xFC,0x20,0xFC,0xA1,0xDB,0x21,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x41,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x39,0xA1,0xF3,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x21,0x92,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x92,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xA1,0xE3,0xA2,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x5B,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xF4,0x94,0x00,0x00,0x00,0x00,0xF8,0xB5,0x7E,0xE7,0x7E,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xA5,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x42,0xD7,0xB5,0x5D,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x9E,0xE7, - 0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x9E,0xEF,0x5D,0xE7,0x7A,0xCE,0x31,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD6,0x4B,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9A,0xCE,0x00,0x00,0x00,0x00,0x6C,0x42,0x7A,0xC6,0x5D,0xDF,0x5D,0xDF,0x5D,0xDF,0x5E,0xDF,0x5E,0xDF,0x3D,0xDF,0x39,0xBE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x21,0x3D,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x3D,0xDF,0xA8,0x29,0x00,0x00,0x4A,0x42,0x9A,0xCE,0x9E,0xE7,0x9E,0xE7,0x7E,0xE7,0x7E,0xE7,0x9E,0xE7,0x1D,0xDF,0x6B,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0xDB,0xD6,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0x9E,0xE7,0xFC,0xD6,0x81,0xEB,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x01,0xE3,0x61,0xB2,0x01,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x69,0xC0,0xEB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0xE0,0xFB,0x00,0xFC,0x41,0xD3,0x00,0x00,0x00,0x00,0x02,0x82,0x00,0xF4,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x00,0xFC,0x01,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0x80,0xFB,0x80,0xFB, - 0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x00,0xDB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x80,0xEB,0xA0,0xFB,0xA0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xE1,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x92,0xC0,0xFB,0xC0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0x81,0xE3,0xA2,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xB6,0x3E,0xDF,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x5E,0xDF,0xB7,0xAD,0x00,0x00,0x29,0x3A,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x3D,0xDF,0x72,0x84,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0xA5,0x7E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7E,0xDF,0xF8,0xB5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4A,0x42,0x15,0x9D,0xDB,0xCE,0x5E,0xE7,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xFC,0xD6,0xF4,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x19,0xFC,0xD6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x7A,0xC6,0x00,0x00,0x00,0x00,0x4D,0x42,0x7A,0xC6,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x3D,0xD7,0x18,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x46,0x21,0x1D,0xD7,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x1D,0xD7,0x09,0x32,0x00,0x00,0x8B,0x4A,0x7A,0xC6,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x1D,0xD7,0x6B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xCE,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0x7E,0xE7,0xFC,0xD6,0x61,0xEB,0xA0,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0xE0,0xF2,0xA0,0xDA,0xA1,0xD2,0x22,0xAA,0xA2,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x21,0xD3,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0xC0,0xFB,0x80,0xEB,0x01,0x51,0x00,0x00,0xE2,0xBA,0xE0,0xFB,0xC0,0xFB,0xC0,0xFB,0xE0,0xFB,0xE0,0xFB,0xC0,0xF3,0x21,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xBA,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0xE0,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xEB,0x80,0xFB,0x80,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xA0,0xFB,0xC1,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x92,0x80,0xFB,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB, - 0x21,0xDB,0x42,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x74,0x1D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x39,0xB6,0x46,0x19,0xD0,0x6B,0xFD,0xCE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0x5E,0xD7,0x9B,0xC6,0xEB,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xA5,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xD8,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x63,0x76,0xA5,0x7A,0xC6,0x1D,0xD7,0x3D,0xD7,0x3D,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xDC,0xCE,0x6E,0x63,0x00,0x00,0x00,0x00,0x26,0x19, - 0xDC,0xCE,0x3D,0xDF,0x3D,0xDF,0x3D,0xDF,0x5D,0xDF,0x5E,0xDF,0x5A,0xBE,0x00,0x00,0x00,0x00,0xCB,0x31,0x39,0xBE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x1D,0xD7,0x19,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x29,0x1D,0xD7,0x5E,0xDF,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x5E,0xDF,0xFC,0xCE,0x87,0x21,0x00,0x00,0x8B,0x4A,0x7A,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x1C,0xD7,0x6B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xC6,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0x5E,0xDF,0xDB,0xCE,0x41,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB, - 0x60,0xFB,0x60,0xFB,0x40,0xFB,0xA2,0x89,0x82,0x79,0xA2,0x89,0xC1,0x99,0xC1,0x99,0xA1,0x91,0xA1,0x91,0xA2,0x91,0x42,0x69,0x03,0x59,0xE2,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAA,0xA0,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x41,0xB2,0x00,0x00,0x21,0xD3,0x80,0xFB,0x80,0xFB,0x80,0xFB,0x80,0xFB,0xA0,0xFB,0x40,0xE3,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xBA,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0xC0,0xDA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0xC1,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xA2,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x40,0xFB,0x40,0xFB,0xE1,0xDA,0xA2,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA9,0x29,0x7B,0xBE,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xBC,0xC6,0xD0,0x6B,0x56,0x9D,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xD7,0x3D,0xD7,0xB7,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x9D,0x5E,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0xD8,0xAD, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0x4A,0xAF,0x63,0xB7,0xA5,0x7A,0xBE,0xBB,0xCE,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3D,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xDF,0x56,0xA5,0x00,0x00,0x00,0x00,0x26,0x19,0xBC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x3D,0xD7,0x39,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xCF,0x1D,0xCF,0x1D,0xD7,0x1D,0xD7,0x15,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x8C,0x1D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0xBB,0xC6,0x00,0x00,0x00,0x00,0x6B,0x4A,0x5A,0xBE, - 0x5E,0xD7,0x3E,0xD7,0x3E,0xD7,0x3E,0xD7,0x5E,0xDF,0x1C,0xD7,0x8C,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9B,0xC6,0x3E,0xD7,0x3E,0xD7,0x3D,0xD7,0x3D,0xDF,0x5D,0xDF,0xBB,0xCE,0x21,0xEB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x82,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x71,0x20,0xEB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0x60,0xFB,0xA0,0xCA,0x63,0x51,0x40,0xF3,0x60,0xFB, - 0x40,0xFB,0x40,0xFB,0x40,0xFB,0x60,0xFB,0xA1,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xBA,0x20,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0x80,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xD2,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x81,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xAA,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x40,0xFB,0x20,0xFB,0x20,0xFB,0xA1,0xDA,0x82,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xA5,0xFD,0xCE,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6, - 0xFD,0xC6,0xFD,0xC6,0x15,0x95,0xF9,0xAD,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xDC,0xC6,0x11,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x9D,0x3E,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x3D,0xD7,0x3E,0xD7,0xB8,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x7C,0xB4,0x8C,0x19,0xB6,0xFC,0xCE,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x1D,0xD7,0x39,0xB6,0x09,0x3A,0x00,0x00,0x05,0x19,0x9C,0xC6,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0x19,0xB6,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xB6,0xFD,0xCE, - 0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0xB7,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF4,0x94,0x1D,0xD7,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xF9,0xAD,0x00,0x00,0x00,0x00,0x2A,0x3A,0x3A,0xBE,0x3E,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3E,0xD7,0xFC,0xCE,0xED,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0xBE,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0x3D,0xD7,0xBB,0xC6,0x01,0xE3,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xFA,0x62,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xD2,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x20,0xFB,0xC0,0xE2,0x41,0x9A,0x20,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xF3,0x81,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xBA,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xA0,0xFA,0x40,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xCA,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x80,0xDA,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x28,0x81,0xCA,0x00,0xFB,0x20,0xFB,0x20,0xFB,0x00,0xFB,0x00,0xFB,0x00,0xFB,0x42,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x74,0xBC,0xBE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xB8,0x9D,0x1A,0xAE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDC,0xC6,0x19,0xAE,0xC8,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x95,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x97,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x8C,0xDC,0xC6,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0x1D,0xCF,0x3A,0xB6,0xF1,0x73,0x00,0x00,0x26,0x19,0x7B,0xBE,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0xF9,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x57,0x9D,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xF9,0xAD,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB8,0xA5,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xFD,0xCE,0xB8,0xA5,0x00,0x00,0x00,0x00,0x09,0x3A,0x19,0xB6,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xFC,0xCE,0xED,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x5B,0xBE,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0x1D,0xCF,0xBB,0xC6,0xC1,0xEA,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xA1,0xC0,0xF2,0xE0,0xFA,0x00,0xFB,0x00,0xFB,0x00,0xFB,0xE0,0xF2,0x61,0xBA,0x00,0xFB,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0x60,0xDA,0x81,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xBA, - 0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x00,0xD2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB9,0xA0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x80,0xF2,0x61,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x81,0xC0,0xF2,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xC0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA2,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x19,0x1A,0xAE,0xBD,0xBE,0xBD,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x7B,0xB6,0x9C,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x15,0x95,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x8C,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0x97,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x84,0xF5,0x84,0xC8,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x01,0x5B,0xB6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0x3A,0xB6,0x11,0x74,0x00,0x00,0x26,0x19,0x7B,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xB8,0xA5,0x00,0x00,0x00,0x00,0x00,0x00,0xF1,0x6B,0xBC,0xBE,0xBD,0xC6,0xDC,0xC6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x9C,0xBE,0x12,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x6F,0x5B,0x5A,0xB6,0xDC,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0x32,0x74,0x00,0x00,0x00,0x00,0xE9,0x31,0x19,0xAE,0xFD,0xCE,0xFD,0xC6,0xFD,0xC6,0xFD,0xCE,0x1D,0xCF,0xDC,0xC6,0x8C,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3A,0xB6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0xFD,0xC6,0x9B,0xBE,0x81,0xEA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0xA0,0xFA,0x80,0xFA,0x21,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x49,0x41,0xDA,0xC0,0xFA,0xC0,0xFA,0xE0,0xFA,0xE0,0xFA,0xE0,0xFA,0xC0,0xF2,0xE0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0xC0,0xFA,0x00,0xCA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xB9,0x60,0xFA,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0xC0,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x58,0x40,0xEA,0x80,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x20,0xDA,0x61,0x99,0xE1,0x58,0x00,0x00,0x00,0x00,0xC2,0x48,0x81,0x89,0x60,0xDA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA, - 0x60,0xFA,0x00,0xDA,0x01,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x9D,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x7B,0xB6,0xF1,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x84,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xC6,0xDD,0xBE,0x77,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0xD1,0x63,0x1A,0xAE,0x9C,0xB6,0x98,0x9D,0x93,0x7C,0x0E,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x00,0x73,0x7C,0x9C,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xDD,0xBE,0x97,0x9D,0x09,0x32, - 0x00,0x00,0x05,0x19,0x3B,0xAE,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0xB8,0x9D,0x00,0x00,0x00,0x00,0x00,0x00,0x6B,0x3A,0xF9,0xA5,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0x1A,0xAE,0x73,0x7C,0x6B,0x3A,0x00,0x00,0x00,0x00,0xE9,0x31,0xF1,0x6B,0xD8,0xA5,0x9C,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBD,0xBE,0x3A,0xAE,0x09,0x32,0x00,0x00,0x00,0x00,0x09,0x32,0xF9,0xAD,0xDD,0xC6,0xDD,0xC6,0xDD,0xC6,0xFD,0xC6,0xFD,0xC6,0xBC,0xBE,0x4B,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x1A,0xAE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xC6,0xDD,0xBE,0x5B,0xB6,0x41,0xEA,0x60,0xFA, - 0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB1,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0xA0,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x41,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xB9,0x20,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xA0,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA1,0xB9,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x40,0xF2,0x20,0xDA,0x41,0xDA,0x41,0xD2,0x41,0xE2,0x80,0xF2,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x20,0xFA,0x80,0xB9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0x84,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0xD9,0xA5,0xC8,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x84,0xBC,0xBE,0x9C,0xB6,0x9C,0xB6,0xBC,0xBE,0xBC,0xBE, - 0xBD,0xBE,0x56,0x95,0x00,0x00,0x00,0x00,0xD3,0x4B,0x98,0x9D,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7B,0xB6,0xD9,0xA5,0x77,0x95,0x57,0x95,0x52,0x74,0x52,0x74,0xF5,0x8C,0xB8,0xA5,0x5B,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x36,0x95,0x00,0x00,0x00,0x00,0x05,0x11,0x3A,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x98,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD4,0x84,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xB6,0xF9,0xA5,0xB8,0xA5,0xB8,0xA5,0xD9,0xA5,0x7B,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xBE,0x9C,0xB6,0x16,0x8D,0x00,0x00,0x00,0x00,0x00,0x00, - 0xE9,0x31,0xD9,0xA5,0xBD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0xDD,0xBE,0x9B,0xB6,0x2A,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xF9,0xA5,0xBC,0xB6,0xBC,0xBE,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0x1A,0xAE,0x21,0xE2,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x79,0x40,0xEA,0x60,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA,0x80,0xFA, - 0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x20,0xE2,0xC1,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xB9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0x80,0xD1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x69,0x01,0xE2,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x60,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x20,0xFA,0x20,0xFA,0xC0,0xD9,0xA1,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x11,0xFA,0x9D, - 0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5C,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x37,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0x7C,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x36,0x8D,0x00,0x00,0x00,0x00,0x15,0x8D,0x7B,0xB6,0x7B,0xB6,0x7B,0xB6,0x7B,0xAE,0x5B,0xAE,0x7B,0xAE,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xBE,0x9C,0xBE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x1A,0xA6,0x90,0x63,0x00,0x00,0x00,0x00,0x26,0x11,0x1A,0xA6,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x78,0x95,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x68,0x09,0x98,0x9D,0x7C,0xAE,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x9C,0xB6,0xD9,0x9D,0x8B,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x29,0xB9,0x9D,0xBC,0xBE,0xBC,0xBE,0xBC,0xB6,0xBC,0xB6,0xBC,0xBE,0x5B,0xAE,0x2A,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xF9,0xA5,0x9C,0xB6,0x9C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0xD9,0x9D,0xE1,0xE1,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x00,0xFA,0xE1,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,0x22,0x00,0xC1,0xD1,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0x40,0xFA,0xC0,0xD1,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xB1,0xA0,0xF9,0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0xA0,0xF9,0x60,0xD1,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,0x91,0xE1,0xE1,0x00,0xFA,0x20,0xFA,0x20,0xFA, - 0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x20,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xA0,0xE1,0xE1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x8D,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x32,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x7C,0x7C,0xAE,0x5B,0xAE,0x5C,0xAE,0x5C,0xAE,0x7C,0xAE,0x7C,0xAE,0xF5,0x84,0x00,0x00,0x00,0x00,0x57,0x95,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE, - 0x5B,0xAE,0x7B,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x1A,0xA6,0x94,0x7C,0x84,0x00,0x00,0x00,0x00,0x00,0x4D,0x22,0xFA,0xA5,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x77,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x4B,0x98,0x95,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x7C,0xAE,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xB6,0x7C,0xAE,0x7B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x98,0x95,0xB1,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x29,0x98,0x9D,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x9C,0xB6,0x3B,0xAE,0x2A,0x2A,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xD9,0x9D,0x7C,0xAE,0x7C,0xAE,0x5C,0xAE,0x5B,0xAE,0x5B,0xAE,0xB9,0x9D,0xA0,0xE1,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xE2,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xA1,0x00,0xFA,0x00,0xFA,0x20,0xFA,0x20,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0x00,0xFA,0xE0,0xF9,0x21,0xA1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x41,0xB9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xD1,0x00,0x00,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,0x81,0xC1,0xD9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA1,0xD9,0xE1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x6C,0xFA,0x9D,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0xFA,0x9D,0xFA,0x9D,0xB9,0x95,0x4B,0x32,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x7C,0x5B,0xAE,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x5B,0xA6,0x5B,0xAE,0xD5,0x84,0x00,0x00,0x00,0x00,0x6B,0x32,0xB5,0x7C,0xB9,0x9D,0x3B,0xA6,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x3B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x3B,0xAE,0x3B,0xA6,0x3B,0xA6,0xD9,0x9D,0x74,0x74,0x4B,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x9C,0x44,0xFA,0x9D,0x1B,0xA6,0x1B,0xA6,0x1B,0xA6,0x1B,0x9E,0x1B,0xA6,0x57,0x8D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xED,0x4A,0x37,0x8D,0x1B,0xA6,0x3B,0xA6,0x3B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE, - 0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x5B,0xAE,0x3B,0xAE,0x3B,0xA6,0x1B,0xA6,0x37,0x8D,0xD1,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE9,0x29,0x98,0x95,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x7C,0xAE,0x1A,0xA6,0xEA,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xB9,0x95,0x5B,0xA6,0x5B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0xB9,0x9D,0x60,0xE1,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0xC2,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x38,0x81,0xC9,0xE0,0xF9,0x00,0xFA,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xE0,0xF9,0xC0,0xF9,0xA0,0xE1,0xE2,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xB1,0x60,0xF1,0x40,0xF1,0x40,0xF1,0x20,0xF1,0x20,0xF9,0x40,0xF9,0x00,0xE1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0x50,0x61,0xB9,0x81,0xD1,0xA0,0xF1,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA0,0xF1,0x61,0xD9,0x41,0xB1, - 0xA2,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x32,0x58,0x85,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xDA,0x95,0xBA,0x95,0xB9,0x95,0xD5,0x7C,0xE9,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x74,0x3B,0xA6,0x1B,0x9E,0xFB,0x9D,0xFB,0x9D,0x1B,0x9E,0x1B,0xA6,0xD5,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x4B,0xD5,0x7C,0x98,0x95,0x1B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x1B,0xA6,0xB9,0x95,0xF6,0x84,0xB0,0x5B,0x06,0x09,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0x3C,0xD9,0x95,0xDA,0x9D,0xFA,0x9D,0xDA,0x9D,0xDA,0x9D,0xFA,0x9D,0x37,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCD,0x42,0x12,0x6C,0x57,0x8D,0xFA,0xA5,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xAE,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x1B,0xA6,0xFA,0x9D,0x57,0x8D,0x53,0x74,0xCD,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE9,0x29,0x78,0x95,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0x3B,0xA6,0xF9,0x9D,0xA8,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x98,0x95,0x1B,0x9E,0x1B,0x9E,0x1B,0x9E,0x1B,0xA6,0x1B,0xA6,0xB8,0x95, - 0xE1,0xB0,0x21,0xC1,0x41,0xB9,0x41,0xC1,0x41,0xC9,0x41,0xD9,0x20,0xD9,0xC7,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x99,0xC0,0xF9,0xE0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xC0,0xF9,0xA0,0xF9,0x40,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE2,0x80,0x01,0xB9,0x21,0xC1,0x21,0xC1,0x01,0xC1,0x01,0xC1,0x01,0xD1,0xE2,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,0x62,0x30,0xE1,0x88,0x41,0xC1,0x60,0xC9,0x80,0xD9,0x80,0xE1,0x80,0xE1,0x80,0xD9,0x61,0xC9,0x41,0xC1,0xE1,0x90,0xC6,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x11,0xD1,0x5B,0x75,0x6C,0x33,0x6C,0x13,0x64,0x12,0x64,0x13,0x64,0x33,0x6C,0xF2,0x63,0xD1,0x63,0x6F,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x5B,0xD5,0x7C,0x94,0x74,0x94,0x74, - 0x94,0x74,0x94,0x7C,0x94,0x7C,0x6F,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x21,0x12,0x6C,0x16,0x85,0x16,0x8D,0x77,0x95,0x98,0x95,0x98,0x95,0x78,0x95,0x16,0x8D,0x37,0x8D,0x53,0x74,0xC9,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x6C,0x53,0x6C,0x33,0x6C,0x32,0x6C,0x12,0x6C,0x12,0x6C,0x90,0x5B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x5B,0xB5,0x7C,0xD9,0x9D,0x57,0x95,0x98,0x9D,0x98,0x9D,0x57,0x95,0x98,0x95,0xB4,0x7C,0x0E,0x4B,0x06,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x67,0x21,0x11,0x6C,0xB5,0x7C,0xB5,0x7C,0xF6,0x84,0x16,0x85,0x16,0x8D,0x94,0x7C,0x26,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0xF2,0x63,0x74,0x74,0x94,0x7C,0xB5,0x7C,0xB5,0x84,0xD5,0x84,0x94,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x81,0xA0,0xE1,0xC0,0xF9,0xA0,0xF9, - 0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF1,0xC1,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,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE1,0xA8,0xE0,0xC0,0xE0,0xB8,0xE1,0xB0,0x21,0xB1,0x61,0xC9,0xA0,0xE9,0xA0,0xF9,0xA0,0xF9,0xA0,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x01,0xC1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC1,0x40,0xF9,0x40,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x80,0xF9,0x80,0xF9,0x80,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xD9,0xA1,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD1,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x60,0xF9,0x60,0xF9,0x60,0xF9,0x40,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xF9,0xE0,0xE0,0xC1,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0xE0,0xD8,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x20,0xF9,0x40,0xF9,0x40,0xF9,0x20,0xF9,0x20,0xF9,0x00,0xF9,0x00,0xD1,0xA1,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x50,0xC0,0xD8,0x00,0xF9,0x20,0xF9,0x00,0xF9,0x00,0xF9,0x00,0xF9,0x20,0xF9,0x20,0xF1, - 0x00,0xF1,0xE0,0xD8,0xE1,0xB8,0xA2,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x60,0xA1,0xB0,0xC0,0xD0,0xC1,0xD0,0xC1,0xD0,0xC1,0xD0,0xC1,0xC8,0xE3,0xD0,0xE1,0xB8,0xA2,0x90,0x82,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xE1, 0x18, 0xE2, 0x10, 0x02, 0x19, 0x02, 0x11, 0xC1, 0x00, 0xA1, 0x00, 0xC1, 0x08, 0x02, 0x19, 0x22, 0x21, 0x22, 0x19, 0x22, 0x21, 0x22, 0x21, 0x42, 0x21, 0x42, 0x21, 0x02, 0x21, 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, 0xE6, 0x08, 0xE5, 0x10, 0xA4, 0x00, 0x23, 0x00, 0x23, 0x00, 0x84, 0x00, 0xC5, 0x10, 0x46, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x10, 0x26, 0x19, 0x46, 0x21, 0x46, 0x21, 0x67, 0x21, 0xA7, 0x29, 0xA8, 0x29, 0xE5, 0x10, 0x92, 0x94, 0x9A, 0xD6, 0xFB, 0xDE, 0xFB, 0xDE, + 0xFB, 0xDE, 0xFB, 0xDE, 0xDB, 0xDE, 0x14, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0x31, 0x79, 0xCE, 0x1C, 0xE7, 0x3C, 0xE7, 0x5D, 0xE7, 0x5D, 0xEF, 0x3D, 0xE7, 0x39, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xCD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x41, 0xDD, 0x41, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x61, 0xDD, 0x62, 0xDD, 0x61, 0xDD, 0x02, 0xCD, 0xA3, 0xBC, 0xA2, 0x93, 0xA1, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xBE, 0xDB, 0xDE, 0xDB, 0xDE, 0xBB, 0xD6, 0xBB, 0xD6, 0xDB, 0xDE, 0xDB, 0xDE, 0x39, 0xC6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6B, 0x7A, 0xCE, 0xDB, 0xDE, 0xDB, 0xDE, 0xDB, 0xDE, 0xDB, 0xDE, 0xFB, 0xDE, 0xBA, 0xD6, 0xCC, 0x52, 0x38, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x73, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xED, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, + 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0x21, 0xFE, 0x41, 0xFE, 0x21, 0xF6, 0xA1, 0xE5, 0x61, 0xB4, 0x21, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xEF, 0xF0, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xAD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDE, 0x93, 0x8C, 0x1C, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x7C, 0xBF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x21, 0xFE, 0x21, 0xFE, 0x21, 0xFE, 0x41, 0xFE, 0x81, 0xE5, 0x21, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8C, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xD6, 0x00, 0x00, 0xFB, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x6B, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x20, 0xFE, 0x20, 0xFE, 0xE1, 0xF5, 0x21, 0xBC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0x1C, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAF, 0x73, 0x3D, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xD3, 0x9C, 0x00, 0x00, 0xB7, 0xAD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x4A, 0x5D, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0x7A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0x00, 0xFE, 0x61, 0xED, 0x61, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0x0C, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0xEC, 0x5A, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, + 0x39, 0xC6, 0xD3, 0x94, 0x76, 0xAD, 0x7A, 0xCE, 0xF4, 0x9C, 0x6A, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x8C, 0x7A, 0xCE, 0xDB, 0xD6, 0x7A, 0xC6, 0x5A, 0xC6, 0x76, 0xAD, 0x29, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xED, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0x21, 0xDD, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x21, 0xE5, 0x01, 0xE5, 0x21, 0xE5, 0xA0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xE0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0x61, 0xCC, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7B, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x92, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0xF8, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0xCE, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xED, 0xA0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xA1, 0xFD, 0xC2, 0x82, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x41, 0x81, 0xA3, 0xE1, 0xD4, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xC0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x21, 0xED, 0x62, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x31, 0x41, 0x6A, 0xA2, 0xB3, 0x82, 0xAB, 0x61, 0x72, 0x01, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0xC3, 0x7A, 0x22, 0x93, 0x82, 0xA3, 0x81, 0xA3, 0x61, 0x9B, 0x41, 0x72, 0x81, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x3A, 0xFC, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0xE4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x6B, 0xDB, 0xDE, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x14, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x42, 0xCF, 0x73, 0xF3, 0x9C, 0xF4, 0x9C, 0x14, 0xA5, 0xD3, 0x9C, 0xB3, 0x94, 0x6A, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x08, 0x88, 0x31, 0x6E, 0x6B, 0xB3, 0x94, 0xF4, 0x9C, 0xF4, 0x9C, 0xB3, 0x94, 0x31, 0x84, 0x4A, 0x4A, 0xAC, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x8B, 0x01, 0x6B, 0x00, 0x8B, 0x01, 0x2B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xB3, 0x94, 0x14, 0x9D, 0x14, 0xA5, 0xB3, 0x94, 0x11, 0x7C, 0xC8, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xED, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0xC1, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x62, 0xE1, 0xD4, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x82, 0xA3, 0x22, 0xAC, 0xA0, 0xD4, 0xA0, 0xD4, 0xA0, 0xD4, 0xA1, 0xCC, 0xA1, 0xCC, 0xA1, 0xCC, 0x61, 0xC4, 0x03, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xC4, 0x81, 0xD4, 0x81, 0xCC, 0x60, 0xCC, + 0x60, 0xCC, 0x80, 0xCC, 0xA0, 0xCC, 0x22, 0xB4, 0x00, 0x00, 0x03, 0xAC, 0xA1, 0xCC, 0xA0, 0xCC, 0xA1, 0xCC, 0xA1, 0xD4, 0x80, 0xD4, 0xE1, 0xB3, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x72, 0x01, 0xB4, 0x01, 0xE5, 0x61, 0xF5, 0xA1, 0xFD, 0x81, 0xFD, 0x60, 0xF5, 0xA1, 0xD4, 0x62, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6A, 0xC1, 0xA3, 0xE1, 0xD4, 0x41, 0xED, 0xA1, 0xF5, 0xC1, 0xFD, 0xC1, 0xFD, 0xC1, 0xFD, 0xC1, 0xFD, 0xA1, 0xF5, 0x61, 0xED, 0xC1, 0xD4, 0xA1, 0xA3, 0x21, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDE, 0xEF, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x31, 0x84, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0x9A, 0xCE, 0x9A, 0xD6, 0x9A, 0xD6, 0xBA, 0xD6, 0xBA, 0xD6, 0x9A, 0xD6, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x6B, 0x96, 0xB5, 0xBA, 0xD6, 0x7D, 0xEF, 0xBE, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0xDB, 0xDE, 0x59, 0xCE, 0xB3, 0x94, 0x0D, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7C, 0x39, 0xC6, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0x79, 0xCE, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7B, 0x55, 0xA5, 0x9A, 0xD6, + 0x3D, 0xE7, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBF, 0xF7, 0x7D, 0xEF, 0xBA, 0xD6, 0x18, 0xC6, 0x52, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x4A, 0xB7, 0xB5, 0x9A, 0xCE, 0x9A, 0xD6, 0x9A, 0xD6, 0x9A, 0xD6, 0x7A, 0xCE, 0x14, 0xA5, 0x00, 0x00, 0xF0, 0x7B, 0x76, 0xAD, 0xDB, 0xDE, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x5D, 0xE7, 0xBB, 0xD6, 0x35, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xED, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0xA1, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x7A, 0x61, 0xF5, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, + 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x42, 0xCC, 0xE1, 0x8A, 0x80, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x60, 0xF5, 0x42, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xDC, 0x80, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x81, 0xA3, 0x00, 0x00, 0x62, 0xC4, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x00, 0xED, 0x81, 0x08, 0xC2, 0xAB, 0x01, 0xE5, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0xC1, 0xE4, 0x81, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x92, 0xE1, 0xB3, 0x01, 0xE5, 0x80, 0xFD, 0x80, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA0, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, 0xA1, 0xFD, + 0xC1, 0xFD, 0xC1, 0xFD, 0xA1, 0xFD, 0x01, 0xDD, 0x81, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x84, 0x7E, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x71, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xC6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xBD, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x35, 0xA5, 0xFC, 0xDE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x9E, 0xF7, 0xDB, 0xDE, 0x51, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x31, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0x3C, 0xE7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xEF, 0xF8, 0xBD, 0x30, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x4A, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xC6, 0x92, 0x8C, 0xBB, 0xD6, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBE, 0xF7, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x21, 0xED, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x60, 0xFD, 0xA2, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x62, 0xA1, 0xDC, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x41, 0xCC, 0xE1, 0x9A, 0xC1, 0xDC, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x21, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x93, 0x40, 0xF5, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0xE1, 0xE4, 0x41, 0x39, 0x00, 0x00, 0x22, 0xC4, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0xE1, 0xEC, + 0xE1, 0x8A, 0x20, 0xF5, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x61, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x49, 0x01, 0xC4, 0x20, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x80, 0xFD, 0x81, 0xFD, 0xA1, 0xFD, 0x61, 0xF5, 0xE1, 0xBB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBA, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xF7, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x29, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x55, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xD7, 0xB5, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x76, 0xAD, 0x9E, 0xEF, 0xDF, 0xFF, 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, 0x5D, 0xEF, 0x71, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x46, 0x21, 0x7E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF8, 0xBD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, + 0xFC, 0xDE, 0x55, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x4A, 0xBB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0xD6, 0xFC, 0xDE, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xF7, 0xB6, 0xB5, 0x00, 0x00, 0x01, 0xED, 0x60, 0xFD, 0x60, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0xA2, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x41, 0x61, 0xD4, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x41, 0xD4, 0x00, 0x00, 0xA1, 0xB3, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, + 0x81, 0xDC, 0x61, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xC4, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x41, 0xCC, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xC3, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x01, 0xFD, 0xA1, 0xE4, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0xC1, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x61, 0x49, 0x01, 0xC4, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x60, 0xFD, 0x61, 0xFD, 0x61, 0xFD, 0x41, 0xFD, 0xC1, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB6, 0xB5, + 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDB, 0xD6, 0x31, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x5B, 0x9E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x3D, 0xE7, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xB5, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xA5, 0x7D, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0xDE, 0xAB, 0x52, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, + 0xDF, 0xFF, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD7, 0xBD, 0xBE, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x9A, 0xD6, 0x2A, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE7, 0x2D, 0x63, 0xE0, 0xEC, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x20, 0xFD, 0x81, 0x82, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x72, 0x61, 0xDC, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0x01, 0xCC, 0x00, 0x00, 0x01, 0x62, 0xA0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0xE0, 0xF4, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xDC, 0x20, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x22, 0x9B, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBB, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x81, 0xB3, 0x00, 0x00, 0x00, 0x00, + 0x82, 0xAB, 0x00, 0xF5, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0x40, 0xFD, 0xE0, 0xF4, 0x81, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x7C, 0x7D, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xEF, 0x8E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xCE, 0xBF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x7A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xBD, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xD6, + 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0xBA, 0xD6, 0xFB, 0xDE, 0x1C, 0xDF, 0x9A, 0xD6, 0xDB, 0xDE, 0x9E, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0xD3, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0x7E, 0xEF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x7D, 0xEF, 0x7D, 0xEF, 0xDF, 0xF7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xF7, 0x35, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xBB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, + 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x96, 0xAD, 0xA0, 0xEC, 0x00, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x20, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x59, 0xA0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0xA1, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x41, 0xD4, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0x81, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x82, 0xE0, 0xEC, 0x00, 0xFD, 0x00, 0xFD, + 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x81, 0xE4, 0x62, 0x82, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xBB, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC1, 0xF4, 0xC1, 0xEC, 0xA1, 0xEC, 0xA0, 0xF4, 0xA0, 0xF4, 0xA1, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x81, 0xE4, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x00, 0xFD, 0xE0, 0xFC, 0x21, 0xD4, 0x62, 0xAB, 0x02, 0x9B, 0xE2, 0x92, 0xA1, 0xBB, 0x81, 0xDC, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x00, 0xFD, 0x01, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xD6, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xBD, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x3C, 0xE7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x7D, 0xEF, 0x14, 0xA5, 0x2D, 0x63, 0x00, 0x00, 0x00, 0x00, 0x88, 0x29, 0x8C, 0x52, 0xAF, 0x73, 0x7A, 0xCE, 0x3C, 0xE7, 0xDF, 0xF7, 0x18, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x21, 0x7E, 0xEF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, + 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xF7, 0x39, 0xC6, 0xB3, 0x94, 0x8A, 0x52, 0x6A, 0x4A, 0x72, 0x8C, 0xF8, 0xBD, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFB, 0xDE, 0xEC, 0x5A, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xDB, 0xD6, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xBE, 0xF7, 0xBB, 0xD6, 0xD7, 0xB5, 0xB7, 0xB5, 0x18, 0xBE, 0x38, 0xC6, 0x1C, 0xDF, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x59, 0xC6, 0xA1, 0xEC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC3, 0xC0, 0xFC, 0xC0, 0xFC, + 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x01, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x62, 0xA3, 0xC0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE0, 0xD3, 0x81, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xAB, 0x00, 0xFD, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0x21, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xBB, 0xA0, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xE1, 0xD3, 0x63, 0xB3, 0x83, 0x72, 0x62, 0x39, 0x61, 0x41, 0x81, 0x82, 0x20, 0xA3, 0xE1, 0x51, 0x00, 0x00, 0xC1, 0x9A, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x61, 0xB3, 0x22, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x31, 0xA1, 0xC3, 0xC0, 0xFC, 0xC0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xE0, 0xFC, 0xC0, 0xFC, 0x80, 0xF4, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xAD, 0xBE, 0xEF, 0xBE, 0xF7, 0xBE, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBA, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x52, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0x7D, 0xEF, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xBD, 0xDF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x08, 0x9E, 0xF7, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFB, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0xD7, 0xB5, 0x0C, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0xBA, 0xD6, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x94, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xF7, 0x96, 0xB5, 0x49, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xA5, 0x9E, 0xEF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xBE, 0xF7, 0x92, 0x8C, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x52, 0xBB, 0xD6, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9E, 0xEF, 0x76, 0xAD, 0x4E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x6B, 0xDB, 0xD6, 0xDF, 0xF7, + 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x9A, 0xCE, 0x81, 0xEC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0x61, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x49, 0x60, 0xBB, 0x60, 0xF4, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x20, 0xEC, 0x01, 0x7A, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x51, 0x20, 0xE4, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xF4, 0x20, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xE1, 0xCB, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xC0, 0xFC, 0xA0, 0xFC, 0xE1, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xBB, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, + 0x40, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0xA0, 0xCB, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xC3, 0x80, 0xFC, 0x80, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x00, 0xE4, 0x21, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x69, 0x21, 0xE4, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x41, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x84, 0x7E, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x5D, 0xE7, 0xCC, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xB5, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBB, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xD7, 0xB5, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDB, 0xD6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x29, 0x7E, 0xEF, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xF7, 0xBF, 0xF7, 0xBA, 0xD6, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0xBE, 0xF7, 0xBE, 0xF7, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xF7, 0xBF, 0xF7, 0xFC, 0xDE, 0x8F, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xCE, 0xDF, 0xF7, + 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x52, 0xBB, 0xD6, 0xBF, 0xF7, 0xDF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xDF, 0xF7, 0x79, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xAD, 0xBE, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0x3D, 0xE7, 0x41, 0xEC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x62, 0xBB, 0xC1, 0xC3, 0xA1, 0xC3, 0xA0, 0xC3, 0x81, 0xC3, 0x80, 0xC3, 0x80, 0xC3, 0x61, 0xCB, 0xE0, 0xE3, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x40, 0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBB, 0x60, 0xFC, 0x60, 0xFC, + 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x7A, 0x20, 0xE4, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0xA0, 0xFC, 0x80, 0xFC, 0x00, 0xE4, 0xC1, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBB, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0xC0, 0xE3, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xDB, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xC3, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x61, 0xFC, 0x81, 0xCB, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0xCE, 0x9E, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xD7, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0xBF, 0xF7, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xF8, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xE7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBE, 0xEF, 0x9A, 0xCE, 0x35, 0xA5, 0x0C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x21, 0x5D, 0xE7, 0xBE, 0xEF, + 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBA, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xC6, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0x18, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xB5, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x4A, 0xBB, 0xCE, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0xBF, 0xF7, 0x7E, 0xEF, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x4A, 0x3C, 0xDF, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xF7, 0xBF, 0xEF, 0x3D, 0xE7, 0x01, 0xEC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, + 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x60, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xC0, 0xF3, 0x01, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x82, 0x20, 0xF4, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0xA0, 0xD3, 0x81, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x92, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x80, 0xFC, 0x60, 0xFC, 0x61, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xBB, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x40, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC1, 0xE3, 0x20, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x01, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB3, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0xA1, 0xDB, 0x82, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xB5, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x32, 0xFC, 0xD6, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x5D, 0xDF, 0xF0, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xAD, 0xBE, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x9A, 0xCE, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x9E, 0xEF, 0x5D, 0xE7, 0xBB, 0xD6, 0x18, 0xBE, 0xB3, 0x94, 0x33, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x21, 0x5D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBA, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x87, 0x21, 0xDB, 0xD6, 0x7E, 0xEF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xEF, 0x14, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x9D, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x1C, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x42, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, + 0x9E, 0xEF, 0x9E, 0xEF, 0xBE, 0xEF, 0x3D, 0xE7, 0xAB, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xD6, 0xBF, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0x1C, 0xDF, 0xC1, 0xEB, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC1, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x10, 0x81, 0xD3, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xF4, 0xC1, 0x79, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x28, 0x81, 0xCB, 0x60, 0xFC, 0x60, 0xFC, + 0x60, 0xFC, 0x40, 0xFC, 0x60, 0xFC, 0x40, 0xF4, 0x61, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xBA, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0x60, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xEB, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x81, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xA2, 0x20, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x81, 0xDB, 0xC2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x73, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x1C, 0xD7, 0x0A, 0x2A, + 0x00, 0x00, 0x00, 0x00, 0x93, 0x8C, 0x5E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9B, 0xCE, 0xAB, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xA5, 0x9E, 0xEF, 0x9E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x84, 0x7D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0xBF, 0xEF, 0xBF, 0xEF, 0x9E, 0xEF, 0xDB, 0xD6, 0x59, 0xC6, 0x72, 0x8C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x64, 0x5E, 0xE7, 0x9E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xBB, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x21, 0x9A, 0xCE, 0x5D, 0xE7, 0x5E, 0xE7, 0x7E, 0xE7, + 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x76, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x42, 0x5D, 0xE7, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x1C, 0xDF, 0xC5, 0x08, 0x00, 0x00, 0x4A, 0x42, 0x9A, 0xCE, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x3D, 0xDF, 0x4A, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xD6, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x1C, 0xDF, 0xA1, 0xE3, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, + 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xF3, 0xA1, 0xBA, 0xE1, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xBA, 0x00, 0xFC, 0x00, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0x01, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x42, 0x51, 0xC1, 0xDB, 0x40, 0xFC, 0x40, 0xFC, 0x40, 0xFC, 0x20, 0xFC, 0x20, 0xFC, 0xA1, 0xDB, 0x21, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x41, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x39, 0xA1, 0xF3, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x92, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xA1, 0xE3, 0xA2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x5B, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB5, 0x7E, 0xE7, 0x7E, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xA5, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x42, 0xD7, 0xB5, 0x5D, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, + 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x9E, 0xEF, 0x5D, 0xE7, 0x7A, 0xCE, 0x31, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0x4B, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9A, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x42, 0x7A, 0xC6, 0x5D, 0xDF, 0x5D, 0xDF, 0x5D, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x3D, 0xDF, 0x39, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x21, 0x3D, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x3D, 0xDF, 0xA8, 0x29, 0x00, 0x00, 0x4A, 0x42, 0x9A, 0xCE, 0x9E, 0xE7, 0x9E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x9E, 0xE7, 0x1D, 0xDF, 0x6B, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xDB, 0xD6, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0x9E, 0xE7, 0xFC, 0xD6, 0x81, 0xEB, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x01, 0xE3, 0x61, 0xB2, 0x01, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x69, 0xC0, 0xEB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0x00, 0xFC, 0x41, 0xD3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x00, 0xF4, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x01, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0x80, 0xFB, 0x80, 0xFB, + 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x00, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0xEB, 0xA0, 0xFB, 0xA0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xE1, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x92, 0xC0, 0xFB, 0xC0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0x81, 0xE3, 0xA2, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB6, 0x3E, 0xDF, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0xB7, 0xAD, 0x00, 0x00, 0x29, 0x3A, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x3D, 0xDF, 0x72, 0x84, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xA5, 0x7E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7E, 0xDF, 0xF8, 0xB5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x42, 0x15, 0x9D, 0xDB, 0xCE, 0x5E, 0xE7, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xFC, 0xD6, 0xF4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x19, 0xFC, 0xD6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x7A, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x42, 0x7A, 0xC6, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xD7, 0x18, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x21, 0x1D, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x1D, 0xD7, 0x09, 0x32, 0x00, 0x00, 0x8B, 0x4A, 0x7A, 0xC6, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x1D, 0xD7, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xCE, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0x7E, 0xE7, 0xFC, 0xD6, 0x61, 0xEB, 0xA0, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0xE0, 0xF2, 0xA0, 0xDA, 0xA1, 0xD2, 0x22, 0xAA, 0xA2, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x21, 0xD3, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0x80, 0xEB, 0x01, 0x51, 0x00, 0x00, 0xE2, 0xBA, 0xE0, 0xFB, 0xC0, 0xFB, 0xC0, 0xFB, 0xE0, 0xFB, 0xE0, 0xFB, 0xC0, 0xF3, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xBA, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0xE0, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xEB, 0x80, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x92, 0x80, 0xFB, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, + 0x21, 0xDB, 0x42, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x74, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x39, 0xB6, 0x46, 0x19, 0xD0, 0x6B, 0xFD, 0xCE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x5E, 0xD7, 0x9B, 0xC6, 0xEB, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xA5, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xD8, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x63, 0x76, 0xA5, 0x7A, 0xC6, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xDC, 0xCE, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x26, 0x19, + 0xDC, 0xCE, 0x3D, 0xDF, 0x3D, 0xDF, 0x3D, 0xDF, 0x5D, 0xDF, 0x5E, 0xDF, 0x5A, 0xBE, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x31, 0x39, 0xBE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x1D, 0xD7, 0x19, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x29, 0x1D, 0xD7, 0x5E, 0xDF, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x5E, 0xDF, 0xFC, 0xCE, 0x87, 0x21, 0x00, 0x00, 0x8B, 0x4A, 0x7A, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x1C, 0xD7, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xC6, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0x5E, 0xDF, 0xDB, 0xCE, 0x41, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, + 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0xA2, 0x89, 0x82, 0x79, 0xA2, 0x89, 0xC1, 0x99, 0xC1, 0x99, 0xA1, 0x91, 0xA1, 0x91, 0xA2, 0x91, 0x42, 0x69, 0x03, 0x59, 0xE2, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAA, 0xA0, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x41, 0xB2, 0x00, 0x00, 0x21, 0xD3, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0x80, 0xFB, 0xA0, 0xFB, 0x40, 0xE3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xBA, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xC0, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0xC1, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xA2, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0xE1, 0xDA, 0xA2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x29, 0x7B, 0xBE, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xBC, 0xC6, 0xD0, 0x6B, 0x56, 0x9D, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xD7, 0x3D, 0xD7, 0xB7, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x9D, 0x5E, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0xD8, 0xAD, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x4A, 0xAF, 0x63, 0xB7, 0xA5, 0x7A, 0xBE, 0xBB, 0xCE, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xDF, 0x56, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x26, 0x19, 0xBC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x3D, 0xD7, 0x39, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xD7, 0x1D, 0xD7, 0x15, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x8C, 0x1D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0xBB, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x4A, 0x5A, 0xBE, + 0x5E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x3E, 0xD7, 0x5E, 0xDF, 0x1C, 0xD7, 0x8C, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xC6, 0x3E, 0xD7, 0x3E, 0xD7, 0x3D, 0xD7, 0x3D, 0xDF, 0x5D, 0xDF, 0xBB, 0xCE, 0x21, 0xEB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x82, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x71, 0x20, 0xEB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0x60, 0xFB, 0xA0, 0xCA, 0x63, 0x51, 0x40, 0xF3, 0x60, 0xFB, + 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x60, 0xFB, 0xA1, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xBA, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0x80, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xD2, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xAA, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x40, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xA1, 0xDA, 0x82, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xA5, 0xFD, 0xCE, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, + 0xFD, 0xC6, 0xFD, 0xC6, 0x15, 0x95, 0xF9, 0xAD, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xDC, 0xC6, 0x11, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x9D, 0x3E, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x7C, 0xB4, 0x8C, 0x19, 0xB6, 0xFC, 0xCE, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x1D, 0xD7, 0x39, 0xB6, 0x09, 0x3A, 0x00, 0x00, 0x05, 0x19, 0x9C, 0xC6, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0x19, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xB6, 0xFD, 0xCE, + 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0xB7, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x94, 0x1D, 0xD7, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x3A, 0x3A, 0xBE, 0x3E, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3E, 0xD7, 0xFC, 0xCE, 0xED, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7B, 0xBE, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0x3D, 0xD7, 0xBB, 0xC6, 0x01, 0xE3, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xFA, 0x62, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xD2, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0xC0, 0xE2, 0x41, 0x9A, 0x20, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xF3, 0x81, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0x40, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xCA, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x80, 0xDA, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x28, 0x81, 0xCA, 0x00, 0xFB, 0x20, 0xFB, 0x20, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0x42, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x74, 0xBC, 0xBE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xB8, 0x9D, 0x1A, 0xAE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDC, 0xC6, 0x19, 0xAE, 0xC8, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x95, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x97, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x8C, 0xDC, 0xC6, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0x1D, 0xCF, 0x3A, 0xB6, 0xF1, 0x73, 0x00, 0x00, 0x26, 0x19, 0x7B, 0xBE, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x9D, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xA5, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xFD, 0xCE, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3A, 0x19, 0xB6, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xFC, 0xCE, 0xED, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xBE, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0x1D, 0xCF, 0xBB, 0xC6, 0xC1, 0xEA, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x42, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xA1, 0xC0, 0xF2, 0xE0, 0xFA, 0x00, 0xFB, 0x00, 0xFB, 0x00, 0xFB, 0xE0, 0xF2, 0x61, 0xBA, 0x00, 0xFB, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0x60, 0xDA, 0x81, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xBA, + 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB9, 0xA0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x80, 0xF2, 0x61, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0xC0, 0xF2, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA2, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x19, 0x1A, 0xAE, 0xBD, 0xBE, 0xBD, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x7B, 0xB6, 0x9C, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x15, 0x95, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x8C, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0x97, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x84, 0xF5, 0x84, 0xC8, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x5B, 0xB6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0x3A, 0xB6, 0x11, 0x74, 0x00, 0x00, 0x26, 0x19, 0x7B, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xB8, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0x6B, 0xBC, 0xBE, 0xBD, 0xC6, 0xDC, 0xC6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x9C, 0xBE, 0x12, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6F, 0x5B, 0x5A, 0xB6, 0xDC, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0x32, 0x74, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x31, 0x19, 0xAE, 0xFD, 0xCE, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xCE, 0x1D, 0xCF, 0xDC, 0xC6, 0x8C, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0xB6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0x9B, 0xBE, 0x81, 0xEA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x21, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x49, 0x41, 0xDA, 0xC0, 0xFA, 0xC0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xE0, 0xFA, 0xC0, 0xF2, 0xE0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0xC0, 0xFA, 0x00, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xB9, 0x60, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0xC0, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x58, 0x40, 0xEA, 0x80, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x20, 0xDA, 0x61, 0x99, 0xE1, 0x58, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x48, 0x81, 0x89, 0x60, 0xDA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, + 0x60, 0xFA, 0x00, 0xDA, 0x01, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x9D, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x7B, 0xB6, 0xF1, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x84, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xC6, 0xDD, 0xBE, 0x77, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x63, 0x1A, 0xAE, 0x9C, 0xB6, 0x98, 0x9D, 0x93, 0x7C, 0x0E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x73, 0x7C, 0x9C, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xDD, 0xBE, 0x97, 0x9D, 0x09, 0x32, + 0x00, 0x00, 0x05, 0x19, 0x3B, 0xAE, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0xB8, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x3A, 0xF9, 0xA5, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0x1A, 0xAE, 0x73, 0x7C, 0x6B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x31, 0xF1, 0x6B, 0xD8, 0xA5, 0x9C, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBD, 0xBE, 0x3A, 0xAE, 0x09, 0x32, 0x00, 0x00, 0x00, 0x00, 0x09, 0x32, 0xF9, 0xAD, 0xDD, 0xC6, 0xDD, 0xC6, 0xDD, 0xC6, 0xFD, 0xC6, 0xFD, 0xC6, 0xBC, 0xBE, 0x4B, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1A, 0xAE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xC6, 0xDD, 0xBE, 0x5B, 0xB6, 0x41, 0xEA, 0x60, 0xFA, + 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB1, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0xA0, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x41, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xB9, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xA0, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xB9, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x40, 0xF2, 0x20, 0xDA, 0x41, 0xDA, 0x41, 0xD2, 0x41, 0xE2, 0x80, 0xF2, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x20, 0xFA, 0x80, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x84, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0xD9, 0xA5, 0xC8, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x84, 0xBC, 0xBE, 0x9C, 0xB6, 0x9C, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, + 0xBD, 0xBE, 0x56, 0x95, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x4B, 0x98, 0x9D, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7B, 0xB6, 0xD9, 0xA5, 0x77, 0x95, 0x57, 0x95, 0x52, 0x74, 0x52, 0x74, 0xF5, 0x8C, 0xB8, 0xA5, 0x5B, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x36, 0x95, 0x00, 0x00, 0x00, 0x00, 0x05, 0x11, 0x3A, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x98, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x84, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xB6, 0xF9, 0xA5, 0xB8, 0xA5, 0xB8, 0xA5, 0xD9, 0xA5, 0x7B, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xBE, 0x9C, 0xB6, 0x16, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE9, 0x31, 0xD9, 0xA5, 0xBD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0xDD, 0xBE, 0x9B, 0xB6, 0x2A, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xF9, 0xA5, 0xBC, 0xB6, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0x1A, 0xAE, 0x21, 0xE2, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x79, 0x40, 0xEA, 0x60, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, 0x80, 0xFA, + 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x20, 0xE2, 0xC1, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xB9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0x80, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x69, 0x01, 0xE2, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x60, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0xC0, 0xD9, 0xA1, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x11, 0xFA, 0x9D, + 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x37, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x7C, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x36, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x15, 0x8D, 0x7B, 0xB6, 0x7B, 0xB6, 0x7B, 0xB6, 0x7B, 0xAE, 0x5B, 0xAE, 0x7B, 0xAE, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xBE, 0x9C, 0xBE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x1A, 0xA6, 0x90, 0x63, 0x00, 0x00, 0x00, 0x00, 0x26, 0x11, 0x1A, 0xA6, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x78, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x68, 0x09, 0x98, 0x9D, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x9C, 0xB6, 0xD9, 0x9D, 0x8B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x29, 0xB9, 0x9D, 0xBC, 0xBE, 0xBC, 0xBE, 0xBC, 0xB6, 0xBC, 0xB6, 0xBC, 0xBE, 0x5B, 0xAE, 0x2A, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xF9, 0xA5, 0x9C, 0xB6, 0x9C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0xD9, 0x9D, 0xE1, 0xE1, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x00, 0xFA, 0xE1, 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, 0x22, 0x00, 0xC1, 0xD1, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0x40, 0xFA, 0xC0, 0xD1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xB1, 0xA0, 0xF9, 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xA0, 0xF9, 0x60, 0xD1, 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, 0x91, 0xE1, 0xE1, 0x00, 0xFA, 0x20, 0xFA, 0x20, 0xFA, + 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xA0, 0xE1, 0xE1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x8D, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x32, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x7C, 0x7C, 0xAE, 0x5B, 0xAE, 0x5C, 0xAE, 0x5C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0xF5, 0x84, 0x00, 0x00, 0x00, 0x00, 0x57, 0x95, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, + 0x5B, 0xAE, 0x7B, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x1A, 0xA6, 0x94, 0x7C, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x22, 0xFA, 0xA5, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x77, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x4B, 0x98, 0x95, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x7C, 0xAE, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xB6, 0x7C, 0xAE, 0x7B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x98, 0x95, 0xB1, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x29, 0x98, 0x9D, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x9C, 0xB6, 0x3B, 0xAE, 0x2A, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xD9, 0x9D, 0x7C, 0xAE, 0x7C, 0xAE, 0x5C, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0xB9, 0x9D, 0xA0, 0xE1, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xE2, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xA1, 0x00, 0xFA, 0x00, 0xFA, 0x20, 0xFA, 0x20, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0xFA, 0xE0, 0xF9, 0x21, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x41, 0xB9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xD1, 0x00, 0x00, 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, 0x81, 0xC1, 0xD9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA1, 0xD9, 0xE1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x6C, 0xFA, 0x9D, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0xFA, 0x9D, 0xFA, 0x9D, 0xB9, 0x95, 0x4B, 0x32, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x7C, 0x5B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x5B, 0xA6, 0x5B, 0xAE, 0xD5, 0x84, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x32, 0xB5, 0x7C, 0xB9, 0x9D, 0x3B, 0xA6, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x3B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x3B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0xD9, 0x9D, 0x74, 0x74, 0x4B, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x44, 0xFA, 0x9D, 0x1B, 0xA6, 0x1B, 0xA6, 0x1B, 0xA6, 0x1B, 0x9E, 0x1B, 0xA6, 0x57, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0x4A, 0x37, 0x8D, 0x1B, 0xA6, 0x3B, 0xA6, 0x3B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, + 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x5B, 0xAE, 0x3B, 0xAE, 0x3B, 0xA6, 0x1B, 0xA6, 0x37, 0x8D, 0xD1, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x29, 0x98, 0x95, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x7C, 0xAE, 0x1A, 0xA6, 0xEA, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB9, 0x95, 0x5B, 0xA6, 0x5B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0xB9, 0x9D, 0x60, 0xE1, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0xC2, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x38, 0x81, 0xC9, 0xE0, 0xF9, 0x00, 0xFA, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xA0, 0xE1, 0xE2, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xB1, 0x60, 0xF1, 0x40, 0xF1, 0x40, 0xF1, 0x20, 0xF1, 0x20, 0xF9, 0x40, 0xF9, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x50, 0x61, 0xB9, 0x81, 0xD1, 0xA0, 0xF1, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF1, 0x61, 0xD9, 0x41, 0xB1, + 0xA2, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x32, 0x58, 0x85, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xDA, 0x95, 0xBA, 0x95, 0xB9, 0x95, 0xD5, 0x7C, 0xE9, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x74, 0x3B, 0xA6, 0x1B, 0x9E, 0xFB, 0x9D, 0xFB, 0x9D, 0x1B, 0x9E, 0x1B, 0xA6, 0xD5, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x4B, 0xD5, 0x7C, 0x98, 0x95, 0x1B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x1B, 0xA6, 0xB9, 0x95, 0xF6, 0x84, 0xB0, 0x5B, 0x06, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x3C, 0xD9, 0x95, 0xDA, 0x9D, 0xFA, 0x9D, 0xDA, 0x9D, 0xDA, 0x9D, 0xFA, 0x9D, 0x37, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x42, 0x12, 0x6C, 0x57, 0x8D, 0xFA, 0xA5, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xAE, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x1B, 0xA6, 0xFA, 0x9D, 0x57, 0x8D, 0x53, 0x74, 0xCD, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x29, 0x78, 0x95, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0x3B, 0xA6, 0xF9, 0x9D, 0xA8, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x98, 0x95, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0x9E, 0x1B, 0xA6, 0x1B, 0xA6, 0xB8, 0x95, + 0xE1, 0xB0, 0x21, 0xC1, 0x41, 0xB9, 0x41, 0xC1, 0x41, 0xC9, 0x41, 0xD9, 0x20, 0xD9, 0xC7, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x99, 0xC0, 0xF9, 0xE0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xC0, 0xF9, 0xA0, 0xF9, 0x40, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x80, 0x01, 0xB9, 0x21, 0xC1, 0x21, 0xC1, 0x01, 0xC1, 0x01, 0xC1, 0x01, 0xD1, 0xE2, 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, 0x62, 0x30, 0xE1, 0x88, 0x41, 0xC1, 0x60, 0xC9, 0x80, 0xD9, 0x80, 0xE1, 0x80, 0xE1, 0x80, 0xD9, 0x61, 0xC9, 0x41, 0xC1, 0xE1, 0x90, 0xC6, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0xD1, 0x5B, 0x75, 0x6C, 0x33, 0x6C, 0x13, 0x64, 0x12, 0x64, 0x13, 0x64, 0x33, 0x6C, 0xF2, 0x63, 0xD1, 0x63, 0x6F, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x5B, 0xD5, 0x7C, 0x94, 0x74, 0x94, 0x74, + 0x94, 0x74, 0x94, 0x7C, 0x94, 0x7C, 0x6F, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x21, 0x12, 0x6C, 0x16, 0x85, 0x16, 0x8D, 0x77, 0x95, 0x98, 0x95, 0x98, 0x95, 0x78, 0x95, 0x16, 0x8D, 0x37, 0x8D, 0x53, 0x74, 0xC9, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x6C, 0x53, 0x6C, 0x33, 0x6C, 0x32, 0x6C, 0x12, 0x6C, 0x12, 0x6C, 0x90, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x5B, 0xB5, 0x7C, 0xD9, 0x9D, 0x57, 0x95, 0x98, 0x9D, 0x98, 0x9D, 0x57, 0x95, 0x98, 0x95, 0xB4, 0x7C, 0x0E, 0x4B, 0x06, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x67, 0x21, 0x11, 0x6C, 0xB5, 0x7C, 0xB5, 0x7C, 0xF6, 0x84, 0x16, 0x85, 0x16, 0x8D, 0x94, 0x7C, 0x26, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0xF2, 0x63, 0x74, 0x74, 0x94, 0x7C, 0xB5, 0x7C, 0xB5, 0x84, 0xD5, 0x84, 0x94, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x81, 0xA0, 0xE1, 0xC0, 0xF9, 0xA0, 0xF9, + 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF1, 0xC1, 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, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xA8, 0xE0, 0xC0, 0xE0, 0xB8, 0xE1, 0xB0, 0x21, 0xB1, 0x61, 0xC9, 0xA0, 0xE9, 0xA0, 0xF9, 0xA0, 0xF9, 0xA0, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x01, 0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC1, 0x40, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x80, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xD9, 0xA1, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x60, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xF9, 0xE0, 0xE0, 0xC1, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0xE0, 0xD8, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x40, 0xF9, 0x40, 0xF9, 0x20, 0xF9, 0x20, 0xF9, 0x00, 0xF9, 0x00, 0xD1, 0xA1, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x50, 0xC0, 0xD8, 0x00, 0xF9, 0x20, 0xF9, 0x00, 0xF9, 0x00, 0xF9, 0x00, 0xF9, 0x20, 0xF9, 0x20, 0xF1, + 0x00, 0xF1, 0xE0, 0xD8, 0xE1, 0xB8, 0xA2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x60, 0xA1, 0xB0, 0xC0, 0xD0, 0xC1, 0xD0, 0xC1, 0xD0, 0xC1, 0xD0, 0xC1, 0xC8, 0xE3, 0xD0, 0xE1, 0xB8, 0xA2, 0x90, 0x82, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //alpha channel data: - 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x11,0x11,0x11,0x11,0x11,0x11,0x05,0x47,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xDC,0xFF,0xFF,0xFF,0xFF,0xFF,0xB4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0xC2,0x96,0x56,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x40,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xAD,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x02,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB1,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x5A, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x00,0x5D,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x16,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xAE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x4A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x21,0x00,0x00,0x3C, - 0x4C,0x93,0x73,0x4B,0x45,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x45,0x4D,0x55,0x4E,0x45,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,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,0xFF,0xFF,0xE7,0xD3,0xD3,0xD3,0xD3,0xD3,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFE,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,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,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00, - 0x00,0x00,0x00,0x00,0x1F,0x5F,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0x3F,0x3F,0x3F,0x3F,0x10,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x33,0x43,0x76,0x8E,0x8E,0x69,0x3F,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x2D,0x52,0x8F,0x97,0x8F,0x86,0x46,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x2C,0x49,0x7F,0x8E,0x8E,0x8C,0x40,0x35,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x0C,0x0C,0x03, - 0x00,0x00,0x00,0x00,0x3C,0x52,0x8F,0x8E,0x84,0x43,0x1A,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x85,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xDA,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xEF,0xEF,0xEF, - 0xEF,0xEF,0xEF,0x6C,0x00,0x78,0xEF,0xEF,0xEF,0xEF,0xEF,0xD8,0x00,0x00,0x1E,0xB7,0xF6,0xFF,0xFF,0xFF,0xFF,0xF5,0x2A,0x00,0x00,0x00,0x00,0x00,0x1C,0x87,0xDE,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xD4,0x79,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x52,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x5B,0xF0,0xEF,0xEF,0xEF,0xEF,0xEF,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x7F,0xE4,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xED,0x9C,0x2F,0x01,0x00,0x00,0x00,0x00,0x01,0xE0,0xEF,0xEF,0xEF,0xEF,0xEF,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x7A,0xDF, - 0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF0,0x8F,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xD0,0xEF,0xF1,0xF2,0xF2,0xF2,0x9C,0x00,0x05,0x7C,0xDA,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xBB,0x34,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xFC,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0x95,0x50,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x05,0x58,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x2A,0x00,0x00,0x00,0x02,0x82,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xE8,0x4D,0x00,0x00,0x00,0x00,0x00,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x01,0x57,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFD,0xAD,0x2E,0x00,0x00,0x00,0x27,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x87,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0x19,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xF7,0x80,0x02,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x01,0xD4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x0E,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x8A,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x15,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xA0,0x07,0x00,0x00,0x00,0x05,0xDA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x71,0x00,0x00,0x00, - 0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x01,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x2B,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x06,0x9B,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x98,0x03,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x00,0x82,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xED,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0x00,0x00,0x02,0xB9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00,0x00,0x00,0x8A, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x22,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x29,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x11,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x99,0x03,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x00,0x2D,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00, - 0x4E,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x55,0x00,0x00,0x00,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x5D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0xAA, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBC,0xB6,0xEB,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x35,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xF6,0x08,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0x00,0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xA2,0x56,0x54,0x98,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x00,0x00,0x00,0x00,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8B,0x00,0x00,0x00,0x00, - 0x00,0x00,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x72,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x0C,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x5C,0x08,0x01,0x00,0x07,0x0D,0x4C,0x8B,0xF6,0xFF,0x92,0x01,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x00,0x00,0x00,0x01,0xA9,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xCE,0x69,0x55,0x55,0x58,0xC2,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDE,0x06,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xA5,0x64,0x55,0xA1,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x77,0x00,0x00,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0x06,0x00,0x00,0x00,0x00,0x00,0x7D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x80,0x43,0x43,0x43,0x45,0x8C,0x14,0x00,0x3B,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB2,0x08,0x00,0x00,0x00, - 0x00,0x14,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x00,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x00,0x00,0x00,0x00,0x00,0x15,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x24,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x38,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB0,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x21,0x89,0x0A,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x08,0x00,0x00,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x02,0x00,0x00,0x00,0x00,0x00,0x6B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4B,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9E,0x03,0x00,0x00,0x00,0x00,0x20,0xDD,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x85,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x35,0x00,0x00,0x17,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x46,0x00,0x00,0x00,0x00,0x03,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x51,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xAF,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x00,0x00,0x00,0x36,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x29,0x00,0x00,0x00,0x00,0x5B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00, - 0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x1E,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x07,0x00,0x00,0x6E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xD3,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x90,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x4D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC2,0x90,0x90,0x90,0x90,0x90,0x90,0xC8,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0x03,0x00,0x00,0x00,0xBB,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x00,0x00,0x13,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x0C,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7,0x00, - 0x00,0x00,0x00,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x61,0x00,0x00,0x00,0x00,0xB1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x4D,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x71,0x00,0x00,0x00,0x00,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x02,0x00,0x00,0x00,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x06,0x00,0x00,0x00,0xA2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7,0x00,0x00,0x00,0x14,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x21,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00, - 0x00,0xB7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0xD5,0x9A,0x46,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x02,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x00,0x00,0x03,0xF7,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC4,0x00,0x00,0x00,0x00,0x00,0x0D,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x37,0x00,0x00,0x01,0xB8,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x5C,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x13, - 0x00,0x00,0x5A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0x04,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x5D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFB,0x9F,0x46,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x09,0xE4,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x16,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xBE,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x97,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x86,0x00,0x00,0x12,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x18,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x05,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x47,0x00,0x00,0x97,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x01,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x43,0x00,0x00,0x00,0x00,0x09,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x08,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x6A,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xD8,0x00,0x00,0x53,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA8,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x00,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9D,0x00,0x09,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x37,0x00,0x00, - 0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x01,0x84,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x50,0x00,0x00,0x00,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x0C,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x39,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFA,0xB1,0x5C,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x2D,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x52,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFC,0x09,0x00,0x00,0x00,0x00,0x49,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x0A,0x41,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x92,0xE1,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x1D,0x00,0x00,0x3E, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x0A,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x28,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xA1,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x54,0x40,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x67,0x00,0xED,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x0F,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x09,0x00,0x00,0x00,0x00,0x0B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2E,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x3D,0x78,0xB3,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xB5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x00,0x00,0x03,0xF7, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x2F,0xFB,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8,0x02,0x00,0x00,0x00,0x00,0x00,0xA1,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0x83,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x47,0xB2,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0x01,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0xAF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA4,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x7A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB9,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDA,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x63,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x02,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9B,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x96, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x4F,0x91,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x02,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x56,0x00,0x00,0x00,0x00,0x00, - 0x00,0x38,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6D,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x08,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x4A,0x06,0x00,0x00,0x04,0x67,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFE,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x29,0xF7,0xFF,0xE6,0x4A,0x07,0x00,0x00,0x00,0x00,0x00,0x01,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1,0x02, - 0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x0B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x54,0x05,0x00,0x00,0x06,0x46,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x1D,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE5,0xB6,0xB6,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xAB,0x00,0x00,0x05,0xD5,0xFF,0xFF,0xFF,0xFE,0xEF,0xB0,0x69,0x69,0x67,0x67,0xA8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0,0x00,0x00,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xE0,0xB6,0xB6,0xE3,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8D,0x00,0x00,0x00, - 0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFD,0x1A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xF4, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x9E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x32,0x00,0x00,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00, - 0x00,0x06,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD3,0x18,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0xF3,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x9B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0x01,0x00,0x00,0x22,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x22,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x2D,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE5,0x5A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x32,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x04,0x77,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x83,0x01,0x00,0x00,0x00,0x08,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xC9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD2,0x1E,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xD2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x96,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x83,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x96, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAB,0x00,0x00,0x00,0x00,0x25,0xA8,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xB2,0x2F,0x01,0x00, - 0x00,0x00,0x00,0x04,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x70,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD9,0x67,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x46,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,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,0x00,0x00,0xA3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x3F,0x3F,0x3F,0x3F,0x3F,0x40,0x26,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x61,0x9D,0xE0,0xDF,0xDF,0xDF,0xDF,0xDE,0x91,0x54,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x3C,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x3F,0x3F,0x3F, - 0x3F,0x3F,0x3F,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x53,0x8F,0xC7,0xDF,0xDF,0xE5,0xE3,0xD7,0x8E,0x62,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x3F,0x3F,0x3F,0x3F,0x3F,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x89,0x93,0xDF,0xDF,0xDF,0xDC,0x8F,0x82,0x3F,0x05,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x01,0x3D,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xFC,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0xBD,0x94,0x94,0x94,0xB9,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xF9,0x9B,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xA9,0xB0,0xDD,0xFF,0xFF,0xFF,0xBD,0xAF,0x5F,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x05, 0x47, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xC2, 0x96, 0x56, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x40, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xAD, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x02, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB1, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x5A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x5D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x21, 0x00, 0x00, 0x3C, + 0x4C, 0x93, 0x73, 0x4B, 0x45, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x45, 0x4D, 0x55, 0x4E, 0x45, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 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, 0xFF, 0xFF, 0xE7, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x5F, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x3F, 0x3F, 0x3F, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x43, 0x76, 0x8E, 0x8E, 0x69, 0x3F, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2D, 0x52, 0x8F, 0x97, 0x8F, 0x86, 0x46, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2C, 0x49, 0x7F, 0x8E, 0x8E, 0x8C, 0x40, 0x35, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0C, 0x0C, 0x0C, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x3C, 0x52, 0x8F, 0x8E, 0x84, 0x43, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x85, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xDA, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xEF, 0xEF, 0xEF, + 0xEF, 0xEF, 0xEF, 0x6C, 0x00, 0x78, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xD8, 0x00, 0x00, 0x1E, 0xB7, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x87, 0xDE, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xD4, 0x79, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x5B, 0xF0, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x7F, 0xE4, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xED, 0x9C, 0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x7A, 0xDF, + 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF0, 0x8F, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0xEF, 0xF1, 0xF2, 0xF2, 0xF2, 0x9C, 0x00, 0x05, 0x7C, 0xDA, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xBB, 0x34, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x95, 0x50, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x05, 0x58, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x2A, 0x00, 0x00, 0x00, 0x02, 0x82, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xE8, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x01, 0x57, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xAD, 0x2E, 0x00, 0x00, 0x00, 0x27, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xE6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0x19, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF7, 0x80, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x01, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x0E, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x8A, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x15, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xA0, 0x07, 0x00, 0x00, 0x00, 0x05, 0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, + 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x01, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x2B, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x9B, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x98, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x00, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0x00, 0x00, 0x02, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x8A, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x22, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x29, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x11, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x03, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC6, 0x00, 0x2D, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x00, 0x00, + 0x4E, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x55, 0x00, 0x00, 0x00, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0xAA, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBC, 0xB6, 0xEB, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x35, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF6, 0x08, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xA2, 0x56, 0x54, 0x98, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8B, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x72, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x0C, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x5C, 0x08, 0x01, 0x00, 0x07, 0x0D, 0x4C, 0x8B, 0xF6, 0xFF, 0x92, 0x01, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x01, 0xA9, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCE, 0x69, 0x55, 0x55, 0x58, 0xC2, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0x06, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xA5, 0x64, 0x55, 0xA1, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x80, 0x43, 0x43, 0x43, 0x45, 0x8C, 0x14, 0x00, 0x3B, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x14, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x24, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x21, 0x89, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x08, 0x00, 0x00, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4B, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0xDD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x85, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x35, 0x00, 0x00, 0x17, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x46, 0x00, 0x00, 0x00, 0x00, 0x03, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xAF, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x00, 0x00, 0x00, 0x36, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x29, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x1E, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x07, 0x00, 0x00, 0x6E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE2, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xD3, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC2, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xC8, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x03, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x0C, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x00, + 0x00, 0x00, 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x00, 0x00, 0x00, 0x00, 0xB1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x4D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x71, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x02, 0x00, 0x00, 0x00, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x06, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0x00, 0x00, 0x00, 0x14, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, + 0x00, 0xB7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0xD5, 0x9A, 0x46, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x02, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x37, 0x00, 0x00, 0x01, 0xB8, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x13, + 0x00, 0x00, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFB, 0x9F, 0x46, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x09, 0xE4, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x16, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x86, 0x00, 0x00, 0x12, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x18, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x05, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0x00, 0x00, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x01, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x43, 0x00, 0x00, 0x00, 0x00, 0x09, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x08, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x6A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD8, 0x00, 0x00, 0x53, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0x00, 0x09, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x01, 0x84, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x50, 0x00, 0x00, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x0C, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFA, 0xB1, 0x5C, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x2D, 0x00, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x49, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x0A, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x92, 0xE1, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x1D, 0x00, 0x00, 0x3E, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x0A, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x28, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xA1, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x40, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x67, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0B, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x3D, 0x78, 0xB3, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0x03, 0xF7, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBD, 0x2F, 0xFB, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x83, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x47, 0xB2, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x01, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0xAF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE2, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDA, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x02, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x91, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x02, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6D, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x4A, 0x06, 0x00, 0x00, 0x04, 0x67, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x29, 0xF7, 0xFF, 0xE6, 0x4A, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x02, + 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x0B, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x54, 0x05, 0x00, 0x00, 0x06, 0x46, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x1D, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE5, 0xB6, 0xB6, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xAB, 0x00, 0x00, 0x05, 0xD5, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0xB0, 0x69, 0x69, 0x67, 0x67, 0xA8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0, 0xB6, 0xB6, 0xE3, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0x00, 0x00, 0x00, + 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xF4, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x32, 0x00, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, + 0x00, 0x06, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD3, 0x18, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xCB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xF3, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x01, 0x00, 0x00, 0x22, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE5, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x32, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x04, 0x77, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x83, 0x01, 0x00, 0x00, 0x00, 0x08, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xC9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x83, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x96, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x25, 0xA8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xB2, 0x2F, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x04, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x70, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x67, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x46, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 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, 0x00, 0x00, 0xA3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x26, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x61, 0x9D, 0xE0, 0xDF, 0xDF, 0xDF, 0xDF, 0xDE, 0x91, 0x54, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3C, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x53, 0x8F, 0xC7, 0xDF, 0xDF, 0xE5, 0xE3, 0xD7, 0x8E, 0x62, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x89, 0x93, 0xDF, 0xDF, 0xDF, 0xDC, 0x8F, 0x82, 0x3F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x3D, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xFC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xBD, 0x94, 0x94, 0x94, 0xB9, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF9, 0x9B, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xA9, 0xB0, 0xDD, 0xFF, 0xFF, 0xFF, 0xBD, 0xAF, 0x5F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const lv_image_dsc_t ui_img_text_218x40_png = { .header.w = 218, diff --git a/main/Application/Tasks/GUI/Export/project.info b/main/Application/Tasks/GUI/Export/project.info index 8f390c5..f3ccc0e 100644 --- a/main/Application/Tasks/GUI/Export/project.info +++ b/main/Application/Tasks/GUI/Export/project.info @@ -1,9 +1,9 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-02-06T07:11:20.7294523+01:00", + "datetime": "2026-02-07T22:29:20.6587403+01:00", "editor_version": "1.6.0", - "project_version": 105, + "project_version": 108, "user": "Kampert Daniel", - "export_datetime": "2026-02-07T12:26:53.4688234+01:00", + "export_datetime": "2026-02-07T22:40:25.7574865+01:00", "export_user": "Kampert Daniel" } diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.c b/main/Application/Tasks/GUI/Export/screens/ui_Info.c index 307ea58..3d9b2fa 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.c @@ -5,74 +5,74 @@ #include "../ui.h" -lv_obj_t * ui_Info = NULL; -lv_obj_t * ui_Panel_Info_Header = NULL; -lv_obj_t * ui_Label_Info_Header = NULL; -lv_obj_t * ui_Panel_Info_Content = NULL; -lv_obj_t * ui_Panel_Device = NULL; -lv_obj_t * ui_Label_Info_Device = NULL; -lv_obj_t * ui_Container_Info_Device = NULL; -lv_obj_t * ui_Info_Container4 = NULL; -lv_obj_t * ui_Label_Info_MAC_Name = NULL; -lv_obj_t * ui_Label_Info_IP_Name = NULL; -lv_obj_t * ui_Label_Info_Serial_Name = NULL; -lv_obj_t * ui_Info_Container5 = NULL; -lv_obj_t * ui_Label_Info_MAC = NULL; -lv_obj_t * ui_Label_Info_IP = NULL; -lv_obj_t * ui_Label_Info_Serial = NULL; -lv_obj_t * ui_Panel_Battery = NULL; -lv_obj_t * ui_Label_Info_Battery = NULL; -lv_obj_t * ui_Container_Battery = NULL; -lv_obj_t * ui_Info_Container2 = NULL; -lv_obj_t * ui_Label_Info_Battery_Status_Name = NULL; -lv_obj_t * ui_Label_Info_Battery_Voltage_Name = NULL; -lv_obj_t * ui_Label_Info_Battery_Remaining_Name = NULL; -lv_obj_t * ui_Info_Container3 = NULL; -lv_obj_t * ui_Label_Info_Battery_Status = NULL; -lv_obj_t * ui_Label_Info_Battery_Voltage = NULL; -lv_obj_t * ui_Label_Info_Battery_Remaining = NULL; -lv_obj_t * ui_Info_Bar2 = NULL; -lv_obj_t * ui_Panel_Lepton = NULL; -lv_obj_t * ui_Label_Info_Lepton = NULL; -lv_obj_t * ui_Container_Lepton = NULL; -lv_obj_t * ui_Info_Container1 = NULL; -lv_obj_t * ui_Label_Info_Lepton_Serial_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_Part_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_GPP_Revision_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_DSP_Revision_Main = NULL; -lv_obj_t * ui_Label_Info_Lepton_Uptime_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_FPA_Name = NULL; -lv_obj_t * ui_Label_Info_Lepton_AUX_Name = NULL; -lv_obj_t * ui_Info_Container7 = NULL; -lv_obj_t * ui_Label_Info_Lepton_Serial = NULL; -lv_obj_t * ui_Label_Info_Lepton_Part = NULL; -lv_obj_t * ui_Label_Info_Lepton_GPP_Revision = NULL; -lv_obj_t * ui_Label_Info_Lepton_DSP_Revision = NULL; -lv_obj_t * ui_Label_Info_Lepton_Uptime = NULL; -lv_obj_t * ui_Label_Info_Lepton_FPA = NULL; -lv_obj_t * ui_Label_Info_Lepton_AUX = NULL; -lv_obj_t * ui_Container_Info_Buttons = NULL; -lv_obj_t * ui_Button_Info_Back = NULL; -lv_obj_t * ui_Label_Info_Back = NULL; +lv_obj_t *ui_Info = NULL; +lv_obj_t *ui_Panel_Info_Header = NULL; +lv_obj_t *ui_Label_Info_Header = NULL; +lv_obj_t *ui_Panel_Info_Content = NULL; +lv_obj_t *ui_Panel_Device = NULL; +lv_obj_t *ui_Label_Info_Device = NULL; +lv_obj_t *ui_Container_Info_Device = NULL; +lv_obj_t *ui_Info_Container4 = NULL; +lv_obj_t *ui_Label_Info_MAC_Name = NULL; +lv_obj_t *ui_Label_Info_IP_Name = NULL; +lv_obj_t *ui_Label_Info_Serial_Name = NULL; +lv_obj_t *ui_Info_Container5 = NULL; +lv_obj_t *ui_Label_Info_MAC = NULL; +lv_obj_t *ui_Label_Info_IP = NULL; +lv_obj_t *ui_Label_Info_Serial = NULL; +lv_obj_t *ui_Panel_Battery = NULL; +lv_obj_t *ui_Label_Info_Battery = NULL; +lv_obj_t *ui_Container_Battery = NULL; +lv_obj_t *ui_Info_Container2 = NULL; +lv_obj_t *ui_Label_Info_Battery_Status_Name = NULL; +lv_obj_t *ui_Label_Info_Battery_Voltage_Name = NULL; +lv_obj_t *ui_Label_Info_Battery_Remaining_Name = NULL; +lv_obj_t *ui_Info_Container3 = NULL; +lv_obj_t *ui_Label_Info_Battery_Status = NULL; +lv_obj_t *ui_Label_Info_Battery_Voltage = NULL; +lv_obj_t *ui_Label_Info_Battery_Remaining = NULL; +lv_obj_t *ui_Info_Bar2 = NULL; +lv_obj_t *ui_Panel_Lepton = NULL; +lv_obj_t *ui_Label_Info_Lepton = NULL; +lv_obj_t *ui_Container_Lepton = NULL; +lv_obj_t *ui_Info_Container1 = NULL; +lv_obj_t *ui_Label_Info_Lepton_Serial_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_Part_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_GPP_Revision_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_DSP_Revision_Main = NULL; +lv_obj_t *ui_Label_Info_Lepton_Uptime_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_FPA_Name = NULL; +lv_obj_t *ui_Label_Info_Lepton_AUX_Name = NULL; +lv_obj_t *ui_Info_Container7 = NULL; +lv_obj_t *ui_Label_Info_Lepton_Serial = NULL; +lv_obj_t *ui_Label_Info_Lepton_Part = NULL; +lv_obj_t *ui_Label_Info_Lepton_GPP_Revision = NULL; +lv_obj_t *ui_Label_Info_Lepton_DSP_Revision = NULL; +lv_obj_t *ui_Label_Info_Lepton_Uptime = NULL; +lv_obj_t *ui_Label_Info_Lepton_FPA = NULL; +lv_obj_t *ui_Label_Info_Lepton_AUX = NULL; +lv_obj_t *ui_Container_Info_Buttons = NULL; +lv_obj_t *ui_Button_Info_Back = NULL; +lv_obj_t *ui_Label_Info_Back = NULL; // event funtions -void ui_event_Info(lv_event_t * e) +void ui_event_Info(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { + if (event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { lv_indev_wait_release(lv_indev_active()); _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } - if(event_code == LV_EVENT_SCREEN_LOADED) { + if (event_code == LV_EVENT_SCREEN_LOADED) { ScreenInfoLoaded(e); } } -void ui_event_Button_Info_Back(lv_event_t * e) +void ui_event_Button_Info_Back(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } } @@ -489,8 +489,8 @@ void ui_Info_screen_init(void) lv_obj_set_style_bg_grad_dir(ui_Info_Bar2, LV_GRAD_DIR_HOR, LV_PART_INDICATOR | LV_STATE_DEFAULT); //Compensating for LVGL9.1 draw crash with bar/slider max value when top-padding is nonzero and right-padding is 0 - if(lv_obj_get_style_pad_top(ui_Info_Bar2, LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_Info_Bar2, - lv_obj_get_style_pad_right(ui_Info_Bar2, LV_PART_MAIN) + 1, LV_PART_MAIN); + if (lv_obj_get_style_pad_top(ui_Info_Bar2, LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_Info_Bar2, + lv_obj_get_style_pad_right(ui_Info_Bar2, LV_PART_MAIN) + 1, LV_PART_MAIN); ui_Panel_Lepton = lv_obj_create(ui_Panel_Info_Content); lv_obj_set_width(ui_Panel_Lepton, 300); lv_obj_set_height(ui_Panel_Lepton, LV_SIZE_CONTENT); /// 1 @@ -826,7 +826,9 @@ void ui_Info_screen_init(void) void ui_Info_screen_destroy(void) { - if(ui_Info) lv_obj_del(ui_Info); + if (ui_Info) { + lv_obj_del(ui_Info); + } // NULL screen variables ui_Info = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Info.h b/main/Application/Tasks/GUI/Export/screens/ui_Info.h index 44372dc..69c782a 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Info.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Info.h @@ -13,57 +13,57 @@ extern "C" { // SCREEN: ui_Info extern void ui_Info_screen_init(void); extern void ui_Info_screen_destroy(void); -extern void ui_event_Info(lv_event_t * e); -extern lv_obj_t * ui_Info; -extern lv_obj_t * ui_Panel_Info_Header; -extern lv_obj_t * ui_Label_Info_Header; -extern lv_obj_t * ui_Panel_Info_Content; -extern lv_obj_t * ui_Panel_Device; -extern lv_obj_t * ui_Label_Info_Device; -extern lv_obj_t * ui_Container_Info_Device; -extern lv_obj_t * ui_Info_Container4; -extern lv_obj_t * ui_Label_Info_MAC_Name; -extern lv_obj_t * ui_Label_Info_IP_Name; -extern lv_obj_t * ui_Label_Info_Serial_Name; -extern lv_obj_t * ui_Info_Container5; -extern lv_obj_t * ui_Label_Info_MAC; -extern lv_obj_t * ui_Label_Info_IP; -extern lv_obj_t * ui_Label_Info_Serial; -extern lv_obj_t * ui_Panel_Battery; -extern lv_obj_t * ui_Label_Info_Battery; -extern lv_obj_t * ui_Container_Battery; -extern lv_obj_t * ui_Info_Container2; -extern lv_obj_t * ui_Label_Info_Battery_Status_Name; -extern lv_obj_t * ui_Label_Info_Battery_Voltage_Name; -extern lv_obj_t * ui_Label_Info_Battery_Remaining_Name; -extern lv_obj_t * ui_Info_Container3; -extern lv_obj_t * ui_Label_Info_Battery_Status; -extern lv_obj_t * ui_Label_Info_Battery_Voltage; -extern lv_obj_t * ui_Label_Info_Battery_Remaining; -extern lv_obj_t * ui_Info_Bar2; -extern lv_obj_t * ui_Panel_Lepton; -extern lv_obj_t * ui_Label_Info_Lepton; -extern lv_obj_t * ui_Container_Lepton; -extern lv_obj_t * ui_Info_Container1; -extern lv_obj_t * ui_Label_Info_Lepton_Serial_Name; -extern lv_obj_t * ui_Label_Info_Lepton_Part_Name; -extern lv_obj_t * ui_Label_Info_Lepton_GPP_Revision_Name; -extern lv_obj_t * ui_Label_Info_Lepton_DSP_Revision_Main; -extern lv_obj_t * ui_Label_Info_Lepton_Uptime_Name; -extern lv_obj_t * ui_Label_Info_Lepton_FPA_Name; -extern lv_obj_t * ui_Label_Info_Lepton_AUX_Name; -extern lv_obj_t * ui_Info_Container7; -extern lv_obj_t * ui_Label_Info_Lepton_Serial; -extern lv_obj_t * ui_Label_Info_Lepton_Part; -extern lv_obj_t * ui_Label_Info_Lepton_GPP_Revision; -extern lv_obj_t * ui_Label_Info_Lepton_DSP_Revision; -extern lv_obj_t * ui_Label_Info_Lepton_Uptime; -extern lv_obj_t * ui_Label_Info_Lepton_FPA; -extern lv_obj_t * ui_Label_Info_Lepton_AUX; -extern lv_obj_t * ui_Container_Info_Buttons; -extern void ui_event_Button_Info_Back(lv_event_t * e); -extern lv_obj_t * ui_Button_Info_Back; -extern lv_obj_t * ui_Label_Info_Back; +extern void ui_event_Info(lv_event_t *e); +extern lv_obj_t *ui_Info; +extern lv_obj_t *ui_Panel_Info_Header; +extern lv_obj_t *ui_Label_Info_Header; +extern lv_obj_t *ui_Panel_Info_Content; +extern lv_obj_t *ui_Panel_Device; +extern lv_obj_t *ui_Label_Info_Device; +extern lv_obj_t *ui_Container_Info_Device; +extern lv_obj_t *ui_Info_Container4; +extern lv_obj_t *ui_Label_Info_MAC_Name; +extern lv_obj_t *ui_Label_Info_IP_Name; +extern lv_obj_t *ui_Label_Info_Serial_Name; +extern lv_obj_t *ui_Info_Container5; +extern lv_obj_t *ui_Label_Info_MAC; +extern lv_obj_t *ui_Label_Info_IP; +extern lv_obj_t *ui_Label_Info_Serial; +extern lv_obj_t *ui_Panel_Battery; +extern lv_obj_t *ui_Label_Info_Battery; +extern lv_obj_t *ui_Container_Battery; +extern lv_obj_t *ui_Info_Container2; +extern lv_obj_t *ui_Label_Info_Battery_Status_Name; +extern lv_obj_t *ui_Label_Info_Battery_Voltage_Name; +extern lv_obj_t *ui_Label_Info_Battery_Remaining_Name; +extern lv_obj_t *ui_Info_Container3; +extern lv_obj_t *ui_Label_Info_Battery_Status; +extern lv_obj_t *ui_Label_Info_Battery_Voltage; +extern lv_obj_t *ui_Label_Info_Battery_Remaining; +extern lv_obj_t *ui_Info_Bar2; +extern lv_obj_t *ui_Panel_Lepton; +extern lv_obj_t *ui_Label_Info_Lepton; +extern lv_obj_t *ui_Container_Lepton; +extern lv_obj_t *ui_Info_Container1; +extern lv_obj_t *ui_Label_Info_Lepton_Serial_Name; +extern lv_obj_t *ui_Label_Info_Lepton_Part_Name; +extern lv_obj_t *ui_Label_Info_Lepton_GPP_Revision_Name; +extern lv_obj_t *ui_Label_Info_Lepton_DSP_Revision_Main; +extern lv_obj_t *ui_Label_Info_Lepton_Uptime_Name; +extern lv_obj_t *ui_Label_Info_Lepton_FPA_Name; +extern lv_obj_t *ui_Label_Info_Lepton_AUX_Name; +extern lv_obj_t *ui_Info_Container7; +extern lv_obj_t *ui_Label_Info_Lepton_Serial; +extern lv_obj_t *ui_Label_Info_Lepton_Part; +extern lv_obj_t *ui_Label_Info_Lepton_GPP_Revision; +extern lv_obj_t *ui_Label_Info_Lepton_DSP_Revision; +extern lv_obj_t *ui_Label_Info_Lepton_Uptime; +extern lv_obj_t *ui_Label_Info_Lepton_FPA; +extern lv_obj_t *ui_Label_Info_Lepton_AUX; +extern lv_obj_t *ui_Container_Info_Buttons; +extern void ui_event_Button_Info_Back(lv_event_t *e); +extern lv_obj_t *ui_Button_Info_Back; +extern lv_obj_t *ui_Label_Info_Back; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.c b/main/Application/Tasks/GUI/Export/screens/ui_Main.c index dcb94e4..2627527 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.c @@ -5,70 +5,70 @@ #include "../ui.h" -lv_obj_t * ui_Main = NULL; -lv_obj_t * ui_Container_Main_StatusBar = NULL; -lv_obj_t * ui_Image_Main_WiFi = NULL; -lv_obj_t * ui_Image_Main_SDCard = NULL; -lv_obj_t * ui_Label_Main_Time = NULL; -lv_obj_t * ui_Label_Main_Battery_Remaining = NULL; -lv_obj_t * ui_Container_Main_Thermal = NULL; -lv_obj_t * ui_Image_Thermal = NULL; -lv_obj_t * ui_Image_Main_Thermal_Scene_ROI = NULL; -lv_obj_t * ui_Image_Main_Thermal_Spotmeter_ROI = NULL; -lv_obj_t * ui_Image_Main_Thermal_Video_Focus_ROI = NULL; -lv_obj_t * ui_Image_Main_Thermal_AGC_ROI = NULL; -lv_obj_t * ui_Label_Main_Thermal_Crosshair = NULL; -lv_obj_t * ui_Label_Main_Thermal_PixelTemperature = NULL; -lv_obj_t * ui_Container_Main_Thermal_Scene_Statistics = NULL; -lv_obj_t * ui_Label_Main_Thermal_Scene_Max = NULL; -lv_obj_t * ui_Label_Main_Thermal_Scene_Min = NULL; -lv_obj_t * ui_Label_Main_Thermal_Scene_Mean = NULL; -lv_obj_t * ui_Container_Gradient = NULL; -lv_obj_t * ui_Label_TempScaleMax = NULL; -lv_obj_t * ui_Image_Gradient = NULL; -lv_obj_t * ui_Label_TempScaleMin = NULL; -lv_obj_t * ui_Container_Main_Buttons = NULL; -lv_obj_t * ui_Button_Main_WiFi = NULL; -lv_obj_t * ui_Label_Main_Button_WiFi = NULL; -lv_obj_t * ui_Button_Main_ROI = NULL; -lv_obj_t * ui_Label_Main_Button_ROI = NULL; -lv_obj_t * ui_Button_Main_Info = NULL; -lv_obj_t * ui_Label_Main_Button_Info = NULL; -lv_obj_t * ui_Button_Main_Menu = NULL; -lv_obj_t * ui_Label_Main_Button_Menu = NULL; +lv_obj_t *ui_Main = NULL; +lv_obj_t *ui_Container_Main_StatusBar = NULL; +lv_obj_t *ui_Image_Main_WiFi = NULL; +lv_obj_t *ui_Image_Main_SDCard = NULL; +lv_obj_t *ui_Label_Main_Time = NULL; +lv_obj_t *ui_Label_Main_Battery_Remaining = NULL; +lv_obj_t *ui_Container_Main_Thermal = NULL; +lv_obj_t *ui_Image_Thermal = NULL; +lv_obj_t *ui_Image_Main_Thermal_Scene_ROI = NULL; +lv_obj_t *ui_Image_Main_Thermal_Spotmeter_ROI = NULL; +lv_obj_t *ui_Image_Main_Thermal_Video_Focus_ROI = NULL; +lv_obj_t *ui_Image_Main_Thermal_AGC_ROI = NULL; +lv_obj_t *ui_Label_Main_Thermal_Crosshair = NULL; +lv_obj_t *ui_Label_Main_Thermal_PixelTemperature = NULL; +lv_obj_t *ui_Container_Main_Thermal_Scene_Statistics = NULL; +lv_obj_t *ui_Label_Main_Thermal_Scene_Max = NULL; +lv_obj_t *ui_Label_Main_Thermal_Scene_Min = NULL; +lv_obj_t *ui_Label_Main_Thermal_Scene_Mean = NULL; +lv_obj_t *ui_Container_Gradient = NULL; +lv_obj_t *ui_Label_TempScaleMax = NULL; +lv_obj_t *ui_Image_Gradient = NULL; +lv_obj_t *ui_Label_TempScaleMin = NULL; +lv_obj_t *ui_Container_Main_Buttons = NULL; +lv_obj_t *ui_Button_Main_Save = NULL; +lv_obj_t *ui_Label_Main_Button_Save = NULL; +lv_obj_t *ui_Button_Main_ROI = NULL; +lv_obj_t *ui_Label_Main_Button_ROI = NULL; +lv_obj_t *ui_Button_Main_Info = NULL; +lv_obj_t *ui_Label_Main_Button_Info = NULL; +lv_obj_t *ui_Button_Main_Menu = NULL; +lv_obj_t *ui_Label_Main_Button_Menu = NULL; // event funtions -void ui_event_Main(lv_event_t * e) +void ui_event_Main(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_SCREEN_LOADED) { + if (event_code == LV_EVENT_SCREEN_LOADED) { ScreenMainLoaded(e); } } -void ui_event_Button_Main_WiFi(lv_event_t * e) +void ui_event_Button_Main_Save(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { - ButtonMainWiFiClicked(e); + if (event_code == LV_EVENT_CLICKED) { + ButtonMainSaveClicked(e); } } -void ui_event_Button_Main_Info(lv_event_t * e) +void ui_event_Button_Main_Info(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Info, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Info_screen_init); } } -void ui_event_Button_Main_Menu(lv_event_t * e) +void ui_event_Button_Main_Menu(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Menu, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Menu_screen_init); } } @@ -353,34 +353,34 @@ void ui_Main_screen_init(void) lv_obj_set_align(ui_Container_Main_Buttons, LV_ALIGN_CENTER); lv_obj_remove_flag(ui_Container_Main_Buttons, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE); /// Flags - ui_Button_Main_WiFi = lv_button_create(ui_Container_Main_Buttons); - lv_obj_set_width(ui_Button_Main_WiFi, 50); - lv_obj_set_height(ui_Button_Main_WiFi, lv_pct(95)); - lv_obj_set_x(ui_Button_Main_WiFi, -20); - lv_obj_set_y(ui_Button_Main_WiFi, 0); - lv_obj_set_align(ui_Button_Main_WiFi, LV_ALIGN_CENTER); - lv_obj_remove_flag(ui_Button_Main_WiFi, + ui_Button_Main_Save = lv_button_create(ui_Container_Main_Buttons); + lv_obj_set_width(ui_Button_Main_Save, 50); + lv_obj_set_height(ui_Button_Main_Save, lv_pct(95)); + lv_obj_set_x(ui_Button_Main_Save, 100); + lv_obj_set_y(ui_Button_Main_Save, 0); + lv_obj_set_align(ui_Button_Main_Save, LV_ALIGN_CENTER); + lv_obj_remove_flag(ui_Button_Main_Save, LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN); /// Flags - lv_obj_set_style_bg_color(ui_Button_Main_WiFi, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_bg_opa(ui_Button_Main_WiFi, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_border_color(ui_Button_Main_WiFi, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_border_opa(ui_Button_Main_WiFi, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_border_width(ui_Button_Main_WiFi, 2, LV_PART_MAIN | LV_STATE_DEFAULT); - - ui_Label_Main_Button_WiFi = lv_label_create(ui_Button_Main_WiFi); - lv_obj_set_width(ui_Label_Main_Button_WiFi, LV_SIZE_CONTENT); /// 1 - lv_obj_set_height(ui_Label_Main_Button_WiFi, LV_SIZE_CONTENT); /// 1 - lv_obj_set_align(ui_Label_Main_Button_WiFi, LV_ALIGN_CENTER); - lv_label_set_text(ui_Label_Main_Button_WiFi, "W"); - lv_obj_set_style_text_color(ui_Label_Main_Button_WiFi, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_opa(ui_Label_Main_Button_WiFi, 255, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_set_style_text_font(ui_Label_Main_Button_WiFi, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_color(ui_Button_Main_Save, lv_color_hex(0x323232), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_Button_Main_Save, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(ui_Button_Main_Save, lv_color_hex(0xB998FF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(ui_Button_Main_Save, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(ui_Button_Main_Save, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_Label_Main_Button_Save = lv_label_create(ui_Button_Main_Save); + lv_obj_set_width(ui_Label_Main_Button_Save, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_Label_Main_Button_Save, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_Label_Main_Button_Save, LV_ALIGN_CENTER); + lv_label_set_text(ui_Label_Main_Button_Save, "S"); + lv_obj_set_style_text_color(ui_Label_Main_Button_Save, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_opa(ui_Label_Main_Button_Save, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_text_font(ui_Label_Main_Button_Save, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); ui_Button_Main_ROI = lv_button_create(ui_Container_Main_Buttons); lv_obj_set_width(ui_Button_Main_ROI, 50); lv_obj_set_height(ui_Button_Main_ROI, lv_pct(95)); - lv_obj_set_x(ui_Button_Main_ROI, 100); + lv_obj_set_x(ui_Button_Main_ROI, -20); lv_obj_set_y(ui_Button_Main_ROI, 0); lv_obj_set_align(ui_Button_Main_ROI, LV_ALIGN_CENTER); lv_obj_remove_flag(ui_Button_Main_ROI, @@ -445,7 +445,7 @@ void ui_Main_screen_init(void) lv_label_set_text(ui_Label_Main_Button_Menu, "M"); lv_obj_set_style_text_font(ui_Label_Main_Button_Menu, &ui_font_fa, LV_PART_MAIN | LV_STATE_DEFAULT); - lv_obj_add_event_cb(ui_Button_Main_WiFi, ui_event_Button_Main_WiFi, LV_EVENT_ALL, NULL); + lv_obj_add_event_cb(ui_Button_Main_Save, ui_event_Button_Main_Save, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(ui_Button_Main_Info, ui_event_Button_Main_Info, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(ui_Button_Main_Menu, ui_event_Button_Main_Menu, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(ui_Main, ui_event_Main, LV_EVENT_ALL, NULL); @@ -454,7 +454,9 @@ void ui_Main_screen_init(void) void ui_Main_screen_destroy(void) { - if(ui_Main) lv_obj_del(ui_Main); + if (ui_Main) { + lv_obj_del(ui_Main); + } // NULL screen variables ui_Main = NULL; @@ -480,8 +482,8 @@ void ui_Main_screen_destroy(void) ui_Image_Gradient = NULL; ui_Label_TempScaleMin = NULL; ui_Container_Main_Buttons = NULL; - ui_Button_Main_WiFi = NULL; - ui_Label_Main_Button_WiFi = NULL; + ui_Button_Main_Save = NULL; + ui_Label_Main_Button_Save = NULL; ui_Button_Main_ROI = NULL; ui_Label_Main_Button_ROI = NULL; ui_Button_Main_Info = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Main.h b/main/Application/Tasks/GUI/Export/screens/ui_Main.h index dd59eae..5622ae7 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Main.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Main.h @@ -13,41 +13,41 @@ extern "C" { // SCREEN: ui_Main extern void ui_Main_screen_init(void); extern void ui_Main_screen_destroy(void); -extern void ui_event_Main(lv_event_t * e); -extern lv_obj_t * ui_Main; -extern lv_obj_t * ui_Container_Main_StatusBar; -extern lv_obj_t * ui_Image_Main_WiFi; -extern lv_obj_t * ui_Image_Main_SDCard; -extern lv_obj_t * ui_Label_Main_Time; -extern lv_obj_t * ui_Label_Main_Battery_Remaining; -extern lv_obj_t * ui_Container_Main_Thermal; -extern lv_obj_t * ui_Image_Thermal; -extern lv_obj_t * ui_Image_Main_Thermal_Scene_ROI; -extern lv_obj_t * ui_Image_Main_Thermal_Spotmeter_ROI; -extern lv_obj_t * ui_Image_Main_Thermal_Video_Focus_ROI; -extern lv_obj_t * ui_Image_Main_Thermal_AGC_ROI; -extern lv_obj_t * ui_Label_Main_Thermal_Crosshair; -extern lv_obj_t * ui_Label_Main_Thermal_PixelTemperature; -extern lv_obj_t * ui_Container_Main_Thermal_Scene_Statistics; -extern lv_obj_t * ui_Label_Main_Thermal_Scene_Max; -extern lv_obj_t * ui_Label_Main_Thermal_Scene_Min; -extern lv_obj_t * ui_Label_Main_Thermal_Scene_Mean; -extern lv_obj_t * ui_Container_Gradient; -extern lv_obj_t * ui_Label_TempScaleMax; -extern lv_obj_t * ui_Image_Gradient; -extern lv_obj_t * ui_Label_TempScaleMin; -extern lv_obj_t * ui_Container_Main_Buttons; -extern void ui_event_Button_Main_WiFi(lv_event_t * e); -extern lv_obj_t * ui_Button_Main_WiFi; -extern lv_obj_t * ui_Label_Main_Button_WiFi; -extern lv_obj_t * ui_Button_Main_ROI; -extern lv_obj_t * ui_Label_Main_Button_ROI; -extern void ui_event_Button_Main_Info(lv_event_t * e); -extern lv_obj_t * ui_Button_Main_Info; -extern lv_obj_t * ui_Label_Main_Button_Info; -extern void ui_event_Button_Main_Menu(lv_event_t * e); -extern lv_obj_t * ui_Button_Main_Menu; -extern lv_obj_t * ui_Label_Main_Button_Menu; +extern void ui_event_Main(lv_event_t *e); +extern lv_obj_t *ui_Main; +extern lv_obj_t *ui_Container_Main_StatusBar; +extern lv_obj_t *ui_Image_Main_WiFi; +extern lv_obj_t *ui_Image_Main_SDCard; +extern lv_obj_t *ui_Label_Main_Time; +extern lv_obj_t *ui_Label_Main_Battery_Remaining; +extern lv_obj_t *ui_Container_Main_Thermal; +extern lv_obj_t *ui_Image_Thermal; +extern lv_obj_t *ui_Image_Main_Thermal_Scene_ROI; +extern lv_obj_t *ui_Image_Main_Thermal_Spotmeter_ROI; +extern lv_obj_t *ui_Image_Main_Thermal_Video_Focus_ROI; +extern lv_obj_t *ui_Image_Main_Thermal_AGC_ROI; +extern lv_obj_t *ui_Label_Main_Thermal_Crosshair; +extern lv_obj_t *ui_Label_Main_Thermal_PixelTemperature; +extern lv_obj_t *ui_Container_Main_Thermal_Scene_Statistics; +extern lv_obj_t *ui_Label_Main_Thermal_Scene_Max; +extern lv_obj_t *ui_Label_Main_Thermal_Scene_Min; +extern lv_obj_t *ui_Label_Main_Thermal_Scene_Mean; +extern lv_obj_t *ui_Container_Gradient; +extern lv_obj_t *ui_Label_TempScaleMax; +extern lv_obj_t *ui_Image_Gradient; +extern lv_obj_t *ui_Label_TempScaleMin; +extern lv_obj_t *ui_Container_Main_Buttons; +extern void ui_event_Button_Main_Save(lv_event_t *e); +extern lv_obj_t *ui_Button_Main_Save; +extern lv_obj_t *ui_Label_Main_Button_Save; +extern lv_obj_t *ui_Button_Main_ROI; +extern lv_obj_t *ui_Label_Main_Button_ROI; +extern void ui_event_Button_Main_Info(lv_event_t *e); +extern lv_obj_t *ui_Button_Main_Info; +extern lv_obj_t *ui_Label_Main_Button_Info; +extern void ui_event_Button_Main_Menu(lv_event_t *e); +extern lv_obj_t *ui_Button_Main_Menu; +extern lv_obj_t *ui_Label_Main_Button_Menu; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c index 719b107..e5f46e3 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.c @@ -5,40 +5,40 @@ #include "../ui.h" -lv_obj_t * ui_Menu = NULL; -lv_obj_t * ui_Panel_Menu_Header = NULL; -lv_obj_t * ui_Label_Menu_Header = NULL; -lv_obj_t * ui_Container_Menu = NULL; -lv_obj_t * ui_Container_Menu_Buttons = NULL; -lv_obj_t * ui_Button_Menu_Back = NULL; -lv_obj_t * ui_Label_Menu_Back = NULL; -lv_obj_t * ui_Button_Menu_Save = NULL; -lv_obj_t * ui_Label_Menu_Button_Save = NULL; +lv_obj_t *ui_Menu = NULL; +lv_obj_t *ui_Panel_Menu_Header = NULL; +lv_obj_t *ui_Label_Menu_Header = NULL; +lv_obj_t *ui_Container_Menu = NULL; +lv_obj_t *ui_Container_Menu_Buttons = NULL; +lv_obj_t *ui_Button_Menu_Back = NULL; +lv_obj_t *ui_Label_Menu_Back = NULL; +lv_obj_t *ui_Button_Menu_Save = NULL; +lv_obj_t *ui_Label_Menu_Button_Save = NULL; // event funtions -void ui_event_Menu(lv_event_t * e) +void ui_event_Menu(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { + if (event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_active()) == LV_DIR_RIGHT) { lv_indev_wait_release(lv_indev_active()); _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } } -void ui_event_Button_Menu_Back(lv_event_t * e) +void ui_event_Button_Menu_Back(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { _ui_screen_change(&ui_Main, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_Main_screen_init); } } -void ui_event_Button_Menu_Save(lv_event_t * e) +void ui_event_Button_Menu_Save(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_CLICKED) { + if (event_code == LV_EVENT_CLICKED) { ButtonMenuSaveClicked(e); } } @@ -153,7 +153,9 @@ void ui_Menu_screen_init(void) void ui_Menu_screen_destroy(void) { - if(ui_Menu) lv_obj_del(ui_Menu); + if (ui_Menu) { + lv_obj_del(ui_Menu); + } // NULL screen variables ui_Menu = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h index 654db67..daa32a9 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Menu.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Menu.h @@ -13,18 +13,18 @@ extern "C" { // SCREEN: ui_Menu extern void ui_Menu_screen_init(void); extern void ui_Menu_screen_destroy(void); -extern void ui_event_Menu(lv_event_t * e); -extern lv_obj_t * ui_Menu; -extern lv_obj_t * ui_Panel_Menu_Header; -extern lv_obj_t * ui_Label_Menu_Header; -extern lv_obj_t * ui_Container_Menu; -extern lv_obj_t * ui_Container_Menu_Buttons; -extern void ui_event_Button_Menu_Back(lv_event_t * e); -extern lv_obj_t * ui_Button_Menu_Back; -extern lv_obj_t * ui_Label_Menu_Back; -extern void ui_event_Button_Menu_Save(lv_event_t * e); -extern lv_obj_t * ui_Button_Menu_Save; -extern lv_obj_t * ui_Label_Menu_Button_Save; +extern void ui_event_Menu(lv_event_t *e); +extern lv_obj_t *ui_Menu; +extern lv_obj_t *ui_Panel_Menu_Header; +extern lv_obj_t *ui_Label_Menu_Header; +extern lv_obj_t *ui_Container_Menu; +extern lv_obj_t *ui_Container_Menu_Buttons; +extern void ui_event_Button_Menu_Back(lv_event_t *e); +extern lv_obj_t *ui_Button_Menu_Back; +extern lv_obj_t *ui_Label_Menu_Back; +extern void ui_event_Button_Menu_Save(lv_event_t *e); +extern lv_obj_t *ui_Button_Menu_Save; +extern lv_obj_t *ui_Label_Menu_Button_Save; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c index e0ab155..9288416 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.c +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.c @@ -5,19 +5,19 @@ #include "../ui.h" -lv_obj_t * ui_Splash = NULL; -lv_obj_t * ui_SplashScreen_Logo = NULL; -lv_obj_t * ui_SplashScreen_LogoText = NULL; -lv_obj_t * ui_SplashScreen_Subtext = NULL; -lv_obj_t * ui_SplashScreen_LoadingBar = NULL; -lv_obj_t * ui_SplashScreen_StatusText = NULL; -lv_obj_t * ui_SplashScreen_FirmwareVersion = NULL; +lv_obj_t *ui_Splash = NULL; +lv_obj_t *ui_SplashScreen_Logo = NULL; +lv_obj_t *ui_SplashScreen_LogoText = NULL; +lv_obj_t *ui_SplashScreen_Subtext = NULL; +lv_obj_t *ui_SplashScreen_LoadingBar = NULL; +lv_obj_t *ui_SplashScreen_StatusText = NULL; +lv_obj_t *ui_SplashScreen_FirmwareVersion = NULL; // event funtions -void ui_event_Splash(lv_event_t * e) +void ui_event_Splash(lv_event_t *e) { lv_event_code_t event_code = lv_event_get_code(e); - if(event_code == LV_EVENT_SCREEN_LOADED) { + if (event_code == LV_EVENT_SCREEN_LOADED) { ScreenSplashLoaded(e); } } @@ -85,9 +85,9 @@ void ui_Splash_screen_init(void) lv_obj_set_style_bg_opa(ui_SplashScreen_LoadingBar, 255, LV_PART_INDICATOR | LV_STATE_DEFAULT); //Compensating for LVGL9.1 draw crash with bar/slider max value when top-padding is nonzero and right-padding is 0 - if(lv_obj_get_style_pad_top(ui_SplashScreen_LoadingBar, - LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_SplashScreen_LoadingBar, - lv_obj_get_style_pad_right(ui_SplashScreen_LoadingBar, LV_PART_MAIN) + 1, LV_PART_MAIN); + if (lv_obj_get_style_pad_top(ui_SplashScreen_LoadingBar, + LV_PART_MAIN) > 0) lv_obj_set_style_pad_right(ui_SplashScreen_LoadingBar, + lv_obj_get_style_pad_right(ui_SplashScreen_LoadingBar, LV_PART_MAIN) + 1, LV_PART_MAIN); ui_SplashScreen_StatusText = lv_label_create(ui_Splash); lv_obj_set_width(ui_SplashScreen_StatusText, LV_SIZE_CONTENT); /// 1 lv_obj_set_height(ui_SplashScreen_StatusText, LV_SIZE_CONTENT); /// 1 @@ -123,7 +123,9 @@ void ui_Splash_screen_init(void) void ui_Splash_screen_destroy(void) { - if(ui_Splash) lv_obj_del(ui_Splash); + if (ui_Splash) { + lv_obj_del(ui_Splash); + } // NULL screen variables ui_Splash = NULL; diff --git a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h index e14dc0c..ad1d63a 100644 --- a/main/Application/Tasks/GUI/Export/screens/ui_Splash.h +++ b/main/Application/Tasks/GUI/Export/screens/ui_Splash.h @@ -13,14 +13,14 @@ extern "C" { // SCREEN: ui_Splash extern void ui_Splash_screen_init(void); extern void ui_Splash_screen_destroy(void); -extern void ui_event_Splash(lv_event_t * e); -extern lv_obj_t * ui_Splash; -extern lv_obj_t * ui_SplashScreen_Logo; -extern lv_obj_t * ui_SplashScreen_LogoText; -extern lv_obj_t * ui_SplashScreen_Subtext; -extern lv_obj_t * ui_SplashScreen_LoadingBar; -extern lv_obj_t * ui_SplashScreen_StatusText; -extern lv_obj_t * ui_SplashScreen_FirmwareVersion; +extern void ui_event_Splash(lv_event_t *e); +extern lv_obj_t *ui_Splash; +extern lv_obj_t *ui_SplashScreen_Logo; +extern lv_obj_t *ui_SplashScreen_LogoText; +extern lv_obj_t *ui_SplashScreen_Subtext; +extern lv_obj_t *ui_SplashScreen_LoadingBar; +extern lv_obj_t *ui_SplashScreen_StatusText; +extern lv_obj_t *ui_SplashScreen_FirmwareVersion; // CUSTOM VARIABLES #ifdef __cplusplus diff --git a/main/Application/Tasks/GUI/Export/ui.c b/main/Application/Tasks/GUI/Export/ui.c index 1783e2a..9edf4a3 100644 --- a/main/Application/Tasks/GUI/Export/ui.c +++ b/main/Application/Tasks/GUI/Export/ui.c @@ -9,13 +9,13 @@ ///////////////////// VARIABLES //////////////////// // EVENTS -lv_obj_t * ui____initial_actions0; +lv_obj_t *ui____initial_actions0; // IMAGES AND IMAGE SETS ///////////////////// TEST LVGL SETTINGS //////////////////// #if LV_COLOR_DEPTH != 16 - #error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" +#error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings" #endif ///////////////////// ANIMATIONS //////////////////// @@ -26,9 +26,9 @@ lv_obj_t * ui____initial_actions0; void ui_init(void) { - lv_disp_t * dispp = lv_display_get_default(); - lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), - false, LV_FONT_DEFAULT); + lv_disp_t *dispp = lv_display_get_default(); + lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), + false, LV_FONT_DEFAULT); lv_disp_set_theme(dispp, theme); ui_Splash_screen_init(); ui_Main_screen_init(); diff --git a/main/Application/Tasks/GUI/Export/ui.h b/main/Application/Tasks/GUI/Export/ui.h index b974ddc..c43397a 100644 --- a/main/Application/Tasks/GUI/Export/ui.h +++ b/main/Application/Tasks/GUI/Export/ui.h @@ -28,7 +28,7 @@ extern "C" { // EVENTS -extern lv_obj_t * ui____initial_actions0; +extern lv_obj_t *ui____initial_actions0; // IMAGES AND IMAGE SETS LV_IMG_DECLARE(ui_img_logo_80x44_png); // assets/Logo_80x44.png diff --git a/main/Application/Tasks/GUI/Export/ui_events.cpp b/main/Application/Tasks/GUI/Export/ui_events.cpp index 3e122b7..c7a7491 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.cpp +++ b/main/Application/Tasks/GUI/Export/ui_events.cpp @@ -10,13 +10,16 @@ #include "../UI/ui_Settings.h" #include "../../../application.h" +#include "../guiTask.h" + +static const char *TAG = "ui_events"; /** @brief Callback for the message box timer to close the box after a delay. * @param p_Timer Timer handle (user data is the message box to close) */ -static void MessageBox_on_Close(lv_timer_t * p_Timer) +static void MessageBox_on_Close(lv_timer_t *p_Timer) { - lv_obj_t * Box = (lv_obj_t *)lv_timer_get_user_data(p_Timer); + lv_obj_t *Box = (lv_obj_t *)lv_timer_get_user_data(p_Timer); lv_msgbox_close(Box); } @@ -34,10 +37,10 @@ void ScreenMainLoaded(lv_event_t *e) lv_label_set_text(ui_Image_Main_WiFi, LV_SYMBOL_WIFI); lv_label_set_text(ui_Image_Main_SDCard, LV_SYMBOL_SD_CARD); lv_label_set_text(ui_Label_Menu_Button_Save, LV_SYMBOL_SAVE); + lv_label_set_text(ui_Label_Main_Button_Save, LV_SYMBOL_SAVE); lv_label_set_text(ui_Label_Main_Button_Menu, "\uF0C9"); lv_label_set_text(ui_Label_Main_Button_Info, "\uF129"); lv_label_set_text(ui_Label_Main_Button_ROI, "\uE595"); - lv_label_set_text(ui_Label_Main_Button_WiFi, "\uF1EB"); lv_label_set_text(ui_Label_Main_Thermal_Crosshair, "\uF05B"); lv_label_set_text(ui_Label_Menu_Back, "\uF060"); lv_label_set_text(ui_Label_Info_Back, "\uF060"); @@ -54,19 +57,47 @@ void ButtonMainWiFiClicked(lv_event_t *e) esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_OPEN_WIFI_REQUEST, NULL, 0, 0); } -void ScreenSplashLoaded(lv_event_t * e) +void ScreenSplashLoaded(lv_event_t *e) { ui_settings_build(ui_Container_Menu); } -void ButtonMenuSaveClicked(lv_event_t * e) +void ButtonMenuSaveClicked(lv_event_t *e) { - lv_obj_t * Box = lv_msgbox_create(NULL); + lv_obj_t *Box = lv_msgbox_create(NULL); SettingsManager_Save(); lv_msgbox_add_title(Box, "Settings Saved"); - lv_timer_t * Timer = lv_timer_create(MessageBox_on_Close, 1000, Box); + lv_timer_t *Timer = lv_timer_create(MessageBox_on_Close, 1000, Box); + lv_timer_set_repeat_count(Timer, 1); +} + +void ButtonMainSaveClicked(lv_event_t *e) +{ + lv_obj_t *Box = lv_msgbox_create(NULL); + esp_err_t Error = GUI_SaveThermalImage(); + + if (Error == ESP_OK) { + lv_msgbox_add_title(Box, "Image Saved"); + lv_msgbox_add_text(Box, "Thermal image saved to storage"); + ESP_LOGI(TAG, "Thermal image saved successfully"); + } else if (Error == ESP_ERR_INVALID_STATE) { + lv_msgbox_add_title(Box, "USB Active"); + lv_msgbox_add_text(Box, "Cannot save - USB mode is active!\\nDisable USB first."); + ESP_LOGW(TAG, "Cannot save image - USB mode active"); + } else if (Error == ESP_ERR_NO_MEM) { + lv_msgbox_add_title(Box, "No Frame"); + lv_msgbox_add_text(Box, "No thermal frame available"); + ESP_LOGW(TAG, "No thermal frame available"); + } else { + lv_msgbox_add_title(Box, "Save Failed"); + lv_msgbox_add_text(Box, "Failed to save image"); + ESP_LOGE(TAG, "Failed to save thermal image: %d!", Error); + } + + /* Auto-close message box after 2 seconds */ + lv_timer_t *Timer = lv_timer_create(MessageBox_on_Close, 2000, Box); lv_timer_set_repeat_count(Timer, 1); } diff --git a/main/Application/Tasks/GUI/Export/ui_events.h b/main/Application/Tasks/GUI/Export/ui_events.h index 9458d2b..3a687e9 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.h +++ b/main/Application/Tasks/GUI/Export/ui_events.h @@ -10,11 +10,11 @@ extern "C" { #endif -void ScreenSplashLoaded(lv_event_t * e); -void ScreenMainLoaded(lv_event_t * e); -void ButtonMainWiFiClicked(lv_event_t * e); -void ButtonMenuSaveClicked(lv_event_t * e); -void ScreenInfoLoaded(lv_event_t * e); +void ScreenSplashLoaded(lv_event_t *e); +void ScreenMainLoaded(lv_event_t *e); +void ButtonMainSaveClicked(lv_event_t *e); +void ButtonMenuSaveClicked(lv_event_t *e); +void ScreenInfoLoaded(lv_event_t *e); #ifdef __cplusplus } /*extern "C"*/ diff --git a/main/Application/Tasks/GUI/Export/ui_helpers.c b/main/Application/Tasks/GUI/Export/ui_helpers.c index 7e5ad39..4ac1444 100644 --- a/main/Application/Tasks/GUI/Export/ui_helpers.c +++ b/main/Application/Tasks/GUI/Export/ui_helpers.c @@ -5,131 +5,176 @@ #include "ui_helpers.h" -void _ui_bar_set_property(lv_obj_t * target, int id, int val) +void _ui_bar_set_property(lv_obj_t *target, int id, int val) { - if(id == _UI_BAR_PROPERTY_VALUE_WITH_ANIM) lv_bar_set_value(target, val, LV_ANIM_ON); - if(id == _UI_BAR_PROPERTY_VALUE) lv_bar_set_value(target, val, LV_ANIM_OFF); + if (id == _UI_BAR_PROPERTY_VALUE_WITH_ANIM) { + lv_bar_set_value(target, val, LV_ANIM_ON); + } + if (id == _UI_BAR_PROPERTY_VALUE) { + lv_bar_set_value(target, val, LV_ANIM_OFF); + } } -void _ui_basic_set_property(lv_obj_t * target, int id, int val) +void _ui_basic_set_property(lv_obj_t *target, int id, int val) { - if(id == _UI_BASIC_PROPERTY_POSITION_X) lv_obj_set_x(target, val); - if(id == _UI_BASIC_PROPERTY_POSITION_Y) lv_obj_set_y(target, val); - if(id == _UI_BASIC_PROPERTY_WIDTH) lv_obj_set_width(target, val); - if(id == _UI_BASIC_PROPERTY_HEIGHT) lv_obj_set_height(target, val); + if (id == _UI_BASIC_PROPERTY_POSITION_X) { + lv_obj_set_x(target, val); + } + if (id == _UI_BASIC_PROPERTY_POSITION_Y) { + lv_obj_set_y(target, val); + } + if (id == _UI_BASIC_PROPERTY_WIDTH) { + lv_obj_set_width(target, val); + } + if (id == _UI_BASIC_PROPERTY_HEIGHT) { + lv_obj_set_height(target, val); + } } -void _ui_dropdown_set_property(lv_obj_t * target, int id, int val) +void _ui_dropdown_set_property(lv_obj_t *target, int id, int val) { - if(id == _UI_DROPDOWN_PROPERTY_SELECTED) lv_dropdown_set_selected(target, val); + if (id == _UI_DROPDOWN_PROPERTY_SELECTED) { + lv_dropdown_set_selected(target, val); + } } -void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val) +void _ui_image_set_property(lv_obj_t *target, int id, uint8_t *val) { - if(id == _UI_IMAGE_PROPERTY_IMAGE) lv_image_set_src(target, val); + if (id == _UI_IMAGE_PROPERTY_IMAGE) { + lv_image_set_src(target, val); + } } -void _ui_label_set_property(lv_obj_t * target, int id, const char * val) +void _ui_label_set_property(lv_obj_t *target, int id, const char *val) { - if(id == _UI_LABEL_PROPERTY_TEXT) lv_label_set_text(target, val); + if (id == _UI_LABEL_PROPERTY_TEXT) { + lv_label_set_text(target, val); + } } -void _ui_roller_set_property(lv_obj_t * target, int id, int val) +void _ui_roller_set_property(lv_obj_t *target, int id, int val) { - if(id == _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM) lv_roller_set_selected(target, val, LV_ANIM_ON); - if(id == _UI_ROLLER_PROPERTY_SELECTED) lv_roller_set_selected(target, val, LV_ANIM_OFF); + if (id == _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM) { + lv_roller_set_selected(target, val, LV_ANIM_ON); + } + if (id == _UI_ROLLER_PROPERTY_SELECTED) { + lv_roller_set_selected(target, val, LV_ANIM_OFF); + } } -void _ui_slider_set_property(lv_obj_t * target, int id, int val) +void _ui_slider_set_property(lv_obj_t *target, int id, int val) { - if(id == _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM) lv_slider_set_value(target, val, LV_ANIM_ON); - if(id == _UI_SLIDER_PROPERTY_VALUE) lv_slider_set_value(target, val, LV_ANIM_OFF); + if (id == _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM) { + lv_slider_set_value(target, val, LV_ANIM_ON); + } + if (id == _UI_SLIDER_PROPERTY_VALUE) { + lv_slider_set_value(target, val, LV_ANIM_OFF); + } } -void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, +void _ui_screen_change(lv_obj_t **target, lv_screen_load_anim_t fademode, int spd, int delay, void (*target_init)(void)) { - if(*target == NULL) + if (*target == NULL) { target_init(); + } lv_screen_load_anim(*target, fademode, spd, delay, false); } void _ui_screen_delete(void (*target)(void)) { - if(target != NULL) { + if (target != NULL) { target(); } } -void _ui_arc_increment(lv_obj_t * target, int val) +void _ui_arc_increment(lv_obj_t *target, int val) { int old = lv_arc_get_value(target); lv_arc_set_value(target, old + val); lv_obj_send_event(target, LV_EVENT_VALUE_CHANGED, 0); } -void _ui_bar_increment(lv_obj_t * target, int val, int anm) +void _ui_bar_increment(lv_obj_t *target, int val, int anm) { int old = lv_bar_get_value(target); lv_bar_set_value(target, old + val, anm); } -void _ui_slider_increment(lv_obj_t * target, int val, int anm) +void _ui_slider_increment(lv_obj_t *target, int val, int anm) { int old = lv_slider_get_value(target); lv_slider_set_value(target, old + val, anm); lv_obj_send_event(target, LV_EVENT_VALUE_CHANGED, 0); } -void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea) +void _ui_keyboard_set_target(lv_obj_t *keyboard, lv_obj_t *textarea) { lv_keyboard_set_textarea(keyboard, textarea); } -void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value) +void _ui_flag_modify(lv_obj_t *target, int32_t flag, int value) { - if(value == _UI_MODIFY_FLAG_TOGGLE) { - if(lv_obj_has_flag(target, flag)) lv_obj_remove_flag(target, flag); - else lv_obj_add_flag(target, flag); + if (value == _UI_MODIFY_FLAG_TOGGLE) { + if (lv_obj_has_flag(target, flag)) { + lv_obj_remove_flag(target, flag); + } else { + lv_obj_add_flag(target, flag); + } + } else if (value == _UI_MODIFY_FLAG_ADD) { + lv_obj_add_flag(target, flag); + } else { + lv_obj_remove_flag(target, flag); } - else if(value == _UI_MODIFY_FLAG_ADD) lv_obj_add_flag(target, flag); - else lv_obj_remove_flag(target, flag); } -void _ui_state_modify(lv_obj_t * target, int32_t state, int value) -{ - if(value == _UI_MODIFY_STATE_TOGGLE) { - if(lv_obj_has_state(target, state)) lv_obj_remove_state(target, state); - else lv_obj_add_state(target, state); +void _ui_state_modify(lv_obj_t *target, int32_t state, int value) +{ + if (value == _UI_MODIFY_STATE_TOGGLE) { + if (lv_obj_has_state(target, state)) { + lv_obj_remove_state(target, state); + } else { + lv_obj_add_state(target, state); + } + } else if (value == _UI_MODIFY_STATE_ADD) { + lv_obj_add_state(target, state); + } else { + lv_obj_remove_state(target, state); } - else if(value == _UI_MODIFY_STATE_ADD) lv_obj_add_state(target, state); - else lv_obj_remove_state(target, state); } -void _ui_textarea_move_cursor(lv_obj_t * target, int val) +void _ui_textarea_move_cursor(lv_obj_t *target, int val) { - if(val == UI_MOVE_CURSOR_UP) lv_textarea_cursor_up(target); - if(val == UI_MOVE_CURSOR_RIGHT) lv_textarea_cursor_right(target); - if(val == UI_MOVE_CURSOR_DOWN) lv_textarea_cursor_down(target); - if(val == UI_MOVE_CURSOR_LEFT) lv_textarea_cursor_left(target); + if (val == UI_MOVE_CURSOR_UP) { + lv_textarea_cursor_up(target); + } + if (val == UI_MOVE_CURSOR_RIGHT) { + lv_textarea_cursor_right(target); + } + if (val == UI_MOVE_CURSOR_DOWN) { + lv_textarea_cursor_down(target); + } + if (val == UI_MOVE_CURSOR_LEFT) { + lv_textarea_cursor_left(target); + } lv_obj_add_state(target, LV_STATE_FOCUSED); } typedef void (*screen_destroy_cb_t)(void); -void scr_unloaded_delete_cb(lv_event_t * e) +void scr_unloaded_delete_cb(lv_event_t *e) { // Get the destroy callback from user_data screen_destroy_cb_t destroy_cb = lv_event_get_user_data(e); - if(destroy_cb) { + if (destroy_cb) { destroy_cb(); // call the specific screen destroy function @@ -137,176 +182,180 @@ void scr_unloaded_delete_cb(lv_event_t * e) } -void _ui_opacity_set(lv_obj_t * target, int val) +void _ui_opacity_set(lv_obj_t *target, int val) { lv_obj_set_style_opa(target, val, 0); } -void _ui_anim_callback_free_user_data(lv_anim_t * a) +void _ui_anim_callback_free_user_data(lv_anim_t *a) { lv_free(a->user_data); a->user_data = NULL; } -void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v) +void _ui_anim_callback_set_x(lv_anim_t *a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_x(usr->target, v); } -void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v) +void _ui_anim_callback_set_y(lv_anim_t *a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_y(usr->target, v); } -void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v) +void _ui_anim_callback_set_width(lv_anim_t *a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_width(usr->target, v); } -void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v) +void _ui_anim_callback_set_height(lv_anim_t *a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_height(usr->target, v); } -void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v) +void _ui_anim_callback_set_opacity(lv_anim_t *a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_obj_set_style_opa(usr->target, v, 0); } -void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v) +void _ui_anim_callback_set_image_zoom(lv_anim_t *a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_image_set_scale(usr->target, v); } -void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v) +void _ui_anim_callback_set_image_angle(lv_anim_t *a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; lv_image_set_rotation(usr->target, v); } -void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v) +void _ui_anim_callback_set_image_frame(lv_anim_t *a, int32_t v) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; usr->val = v; - if(v < 0) v = 0; - if(v >= usr->imgset_size) v = usr->imgset_size - 1; + if (v < 0) { + v = 0; + } + if (v >= usr->imgset_size) { + v = usr->imgset_size - 1; + } lv_image_set_src(usr->target, usr->imgset[v]); } -int32_t _ui_anim_callback_get_x(lv_anim_t * a) +int32_t _ui_anim_callback_get_x(lv_anim_t *a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_x_aligned(usr->target); } -int32_t _ui_anim_callback_get_y(lv_anim_t * a) +int32_t _ui_anim_callback_get_y(lv_anim_t *a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_y_aligned(usr->target); } -int32_t _ui_anim_callback_get_width(lv_anim_t * a) +int32_t _ui_anim_callback_get_width(lv_anim_t *a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_width(usr->target); } -int32_t _ui_anim_callback_get_height(lv_anim_t * a) +int32_t _ui_anim_callback_get_height(lv_anim_t *a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_height(usr->target); } -int32_t _ui_anim_callback_get_opacity(lv_anim_t * a) +int32_t _ui_anim_callback_get_opacity(lv_anim_t *a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_obj_get_style_opa(usr->target, 0); } -int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a) +int32_t _ui_anim_callback_get_image_zoom(lv_anim_t *a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_image_get_scale(usr->target); } -int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a) +int32_t _ui_anim_callback_get_image_angle(lv_anim_t *a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return lv_image_get_rotation(usr->target); } -int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a) +int32_t _ui_anim_callback_get_image_frame(lv_anim_t *a) { - ui_anim_user_data_t * usr = (ui_anim_user_data_t *)a->user_data; + ui_anim_user_data_t *usr = (ui_anim_user_data_t *)a->user_data; return usr->val; } -void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix) +void _ui_arc_set_text_value(lv_obj_t *trg, lv_obj_t *src, const char *prefix, const char *postfix) { char buf[_UI_TEMPORARY_STRING_BUFFER_SIZE]; @@ -315,7 +364,7 @@ void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, lv_label_set_text(trg, buf); } -void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix) +void _ui_slider_set_text_value(lv_obj_t *trg, lv_obj_t *src, const char *prefix, const char *postfix) { char buf[_UI_TEMPORARY_STRING_BUFFER_SIZE]; @@ -323,20 +372,27 @@ void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * pref lv_label_set_text(trg, buf); } -void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off) +void _ui_checked_set_text_value(lv_obj_t *trg, lv_obj_t *src, const char *txt_on, const char *txt_off) { - if(lv_obj_has_state(src, LV_STATE_CHECKED)) lv_label_set_text(trg, txt_on); - else lv_label_set_text(trg, txt_off); + if (lv_obj_has_state(src, LV_STATE_CHECKED)) { + lv_label_set_text(trg, txt_on); + } else { + lv_label_set_text(trg, txt_off); + } } -void _ui_spinbox_step(lv_obj_t * target, int val) +void _ui_spinbox_step(lv_obj_t *target, int val) { - if(val > 0) lv_spinbox_increment(target); + if (val > 0) { + lv_spinbox_increment(target); + } - else lv_spinbox_decrement(target); + else { + lv_spinbox_decrement(target); + } lv_obj_send_event(target, LV_EVENT_VALUE_CHANGED, 0); diff --git a/main/Application/Tasks/GUI/Export/ui_helpers.h b/main/Application/Tasks/GUI/Export/ui_helpers.h index cf49380..db4aded 100644 --- a/main/Application/Tasks/GUI/Export/ui_helpers.h +++ b/main/Application/Tasks/GUI/Export/ui_helpers.h @@ -15,125 +15,125 @@ extern "C" { #define _UI_TEMPORARY_STRING_BUFFER_SIZE 32 #define _UI_BAR_PROPERTY_VALUE 0 #define _UI_BAR_PROPERTY_VALUE_WITH_ANIM 1 -void _ui_bar_set_property(lv_obj_t * target, int id, int val); +void _ui_bar_set_property(lv_obj_t *target, int id, int val); #define _UI_BASIC_PROPERTY_POSITION_X 0 #define _UI_BASIC_PROPERTY_POSITION_Y 1 #define _UI_BASIC_PROPERTY_WIDTH 2 #define _UI_BASIC_PROPERTY_HEIGHT 3 -void _ui_basic_set_property(lv_obj_t * target, int id, int val); +void _ui_basic_set_property(lv_obj_t *target, int id, int val); #define _UI_DROPDOWN_PROPERTY_SELECTED 0 -void _ui_dropdown_set_property(lv_obj_t * target, int id, int val); +void _ui_dropdown_set_property(lv_obj_t *target, int id, int val); #define _UI_IMAGE_PROPERTY_IMAGE 0 -void _ui_image_set_property(lv_obj_t * target, int id, uint8_t * val); +void _ui_image_set_property(lv_obj_t *target, int id, uint8_t *val); #define _UI_LABEL_PROPERTY_TEXT 0 -void _ui_label_set_property(lv_obj_t * target, int id, const char * val); +void _ui_label_set_property(lv_obj_t *target, int id, const char *val); #define _UI_ROLLER_PROPERTY_SELECTED 0 #define _UI_ROLLER_PROPERTY_SELECTED_WITH_ANIM 1 -void _ui_roller_set_property(lv_obj_t * target, int id, int val); +void _ui_roller_set_property(lv_obj_t *target, int id, int val); #define _UI_SLIDER_PROPERTY_VALUE 0 #define _UI_SLIDER_PROPERTY_VALUE_WITH_ANIM 1 -void _ui_slider_set_property(lv_obj_t * target, int id, int val); +void _ui_slider_set_property(lv_obj_t *target, int id, int val); -void _ui_screen_change(lv_obj_t ** target, lv_screen_load_anim_t fademode, int spd, int delay, +void _ui_screen_change(lv_obj_t **target, lv_screen_load_anim_t fademode, int spd, int delay, void (*target_init)(void)); void _ui_screen_delete(void (*target)(void)); -void _ui_arc_increment(lv_obj_t * target, int val); +void _ui_arc_increment(lv_obj_t *target, int val); -void _ui_bar_increment(lv_obj_t * target, int val, int anm); +void _ui_bar_increment(lv_obj_t *target, int val, int anm); -void _ui_slider_increment(lv_obj_t * target, int val, int anm); +void _ui_slider_increment(lv_obj_t *target, int val, int anm); -void _ui_keyboard_set_target(lv_obj_t * keyboard, lv_obj_t * textarea); +void _ui_keyboard_set_target(lv_obj_t *keyboard, lv_obj_t *textarea); #define _UI_MODIFY_FLAG_ADD 0 #define _UI_MODIFY_FLAG_REMOVE 1 #define _UI_MODIFY_FLAG_TOGGLE 2 -void _ui_flag_modify(lv_obj_t * target, int32_t flag, int value); +void _ui_flag_modify(lv_obj_t *target, int32_t flag, int value); #define _UI_MODIFY_STATE_ADD 0 #define _UI_MODIFY_STATE_REMOVE 1 #define _UI_MODIFY_STATE_TOGGLE 2 -void _ui_state_modify(lv_obj_t * target, int32_t state, int value); +void _ui_state_modify(lv_obj_t *target, int32_t state, int value); #define UI_MOVE_CURSOR_UP 0 #define UI_MOVE_CURSOR_RIGHT 1 #define UI_MOVE_CURSOR_DOWN 2 #define UI_MOVE_CURSOR_LEFT 3 -void _ui_textarea_move_cursor(lv_obj_t * target, int val) +void _ui_textarea_move_cursor(lv_obj_t *target, int val) ; -void scr_unloaded_delete_cb(lv_event_t * e); +void scr_unloaded_delete_cb(lv_event_t *e); -void _ui_opacity_set(lv_obj_t * target, int val); +void _ui_opacity_set(lv_obj_t *target, int val); /** Describes an animation*/ typedef struct _ui_anim_user_data_t { - lv_obj_t * target; - lv_image_dsc_t ** imgset; + lv_obj_t *target; + lv_image_dsc_t **imgset; int32_t imgset_size; int32_t val; } ui_anim_user_data_t; -void _ui_anim_callback_free_user_data(lv_anim_t * a); +void _ui_anim_callback_free_user_data(lv_anim_t *a); -void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v); +void _ui_anim_callback_set_x(lv_anim_t *a, int32_t v); -void _ui_anim_callback_set_y(lv_anim_t * a, int32_t v); +void _ui_anim_callback_set_y(lv_anim_t *a, int32_t v); -void _ui_anim_callback_set_width(lv_anim_t * a, int32_t v); +void _ui_anim_callback_set_width(lv_anim_t *a, int32_t v); -void _ui_anim_callback_set_height(lv_anim_t * a, int32_t v); +void _ui_anim_callback_set_height(lv_anim_t *a, int32_t v); -void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v); +void _ui_anim_callback_set_opacity(lv_anim_t *a, int32_t v); -void _ui_anim_callback_set_image_zoom(lv_anim_t * a, int32_t v); +void _ui_anim_callback_set_image_zoom(lv_anim_t *a, int32_t v); -void _ui_anim_callback_set_image_angle(lv_anim_t * a, int32_t v); +void _ui_anim_callback_set_image_angle(lv_anim_t *a, int32_t v); -void _ui_anim_callback_set_image_frame(lv_anim_t * a, int32_t v); +void _ui_anim_callback_set_image_frame(lv_anim_t *a, int32_t v); -int32_t _ui_anim_callback_get_x(lv_anim_t * a); +int32_t _ui_anim_callback_get_x(lv_anim_t *a); -int32_t _ui_anim_callback_get_y(lv_anim_t * a); +int32_t _ui_anim_callback_get_y(lv_anim_t *a); -int32_t _ui_anim_callback_get_width(lv_anim_t * a); +int32_t _ui_anim_callback_get_width(lv_anim_t *a); -int32_t _ui_anim_callback_get_height(lv_anim_t * a); +int32_t _ui_anim_callback_get_height(lv_anim_t *a); -int32_t _ui_anim_callback_get_opacity(lv_anim_t * a); +int32_t _ui_anim_callback_get_opacity(lv_anim_t *a); -int32_t _ui_anim_callback_get_image_zoom(lv_anim_t * a); +int32_t _ui_anim_callback_get_image_zoom(lv_anim_t *a); -int32_t _ui_anim_callback_get_image_angle(lv_anim_t * a); +int32_t _ui_anim_callback_get_image_angle(lv_anim_t *a); -int32_t _ui_anim_callback_get_image_frame(lv_anim_t * a); +int32_t _ui_anim_callback_get_image_frame(lv_anim_t *a); -void _ui_arc_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); +void _ui_arc_set_text_value(lv_obj_t *trg, lv_obj_t *src, const char *prefix, const char *postfix); -void _ui_slider_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * prefix, const char * postfix); +void _ui_slider_set_text_value(lv_obj_t *trg, lv_obj_t *src, const char *prefix, const char *postfix); -void _ui_checked_set_text_value(lv_obj_t * trg, lv_obj_t * src, const char * txt_on, const char * txt_off); +void _ui_checked_set_text_value(lv_obj_t *trg, lv_obj_t *src, const char *txt_on, const char *txt_off); -void _ui_spinbox_step(lv_obj_t * target, int val) +void _ui_spinbox_step(lv_obj_t *target, int val) ; diff --git a/main/Application/Tasks/GUI/Private/guiHelper.cpp b/main/Application/Tasks/GUI/Private/guiHelper.cpp index b9d6ee9..c770962 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.cpp +++ b/main/Application/Tasks/GUI/Private/guiHelper.cpp @@ -21,7 +21,6 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ - #include #include @@ -29,14 +28,6 @@ #include "Application/application.h" #include "../Export/ui.h" -#if defined(CONFIG_TOUCH_I2C0_HOST) -#define TOUCH_I2C_HOST I2C_NUM_0 -#elif defined(CONFIG_TOUCH_I2C1_HOST) -#define TOUCH_I2C_HOST I2C_NUM_1 -#else -#error "No I2C host defined for Touch!" -#endif - #if defined(CONFIG_LCD_SPI2_HOST) #define LCD_SPI_HOST SPI2_HOST #elif defined(CONFIG_LCD_SPI3_HOST) @@ -86,20 +77,6 @@ static const esp_lcd_panel_io_spi_config_t _GUI_Panel_IO_Config = { }, }; -static const i2c_master_bus_config_t _GUI_Touch_I2C_Config = { - .i2c_port = TOUCH_I2C_HOST, - .sda_io_num = static_cast(CONFIG_TOUCH_SDA), - .scl_io_num = static_cast(CONFIG_TOUCH_SCL), - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = true, - .allow_pd = false, - }, -}; - static const esp_lcd_panel_io_i2c_config_t _GUI_Touch_IO_Config = { #if((CONFIG_TOUCH_IRQ != -1) && (CONFIG_TOUCH_RST != -1)) .dev_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS, @@ -144,13 +121,18 @@ static const esp_lcd_touch_config_t _GUI_Touch_Config = { .driver_data = &_GUI_Touch_GT911_Config, }; -static const char *TAG = "gui_helper"; +static const char *TAG = "GUI-Helper"; inline void GUI_LVGL_TickTimer_CB(void *p_Arg) { lv_tick_inc(CONFIG_GUI_LVGL_TICK_PERIOD_MS); } +/** @brief Initialize the GUI helper functions. + * @param p_Disp + * @param p_Area + * @param p_PxMap + */ static void GUI_LCD_Flush_CB(lv_display_t *p_Disp, const lv_area_t *p_Area, uint8_t *p_PxMap) { esp_lcd_panel_handle_t panel_handle = static_cast(lv_display_get_user_data(p_Disp)); @@ -165,16 +147,18 @@ static void GUI_LCD_Flush_CB(lv_display_t *p_Disp, const lv_area_t *p_Area, uint lv_display_flush_ready(p_Disp); } -esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t Touch_Read_Callback) +esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUI_Task_State, lv_indev_read_cb_t Touch_Read_Callback) { + esp_err_t Error; + #if (CONFIG_LCD_BL != -1) ESP_LOGI(TAG, "Configure LCD backlight GPIO..."); gpio_config_t bk_gpio_config = { .pin_bit_mask = 1ULL << CONFIG_LCD_BL, - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, }; ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); gpio_set_level(static_cast(CONFIG_LCD_BL), LCD_BK_LIGHT_ON_LEVEL); @@ -182,106 +166,91 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t ESP_LOGI(TAG, "Create I2C bus for touch controller..."); - i2c_new_master_bus(&_GUI_Touch_I2C_Config, &p_GUITask_State->Touch_Bus_Handle); - - // --- I2C-Scanner --- - /* - ESP_LOGI(TAG, "Starte I2C-Scan auf Touch-Bus (driver_ng)..."); - for (uint8_t addr = 1; addr < 127; addr++) { - esp_err_t ret = i2c_master_probe(p_GUITask_State->Touch_Bus_Handle, addr, 10 / portTICK_PERIOD_MS); - if (ret == ESP_OK) { - ESP_LOGW(TAG, "I2C-Gerät gefunden bei Adresse 0x%02X", addr); - } - } - ESP_LOGI(TAG, "I2C-Scan abgeschlossen."); - - while(1) - { - vTaskDelay(1000 / portTICK_PERIOD_MS); - }*/ + p_GUI_Task_State->Touch_Bus_Handle = DevicesManager_GetTouchI2CBusHandle(); ESP_LOGI(TAG, "Create panel IO..."); ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(static_cast(LCD_SPI_HOST), &_GUI_Panel_IO_Config, - &p_GUITask_State->Panel_IO_Handle)); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(p_GUITask_State->Touch_Bus_Handle, &_GUI_Touch_IO_Config, - &p_GUITask_State->Touch_IO_Handle)); + &p_GUI_Task_State->Panel_IO_Handle)); + ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(p_GUI_Task_State->Touch_Bus_Handle, &_GUI_Touch_IO_Config, + &p_GUI_Task_State->Touch_IO_Handle)); ESP_LOGI(TAG, "Initialize LVGL library and display..."); lv_init(); - p_GUITask_State->Display = lv_display_create(CONFIG_GUI_WIDTH, CONFIG_GUI_HEIGHT); + p_GUI_Task_State->Display = lv_display_create(CONFIG_GUI_WIDTH, CONFIG_GUI_HEIGHT); ESP_LOGI(TAG, "Register LCD panel IO callbacks..."); - ESP_ERROR_CHECK(esp_lcd_panel_io_register_event_callbacks(p_GUITask_State->Panel_IO_Handle, &_GUI_Panel_Callbacks, - p_GUITask_State->Display)); + ESP_ERROR_CHECK(esp_lcd_panel_io_register_event_callbacks(p_GUI_Task_State->Panel_IO_Handle, &_GUI_Panel_Callbacks, + p_GUI_Task_State->Display)); - ESP_LOGI(TAG, "Install ILI9341 panel driver..."); - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(p_GUITask_State->Panel_IO_Handle, &_GUI_Panel_Config, - &p_GUITask_State->PanelHandle)); + ESP_LOGI(TAG, "Install ILI9341 panel driver..."); + ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(p_GUI_Task_State->Panel_IO_Handle, &_GUI_Panel_Config, + &p_GUI_Task_State->PanelHandle)); ESP_LOGD(TAG, " ILI9341 panel driver installed"); ESP_LOGD(TAG, "Reset the panel..."); - ESP_ERROR_CHECK(esp_lcd_panel_reset(p_GUITask_State->PanelHandle)); + ESP_ERROR_CHECK(esp_lcd_panel_reset(p_GUI_Task_State->PanelHandle)); vTaskDelay(100 / portTICK_PERIOD_MS); ESP_LOGD(TAG, " Panel reset complete"); ESP_LOGI(TAG, "Initialize the panel..."); - ESP_ERROR_CHECK(esp_lcd_panel_init(p_GUITask_State->PanelHandle)); + ESP_ERROR_CHECK(esp_lcd_panel_init(p_GUI_Task_State->PanelHandle)); vTaskDelay(100 / portTICK_PERIOD_MS); ESP_LOGD(TAG, " Panel initialized"); ESP_LOGI(TAG, "Configure panel for landscape mode..."); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(p_GUITask_State->PanelHandle, true)); + ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(p_GUI_Task_State->PanelHandle, true)); ESP_LOGD(TAG, " Panel swap_xy enabled for landscape"); ESP_LOGI(TAG, "Configure panel mirroring..."); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(p_GUITask_State->PanelHandle, true, true)); + ESP_ERROR_CHECK(esp_lcd_panel_mirror(p_GUI_Task_State->PanelHandle, true, true)); ESP_LOGD(TAG, " Panel mirroring configured (180 degree rotation)"); ESP_LOGI(TAG, "Turn ON the panel display..."); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(p_GUITask_State->PanelHandle, true)); + ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(p_GUI_Task_State->PanelHandle, true)); vTaskDelay(100 / portTICK_PERIOD_MS); ESP_LOGD(TAG, " Panel display turned ON"); /* Set LVGL display properties */ - lv_display_set_flush_cb(p_GUITask_State->Display, GUI_LCD_Flush_CB); - lv_display_set_user_data(p_GUITask_State->Display, - p_GUITask_State->PanelHandle); + lv_display_set_flush_cb(p_GUI_Task_State->Display, GUI_LCD_Flush_CB); + lv_display_set_user_data(p_GUI_Task_State->Display, + p_GUI_Task_State->PanelHandle); /* Note: Color format set to RGB565 by default, matching thermal image BGR565 conversion */ - p_GUITask_State->DisplayBuffer1 = heap_caps_malloc(GUI_DRAW_BUFFER_SIZE, MALLOC_CAP_SPIRAM); - p_GUITask_State->DisplayBuffer2 = heap_caps_malloc(GUI_DRAW_BUFFER_SIZE, MALLOC_CAP_SPIRAM); + p_GUI_Task_State->DisplayBuffer1 = heap_caps_malloc(GUI_DRAW_BUFFER_SIZE, MALLOC_CAP_SPIRAM); + p_GUI_Task_State->DisplayBuffer2 = heap_caps_malloc(GUI_DRAW_BUFFER_SIZE, MALLOC_CAP_SPIRAM); ESP_LOGD(TAG, "Allocated LVGL buffers: %d bytes each in PSRAM", GUI_DRAW_BUFFER_SIZE); - if ((p_GUITask_State->DisplayBuffer1 == NULL) || (p_GUITask_State->DisplayBuffer2 == NULL)) { + if ((p_GUI_Task_State->DisplayBuffer1 == NULL) || (p_GUI_Task_State->DisplayBuffer2 == NULL)) { ESP_LOGE(TAG, "Failed to allocate LVGL draw buffers!"); + return ESP_ERR_NO_MEM; } - lv_display_set_buffers(p_GUITask_State->Display, - p_GUITask_State->DisplayBuffer1, - p_GUITask_State->DisplayBuffer2, + lv_display_set_buffers(p_GUI_Task_State->Display, + p_GUI_Task_State->DisplayBuffer1, + p_GUI_Task_State->DisplayBuffer2, GUI_DRAW_BUFFER_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL); ESP_LOGI(TAG, "Initialize GT911 touch controller..."); - esp_err_t TouchError = esp_lcd_touch_new_i2c_gt911(p_GUITask_State->Touch_IO_Handle, &_GUI_Touch_Config, - &p_GUITask_State->TouchHandle); - if (TouchError != ESP_OK) { - ESP_LOGW(TAG, "GT911 touch controller initialization failed (0x%x)", TouchError); + Error = esp_lcd_touch_new_i2c_gt911(p_GUI_Task_State->Touch_IO_Handle, &_GUI_Touch_Config, + &p_GUI_Task_State->TouchHandle); + if (Error != ESP_OK) { + ESP_LOGW(TAG, "GT911 touch controller initialization failed (0x%x)", Error); ESP_LOGW(TAG, "System will continue without touch functionality"); - p_GUITask_State->TouchHandle = NULL; - p_GUITask_State->Touch = NULL; + + p_GUI_Task_State->TouchHandle = NULL; + p_GUI_Task_State->Touch = NULL; } else { ESP_LOGI(TAG, "GT911 touch controller initialized successfully"); /* Register touchpad input device */ ESP_LOGD(TAG, "Register touch input device to LVGL"); - p_GUITask_State->Touch = lv_indev_create(); - lv_indev_set_type(p_GUITask_State->Touch, LV_INDEV_TYPE_POINTER); - lv_indev_set_display(p_GUITask_State->Touch, p_GUITask_State->Display); - lv_indev_set_read_cb(p_GUITask_State->Touch, Touch_Read_Callback); - lv_indev_set_user_data(p_GUITask_State->Touch, p_GUITask_State->TouchHandle); + p_GUI_Task_State->Touch = lv_indev_create(); + lv_indev_set_type(p_GUI_Task_State->Touch, LV_INDEV_TYPE_POINTER); + lv_indev_set_display(p_GUI_Task_State->Touch, p_GUI_Task_State->Display); + lv_indev_set_read_cb(p_GUI_Task_State->Touch, Touch_Read_Callback); + lv_indev_set_user_data(p_GUI_Task_State->Touch, p_GUI_Task_State->TouchHandle); } - /* Create LVGL tick timer */ const esp_timer_create_args_t LVGL_TickTimer_args = { .callback = &GUI_LVGL_TickTimer_CB, .arg = NULL, @@ -290,100 +259,99 @@ esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t .skip_unhandled_events = false, }; - p_GUITask_State->EventGroup = xEventGroupCreate(); - if (p_GUITask_State->EventGroup == NULL) { + p_GUI_Task_State->EventGroup = xEventGroupCreate(); + if (p_GUI_Task_State->EventGroup == NULL) { ESP_LOGE(TAG, "Failed to create GUI event group!"); + return ESP_ERR_NO_MEM; } - ESP_ERROR_CHECK(esp_timer_create(&LVGL_TickTimer_args, &p_GUITask_State->LVGL_TickTimer)); - ESP_ERROR_CHECK(esp_timer_start_periodic(p_GUITask_State->LVGL_TickTimer, CONFIG_GUI_LVGL_TICK_PERIOD_MS * 1000)); + ESP_ERROR_CHECK(esp_timer_create(&LVGL_TickTimer_args, &p_GUI_Task_State->LVGL_TickTimer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(p_GUI_Task_State->LVGL_TickTimer, CONFIG_GUI_LVGL_TICK_PERIOD_MS * 1000)); /* Create LVGL clock update timer. Use a 100 ms interval for smoother updates */ - p_GUITask_State->UpdateTimer[0] = lv_timer_create(GUI_Helper_Timer_ClockUpdate, 100, NULL); + p_GUI_Task_State->UpdateTimer[0] = lv_timer_create(GUI_Helper_Timer_ClockUpdate, 100, NULL); - p_GUITask_State->UpdateTimer[1] = lv_timer_create(GUI_Helper_Timer_SpotUpdate, 2000, NULL); - p_GUITask_State->UpdateTimer[2] = lv_timer_create(GUI_Helper_Timer_SpotmeterUpdate, 5000, NULL); - p_GUITask_State->UpdateTimer[3] = lv_timer_create(GUI_Helper_Timer_SceneStatisticsUpdate, 5000, NULL); + p_GUI_Task_State->UpdateTimer[1] = lv_timer_create(GUI_Helper_Timer_SpotUpdate, 2000, NULL); + p_GUI_Task_State->UpdateTimer[2] = lv_timer_create(GUI_Helper_Timer_SpotmeterUpdate, 5000, NULL); + p_GUI_Task_State->UpdateTimer[3] = lv_timer_create(GUI_Helper_Timer_SceneStatisticsUpdate, 5000, NULL); - _lock_init(&p_GUITask_State->LVGL_API_Lock); + _lock_init(&p_GUI_Task_State->LVGL_API_Lock); return ESP_OK; } -void GUI_Helper_Deinit(GUI_Task_State_t *p_GUITask_State) +void GUI_Helper_Deinit(GUI_Task_State_t *p_GUI_Task_State) { - if (p_GUITask_State->isInitialized == false) { + if (p_GUI_Task_State->isInitialized == false) { return; } - for (uint32_t i = 0; i < sizeof(p_GUITask_State->UpdateTimer) / sizeof(p_GUITask_State->UpdateTimer[0]); i++) { - if (p_GUITask_State->UpdateTimer[i] != NULL) { - lv_timer_delete(p_GUITask_State->UpdateTimer[i]); - p_GUITask_State->UpdateTimer[i] = NULL; + for (uint32_t i = 0; i < sizeof(p_GUI_Task_State->UpdateTimer) / sizeof(p_GUI_Task_State->UpdateTimer[0]); i++) { + if (p_GUI_Task_State->UpdateTimer[i] != NULL) { + lv_timer_delete(p_GUI_Task_State->UpdateTimer[i]); + p_GUI_Task_State->UpdateTimer[i] = NULL; } } - if (p_GUITask_State->LVGL_TickTimer != NULL) { - esp_timer_stop(p_GUITask_State->LVGL_TickTimer); - esp_timer_delete(p_GUITask_State->LVGL_TickTimer); - p_GUITask_State->LVGL_TickTimer = NULL; + if (p_GUI_Task_State->LVGL_TickTimer != NULL) { + esp_timer_stop(p_GUI_Task_State->LVGL_TickTimer); + esp_timer_delete(p_GUI_Task_State->LVGL_TickTimer); + p_GUI_Task_State->LVGL_TickTimer = NULL; } - if (p_GUITask_State->EventGroup != NULL) { - vEventGroupDelete(p_GUITask_State->EventGroup); - p_GUITask_State->EventGroup = NULL; + if (p_GUI_Task_State->EventGroup != NULL) { + vEventGroupDelete(p_GUI_Task_State->EventGroup); + p_GUI_Task_State->EventGroup = NULL; } - if (p_GUITask_State->Touch != NULL) { - lv_indev_delete(p_GUITask_State->Touch); - p_GUITask_State->Touch = NULL; + if (p_GUI_Task_State->Touch != NULL) { + lv_indev_delete(p_GUI_Task_State->Touch); + p_GUI_Task_State->Touch = NULL; } - esp_lcd_touch_del(p_GUITask_State->TouchHandle); + esp_lcd_touch_del(p_GUI_Task_State->TouchHandle); - if (p_GUITask_State->Display != NULL) { - lv_display_delete(p_GUITask_State->Display); - p_GUITask_State->Display = NULL; + if (p_GUI_Task_State->Display != NULL) { + lv_display_delete(p_GUI_Task_State->Display); + p_GUI_Task_State->Display = NULL; } - if (p_GUITask_State->DisplayBuffer1 != NULL) { - heap_caps_free(p_GUITask_State->DisplayBuffer1); - p_GUITask_State->DisplayBuffer1 = NULL; + if (p_GUI_Task_State->DisplayBuffer1 != NULL) { + heap_caps_free(p_GUI_Task_State->DisplayBuffer1); + p_GUI_Task_State->DisplayBuffer1 = NULL; } - if (p_GUITask_State->DisplayBuffer2 != NULL) { - heap_caps_free(p_GUITask_State->DisplayBuffer2); - p_GUITask_State->DisplayBuffer2 = NULL; + if (p_GUI_Task_State->DisplayBuffer2 != NULL) { + heap_caps_free(p_GUI_Task_State->DisplayBuffer2); + p_GUI_Task_State->DisplayBuffer2 = NULL; } - if (p_GUITask_State->Touch_IO_Handle != NULL) { - esp_lcd_panel_io_del(p_GUITask_State->Touch_IO_Handle); - p_GUITask_State->Touch_IO_Handle = NULL; + if (p_GUI_Task_State->Touch_IO_Handle != NULL) { + esp_lcd_panel_io_del(p_GUI_Task_State->Touch_IO_Handle); + p_GUI_Task_State->Touch_IO_Handle = NULL; } - if (p_GUITask_State->PanelHandle != NULL) { - esp_lcd_panel_del(p_GUITask_State->PanelHandle); - p_GUITask_State->PanelHandle = NULL; + if (p_GUI_Task_State->PanelHandle != NULL) { + esp_lcd_panel_del(p_GUI_Task_State->PanelHandle); + p_GUI_Task_State->PanelHandle = NULL; } - _lock_close(&p_GUITask_State->LVGL_API_Lock); + _lock_close(&p_GUI_Task_State->LVGL_API_Lock); } void GUI_Helper_Timer_ClockUpdate(lv_timer_t *p_Timer) { - char buf[9]; - struct tm time_now; + char Buffer[9]; + struct tm Now; - /* Get current time from TimeManager */ - TimeManager_GetTime(&time_now, NULL); + TimeManager_GetTime(&Now, NULL); - snprintf(buf, sizeof(buf), "%02d:%02d:%02d", time_now.tm_hour, time_now.tm_min, time_now.tm_sec); - lv_label_set_text(ui_Label_Main_Time, buf); + snprintf(Buffer, sizeof(Buffer), "%02d:%02d:%02d", Now.tm_hour, Now.tm_min, Now.tm_sec); + lv_label_set_text(ui_Label_Main_Time, Buffer); - /* Broadcast telemetry to WebSocket clients if server is running */ - if (Server_isRunning()) { - WebSocket_Handler_BroadcastTelemetry(); + if (Server_IsRunning()) { + WebSocket_BroadcastTelemetry(); } } diff --git a/main/Application/Tasks/GUI/Private/guiHelper.h b/main/Application/Tasks/GUI/Private/guiHelper.h index a0357e1..33bf5ae 100644 --- a/main/Application/Tasks/GUI/Private/guiHelper.h +++ b/main/Application/Tasks/GUI/Private/guiHelper.h @@ -62,6 +62,7 @@ typedef struct { bool ProvisioningActive; bool CardPresent; TaskHandle_t TaskHandle; + TaskHandle_t ImageSaveTaskHandle; void *DisplayBuffer1; void *DisplayBuffer2; i2c_master_bus_handle_t Touch_Bus_Handle; @@ -80,16 +81,17 @@ typedef struct { App_Lepton_ROI_Result_t ROIResult; App_Lepton_Device_t LeptonDeviceInfo; App_Lepton_Temperatures_t LeptonTemperatures; + App_Context_t *AppContext; Network_IP_Info_t IP_Info; EventGroupHandle_t EventGroup; uint8_t *ThermalCanvasBuffer; uint8_t *GradientCanvasBuffer; - uint8_t *NetworkRGBBuffer; /* RGB888 buffer for network streaming (240x180x3) */ + uint8_t *NetworkRGBBuffer; uint32_t LeptonUptime; float SpotTemperature; - - /* Network frame for server streaming */ + QueueHandle_t ImageSaveQueue; Network_Thermal_Frame_t NetworkFrame; + bool SaveNextFrameRequested; #ifdef CONFIG_GUI_TOUCH_DEBUG /* Touch debug visualization */ @@ -100,15 +102,15 @@ typedef struct { } GUI_Task_State_t; /** @brief Initialize the GUI helper functions. - * @param p_GUITask_State Pointer to the GUI task state structure. + * @param p_GUI_Task_State Pointer to the GUI task state structure. * @param Touch_Read_Callback LVGL touch read callback function. */ -esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUITask_State, lv_indev_read_cb_t Touch_Read_Callback); +esp_err_t GUI_Helper_Init(GUI_Task_State_t *p_GUI_Task_State, lv_indev_read_cb_t Touch_Read_Callback); /** @brief Deinitialize the GUI helper functions. - * @param p_GUITask_State Pointer to the GUI task state structure. + * @param p_GUI_Task_State Pointer to the GUI task state structure. */ -void GUI_Helper_Deinit(GUI_Task_State_t *p_GUITask_State); +void GUI_Helper_Deinit(GUI_Task_State_t *p_GUI_Task_State); /** @brief LVGL timer callback to update the clock display. * @param p_Timer Pointer to the LVGL timer structure. diff --git a/main/Application/Tasks/GUI/Private/guiImageSave.cpp b/main/Application/Tasks/GUI/Private/guiImageSave.cpp new file mode 100644 index 0000000..3673d08 --- /dev/null +++ b/main/Application/Tasks/GUI/Private/guiImageSave.cpp @@ -0,0 +1,171 @@ +/* + * guiImageSave.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: GUI task image save implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include + +#include +#include +#include +#include + +#include "guiImageSave.h" +#include "Application/application.h" +#include "Application/Manager/Memory/memoryManager.h" + +extern GUI_Task_State_t _GUI_Task_State; + +static const char *TAG = "GUI-ImgSave"; + +void Task_ImageSave(void *p_Param) +{ + App_Lepton_FrameReady_t Frame; + char FilePath[128]; + + ESP_LOGI(TAG, "Image save task started"); + + while (true) { + if (xQueueReceive(_GUI_Task_State.ImageSaveQueue, &Frame, portMAX_DELAY) != pdTRUE) { + continue; + } + + /* Check if filesystem is locked (USB active) */ + if (MemoryManager_IsFilesystemLocked()) { + ESP_LOGW(TAG, "Cannot save image - USB mode active!"); + + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + + continue; + } + + /* Validate frame data */ + if ((Frame.Buffer == NULL) || (Frame.Width == 0) || (Frame.Height == 0)) { + ESP_LOGE(TAG, "Invalid frame data!"); + + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + + continue; + } + + const char *p_StoragePath = MemoryManager_GetStoragePath(); + static uint32_t ImageCounter = 0; + snprintf(FilePath, sizeof(FilePath), "%s/IMG_%03u.PNG", p_StoragePath, (unsigned int)(ImageCounter % 1000)); + ImageCounter++; + + ESP_LOGI(TAG, "Saving PNG: %s (%dx%d)", FilePath, Frame.Width, Frame.Height); + + /* Open file for writing PNG */ + FILE *PNGFile = fopen(FilePath, "wb"); + if (PNGFile == NULL) { + ESP_LOGE(TAG, "Failed to open file for writing: %s", FilePath); + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; + } + + /* Initialize PNG structures */ + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + ESP_LOGE(TAG, "Failed to create PNG write struct!"); + fclose(PNGFile); + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + ESP_LOGE(TAG, "Failed to create PNG info struct!"); + png_destroy_write_struct(&png_ptr, NULL); + fclose(PNGFile); + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; + } + + /* Allocate line buffer before setjmp (to avoid crossing initialization) */ + uint8_t *LineBuffer = static_cast(heap_caps_malloc(Frame.Width * 3, MALLOC_CAP_SPIRAM)); + if (LineBuffer == NULL) { + ESP_LOGE(TAG, "Failed to allocate line buffer!"); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(PNGFile); + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; + } + + /* Set error handling */ + if (setjmp(png_jmpbuf(png_ptr))) { + ESP_LOGE(TAG, "PNG encoding error!"); + heap_caps_free(LineBuffer); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(PNGFile); + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; + } + + /* Set up PNG output */ + png_init_io(png_ptr, PNGFile); + + /* Set PNG image parameters */ + png_set_IHDR(png_ptr, info_ptr, Frame.Width, Frame.Height, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + /* Write PNG header */ + png_write_info(png_ptr, info_ptr); + + /* Write image data row by row */ + for (uint32_t y = 0; y < Frame.Height; y++) { + for (uint32_t x = 0; x < Frame.Width; x++) { + uint32_t idx = (y * Frame.Width + x) * 2; /* RGB565 = 2 bytes per pixel */ + uint16_t rgb565 = Frame.Buffer[idx] | (Frame.Buffer[idx + 1] << 8); + + /* Convert RGB565 to RGB888 */ + uint8_t r = ((rgb565 >> 11) & 0x1F) << 3; + uint8_t g = ((rgb565 >> 5) & 0x3F) << 2; + uint8_t b = (rgb565 & 0x1F) << 3; + + /* PNG uses RGB format */ + LineBuffer[x * 3 + 0] = r; + LineBuffer[x * 3 + 1] = g; + LineBuffer[x * 3 + 2] = b; + } + + png_write_row(png_ptr, LineBuffer); + } + + /* Finish writing PNG */ + png_write_end(png_ptr, NULL); + + heap_caps_free(LineBuffer); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(PNGFile); + + /* Get file size for logging */ + struct stat FileStat; + if (stat(FilePath, &FileStat) == 0) { + ESP_LOGI(TAG, "PNG image saved: %s (%u bytes)", FilePath, (uint32_t)FileStat.st_size); + } else { + ESP_LOGI(TAG, "PNG image saved: %s", FilePath); + } + + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVED, NULL, 0, portMAX_DELAY); + } +} diff --git a/main/Application/Manager/Devices/devices.h b/main/Application/Tasks/GUI/Private/guiImageSave.h similarity index 67% rename from main/Application/Manager/Devices/devices.h rename to main/Application/Tasks/GUI/Private/guiImageSave.h index 41cff11..e513020 100644 --- a/main/Application/Manager/Devices/devices.h +++ b/main/Application/Tasks/GUI/Private/guiImageSave.h @@ -1,9 +1,9 @@ /* - * devices.h + * guiImageSave.h * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Device hardware abstraction layer includes. + * File info: GUI task image save implementation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +21,17 @@ * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de */ -#ifndef DEVICES_H_ -#define DEVICES_H_ +#ifndef GUI_IMAGE_SAVE_H_ +#define GUI_IMAGE_SAVE_H_ -#include "ADC/adc.h" -#include "RTC/rtc.h" -#include "PortExpander/portexpander.h" +#include +#include -#endif /* DEVICES_H_ */ \ No newline at end of file +#include "guiHelper.h" + +/** @brief Image save task. Runs in background to avoid blocking GUI. + * @param p_Param Task parameters (unused) + */ +void Task_ImageSave(void *p_Param); + +#endif /* GUI_IMAGE_SAVE_H_ */ diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp index e6d42a4..9f6dd8f 100644 --- a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp +++ b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp @@ -29,11 +29,12 @@ static const char *TAG = "ui_Settings_Events"; -void on_Lepton_Emissivity_Slider_Callback(lv_event_t * e) { +void on_Lepton_Emissivity_Slider_Callback(lv_event_t *e) +{ int Value; App_Settings_Lepton_t LeptonSettings; - lv_obj_t * slider = static_cast(lv_event_get_target(e)); - Slider_Widgets_t * widgets = static_cast(lv_obj_get_user_data(slider)); + lv_obj_t *slider = static_cast(lv_event_get_target(e)); + Slider_Widgets_t *widgets = static_cast(lv_obj_get_user_data(slider)); SettingsManager_GetLepton(&LeptonSettings); @@ -41,7 +42,7 @@ void on_Lepton_Emissivity_Slider_Callback(lv_event_t * e) { lv_label_set_text_fmt(widgets->Label, "%d", Value); /* Save on release only */ - if(lv_event_get_code(e) == LV_EVENT_RELEASED) { + if (lv_event_get_code(e) == LV_EVENT_RELEASED) { SettingsManager_Setting_t Setting; Setting.ID = SETTINGS_ID_LEPTON_EMISSIVITY; @@ -51,11 +52,12 @@ void on_Lepton_Emissivity_Slider_Callback(lv_event_t * e) { } } -void on_Display_Brightness_Slider_Callback(lv_event_t * e) { +void on_Display_Brightness_Slider_Callback(lv_event_t *e) +{ int Value; App_Settings_Display_t DisplaySettings; - lv_obj_t * slider = static_cast(lv_event_get_target(e)); - Slider_Widgets_t * widgets = static_cast(lv_obj_get_user_data(slider)); + lv_obj_t *slider = static_cast(lv_event_get_target(e)); + Slider_Widgets_t *widgets = static_cast(lv_obj_get_user_data(slider)); SettingsManager_GetDisplay(&DisplaySettings); @@ -63,17 +65,18 @@ void on_Display_Brightness_Slider_Callback(lv_event_t * e) { lv_label_set_text_fmt(widgets->Label, "%d", Value); /* Save on release only */ - if(lv_event_get_code(e) == LV_EVENT_RELEASED) { + if (lv_event_get_code(e) == LV_EVENT_RELEASED) { DisplaySettings.Brightness = static_cast(Value); SettingsManager_UpdateDisplay(&DisplaySettings); } } -void on_Lepton_Dropdown_Callback(lv_event_t * e) { +void on_Lepton_Dropdown_Callback(lv_event_t *e) +{ int Value; App_Settings_Lepton_t LeptonSettings; - lv_obj_t * dropdown = static_cast(lv_event_get_target(e)); - Slider_Widgets_t * widgets = static_cast(lv_obj_get_user_data(dropdown)); + lv_obj_t *dropdown = static_cast(lv_event_get_target(e)); + Slider_Widgets_t *widgets = static_cast(lv_obj_get_user_data(dropdown)); SettingsManager_GetLepton(&LeptonSettings); @@ -89,13 +92,14 @@ void on_Lepton_Dropdown_Callback(lv_event_t * e) { SettingsManager_UpdateLepton(&LeptonSettings, &Setting); } -void on_WiFi_Autoconnect_Callback(lv_event_t * e) { +void on_WiFi_Autoconnect_Callback(lv_event_t *e) +{ App_Settings_WiFi_t WiFiSettings; - lv_obj_t * switch_obj = static_cast(lv_event_get_target(e)); + lv_obj_t *switch_obj = static_cast(lv_event_get_target(e)); SettingsManager_GetWiFi(&WiFiSettings); - if(lv_obj_has_state(switch_obj, LV_STATE_CHECKED)) { + if (lv_obj_has_state(switch_obj, LV_STATE_CHECKED)) { WiFiSettings.AutoConnect = true; ESP_LOGI(TAG, "WiFi autoconnect enabled"); } else { @@ -106,6 +110,12 @@ void on_WiFi_Autoconnect_Callback(lv_event_t * e) { SettingsManager_UpdateWiFi(&WiFiSettings); } +void on_WiFi_Connect_Callback(lv_event_t *e) +{ + ESP_LOGI(TAG, "WiFi connect button clicked, posting network event..."); + esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_OPEN_WIFI_REQUEST, NULL, 0, 0); +} + void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) { ESP_LOGD(TAG, "Network event received: ID=%d", ID); @@ -128,16 +138,21 @@ void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32 switch (ID) { case SETTINGS_EVENT_LEPTON_CHANGED: { - SettingsManager_Setting_t NewSetting; + /* Check if specific setting information is provided */ + if (p_Data != NULL) { + SettingsManager_Setting_t NewSetting; - memcpy(&NewSetting, p_Data, sizeof(SettingsManager_Setting_t)); + memcpy(&NewSetting, p_Data, sizeof(SettingsManager_Setting_t)); - ESP_LOGD(TAG, "Lepton settings changed: ID=%d", NewSetting.ID); - ESP_LOGD(TAG, "Lepton settings changed: Value=%d", NewSetting.Value); + ESP_LOGD(TAG, "Lepton settings changed: ID=%d", NewSetting.ID); + ESP_LOGD(TAG, "Lepton settings changed: Value=%d", NewSetting.Value); - if(NewSetting.ID == SETTINGS_ID_LEPTON_EMISSIVITY) { - lv_slider_set_value(emissivity_widgets.Slider, NewSetting.Value, LV_ANIM_ON); - lv_label_set_text_fmt(emissivity_widgets.Label, "%d", static_cast(NewSetting.Value)); + if (NewSetting.ID == SETTINGS_ID_LEPTON_EMISSIVITY) { + lv_slider_set_value(emissivity_widgets.Slider, NewSetting.Value, LV_ANIM_ON); + lv_label_set_text_fmt(emissivity_widgets.Label, "%d", static_cast(NewSetting.Value)); + } + } else { + ESP_LOGD(TAG, "Lepton settings changed (no specific setting data provided)"); } break; @@ -148,4 +163,118 @@ void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32 break; } } -} \ No newline at end of file +} + +void on_USB_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "USB event received: ID=%d", ID); + + switch (ID) { + case USB_EVENT_INITIALIZED: { + lv_obj_add_state(usb_mode_switch, LV_STATE_CHECKED); + + break; + } + case USB_EVENT_UNINITIALIZED: { + lv_obj_clear_state(usb_mode_switch, LV_STATE_CHECKED); + + break; + } + } +} + +void on_Flash_ClearNVS_Callback(lv_event_t *e) +{ + esp_err_t Error; + + ESP_LOGI(TAG, "Resetting settings to factory defaults..."); + + Error = SettingsManager_ResetToDefaults(); + if (Error == ESP_OK) { + ESP_LOGI(TAG, "Settings reset successfully, restarting..."); + vTaskDelay(500 / portTICK_PERIOD_MS); + esp_restart(); + } else { + ESP_LOGE(TAG, "Failed to reset settings: %d!", Error); + } +} + +void on_Flash_ClearStorage_Callback(lv_event_t *e) +{ + esp_err_t Error; + + ESP_LOGI(TAG, "Erasing storage partition..."); + + Error = MemoryManager_EraseStorage(); + if (Error == ESP_OK) { + ESP_LOGI(TAG, "Storage partition erased successfully"); + ui_settings_update_flash_usage(); + } else { + ESP_LOGE(TAG, "Failed to erase storage partition: %d!", Error); + } +} + +void on_Flash_ClearCoredump_Callback(lv_event_t *e) +{ + esp_err_t Error; + + ESP_LOGI(TAG, "Erasing coredump partition..."); + + Error = MemoryManager_EraseCoredump(); + if (Error == ESP_OK) { + ESP_LOGI(TAG, "Coredump partition erased successfully"); + ui_settings_update_flash_usage(); + } else { + ESP_LOGE(TAG, "Failed to erase coredump partition: %d!", Error); + } +} + +void on_USB_Mode_Switch_Callback(lv_event_t *e) +{ + esp_err_t Error; + lv_obj_t *switch_obj = static_cast(lv_event_get_target(e)); + + if (lv_obj_has_state(switch_obj, LV_STATE_CHECKED)) { + App_Settings_Info_t InfoSettings; + + ESP_LOGI(TAG, "Enabling USB Mass Storage..."); + + if (USBManager_IsInitialized()) { + ESP_LOGW(TAG, "USB already active!"); + + return; + } + + SettingsManager_GetInfo(&InfoSettings); + + /* Configure USB Mass Storage with auto-detected mount point */ + USB_Manager_Config_t USB_Config = { + .MountPoint = MemoryManager_GetStoragePath(), + .Manufacturer = InfoSettings.Manufacturer, + .Product = InfoSettings.Name, + .SerialNumber = InfoSettings.Serial, + }; + + Error = USBManager_Init(&USB_Config); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize USB Manager: %d", Error); + + lv_obj_clear_state(switch_obj, LV_STATE_CHECKED); + } else { + ESP_LOGI(TAG, "\u2713 USB Mass Storage Device active!"); + ESP_LOGW(TAG, "\u26a0\ufe0f Application CANNOT write to /storage while USB is active!"); + } + } else { + ESP_LOGI(TAG, "Disabling USB Mass Storage..."); + + if (USBManager_IsInitialized() == false) { + ESP_LOGW(TAG, "USB not active!"); + + lv_obj_clear_state(switch_obj, LV_STATE_CHECKED); + + return; + } + + USBManager_Deinit(); + } +} diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h index 39065f5..e4cd9ae 100644 --- a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h +++ b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h @@ -28,42 +28,75 @@ #include -/** @brief +/** @brief Forward declaration for memory usage update function. + * Implemented in ui_Settings.cpp to update storage and + * coredump partition usage displays. + */ +void ui_settings_update_flash_usage(void); + +/** @brief */ typedef struct { - lv_obj_t * Slider; - lv_obj_t * Label; + lv_obj_t *Slider; + lv_obj_t *Label; } Slider_Widgets_t; -/** @brief +/** @brief */ typedef struct { - lv_obj_t * Container; - lv_obj_t * Page; + lv_obj_t *Container; + lv_obj_t *Page; } Menu_Page_Result_t; extern Slider_Widgets_t brightness_widgets; extern Slider_Widgets_t emissivity_widgets; +extern lv_obj_t *usb_mode_switch; + /** @brief Display brightness slider event callback to update value label. * @param e Pointer to the event object */ -void on_Lepton_Emissivity_Slider_Callback(lv_event_t * e); +void on_Lepton_Emissivity_Slider_Callback(lv_event_t *e); /** @brief Display brightness slider event callback to update value label. * @param e Pointer to the event object */ -void on_Display_Brightness_Slider_Callback(lv_event_t * e); +void on_Display_Brightness_Slider_Callback(lv_event_t *e); /** @brief Dropdown event callback to update slider and label with selected emissivity preset value. * @param e Pointer to the event object */ -void on_Lepton_Dropdown_Callback(lv_event_t * e); +void on_Lepton_Dropdown_Callback(lv_event_t *e); /** @brief Switch event callback to toggle WiFi autoconnect setting. * @param e Pointer to the event object */ -void on_WiFi_Autoconnect_Callback(lv_event_t * e); +void on_WiFi_Autoconnect_Callback(lv_event_t *e); + +/** @brief WiFi connect button callback to open WiFi connection dialog. + * @param e Pointer to the event object + */ +void on_WiFi_Connect_Callback(lv_event_t *e); + +/** @brief Flash clear NVS button callback to reset all settings to factory defaults. + * @param e Pointer to the event object + */ +void on_Flash_ClearNVS_Callback(lv_event_t *e); + +/** @brief Flash clear storage button callback to erase storage partition. + * @param e Pointer to the event object + */ +void on_Flash_ClearStorage_Callback(lv_event_t *e); + +/** @brief Flash clear coredump button callback to erase coredump partition. + * @param e Pointer to the event object + */ +void on_Flash_ClearCoredump_Callback(lv_event_t *e); + +/** @brief USB mode switch callback to enable/disable USB Mass Storage. + * @param e Pointer to the event object + */ +void on_USB_Mode_Switch_Callback(lv_event_t *e); /** @brief Network event handler which is used to handle network-related events such as WiFi connection changes. * This can be used to update the UI or internal state based on network events. @@ -84,4 +117,14 @@ void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_ */ void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data); +/** @brief USB event handler which is used to update the UI elements when a + * USB change event is received from the USB Manager. + * This ensures that the UI always reflects the current settings values. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +void on_USB_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data); + #endif /* UI_SETTINGS_EVENTS_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/UI/ui_Settings.cpp b/main/Application/Tasks/GUI/UI/ui_Settings.cpp index 690f6ff..99b6858 100644 --- a/main/Application/Tasks/GUI/UI/ui_Settings.cpp +++ b/main/Application/Tasks/GUI/UI/ui_Settings.cpp @@ -27,31 +27,42 @@ #include #include "../Export/ui.h" +#include "../Export/screens/ui_Menu.h" #include "ui_Settings.h" #include "Private/ui_Settings_Events.h" #include "../../../Manager/Settings/settingsManager.h" +#include "../../../Manager/Memory/memoryManager.h" #include "../../../Manager/Network/Server/server.h" +#include "../../../Manager/USB/usbManager.h" Slider_Widgets_t brightness_widgets; Slider_Widgets_t emissivity_widgets; -lv_obj_t * root_page; -lv_obj_t * menu; -lv_obj_t * cont; -lv_obj_t * section; -lv_obj_t * about_Page; -lv_obj_t * wifi_Page; -lv_obj_t * display_Page; -lv_obj_t * lepton_Page; -lv_obj_t * flash_Page; -lv_obj_t * settings_Menu; -lv_obj_t * emissivity_Dropdown; -lv_obj_t * wifi_status_label; - -static lv_obj_t * create_menu_container(lv_obj_t * parent) { - lv_obj_t * container = lv_obj_create(parent); +static lv_obj_t *flash_storage_used_label = NULL; +static lv_obj_t *flash_storage_free_label = NULL; +static lv_obj_t *flash_coredump_used_label = NULL; +static lv_obj_t *flash_coredump_total_label = NULL; + +lv_obj_t *root_page; +lv_obj_t *cont; +lv_obj_t *section; +lv_obj_t *about_Page; +lv_obj_t *wifi_Page; +lv_obj_t *display_Page; +lv_obj_t *lepton_Page; +lv_obj_t *flash_Page; +lv_obj_t *usb_Page; +lv_obj_t *settings_Menu; +lv_obj_t *emissivity_Dropdown; +lv_obj_t *wifi_status_label; +lv_obj_t *usb_mode_switch; + +static lv_obj_t *create_menu_container(lv_obj_t *parent) +{ + lv_obj_t *container = lv_obj_create(parent); lv_obj_clear_flag(container, LV_OBJ_FLAG_CLICKABLE); + lv_obj_clear_flag(container, LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_size(container, LV_PCT(100), LV_SIZE_CONTENT); lv_obj_set_style_pad_all(container, 8, 0); lv_obj_set_style_bg_color(container, lv_color_hex(0x2A2A2A), 0); @@ -64,8 +75,9 @@ static lv_obj_t * create_menu_container(lv_obj_t * parent) { return container; } -static lv_obj_t * create_row(lv_obj_t * parent, lv_flex_align_t main_align) { - lv_obj_t * row = lv_obj_create(parent); +static lv_obj_t *create_row(lv_obj_t *parent, lv_flex_align_t main_align) +{ + lv_obj_t *row = lv_obj_create(parent); lv_obj_clear_flag(row, static_cast(LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_GESTURE_BUBBLE)); lv_obj_set_size(row, LV_PCT(100), 28); lv_obj_set_style_border_width(row, 0, 0); @@ -80,22 +92,23 @@ static lv_obj_t * create_row(lv_obj_t * parent, lv_flex_align_t main_align) { return row; } -static lv_obj_t* create_compact_slider(lv_obj_t * parent, const char * label_text, - int min_val, int max_val, int init_val, Slider_Widgets_t *widgets) { +static lv_obj_t *create_compact_slider(lv_obj_t *parent, const char *label_text, + int min_val, int max_val, int init_val, Slider_Widgets_t *widgets) +{ char Buffer[8]; - if(widgets == NULL) { + if (widgets == NULL) { return NULL; } - lv_obj_t * label_row = create_row(parent, LV_FLEX_ALIGN_START); - lv_obj_t * label = lv_label_create(label_row); + lv_obj_t *label_row = create_row(parent, LV_FLEX_ALIGN_START); + lv_obj_t *label = lv_label_create(label_row); lv_label_set_text(label, label_text); lv_obj_set_width(label, LV_PCT(50)); lv_obj_set_style_text_color(label, lv_color_white(), 0); snprintf(Buffer, sizeof(Buffer), "%i", init_val); - lv_obj_t * value_label = lv_label_create(label_row); + lv_obj_t *value_label = lv_label_create(label_row); lv_label_set_text(value_label, Buffer); lv_label_set_long_mode(value_label, LV_LABEL_LONG_CLIP); lv_obj_set_width(value_label, 40); @@ -109,8 +122,8 @@ static lv_obj_t* create_compact_slider(lv_obj_t * parent, const char * label_tex lv_obj_clear_flag(value_label, LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_style_margin_left(value_label, 10, 0); - lv_obj_t * slider_row = create_row(parent, LV_FLEX_ALIGN_CENTER); - lv_obj_t * slider = lv_slider_create(slider_row); + lv_obj_t *slider_row = create_row(parent, LV_FLEX_ALIGN_CENTER); + lv_obj_t *slider = lv_slider_create(slider_row); lv_obj_clear_flag(slider, LV_OBJ_FLAG_GESTURE_BUBBLE); widgets->Slider = slider; @@ -127,66 +140,69 @@ static lv_obj_t* create_compact_slider(lv_obj_t * parent, const char * label_tex return slider; } -static Menu_Page_Result_t create_menu_page_with_container(lv_obj_t * menu) { - lv_obj_t * page = lv_menu_page_create(menu, NULL); - lv_obj_t * section = lv_menu_section_create(page); - lv_obj_t * container = create_menu_container(section); +static Menu_Page_Result_t create_menu_page_with_container(lv_obj_t *menu) +{ + lv_obj_t *page = lv_menu_page_create(menu, NULL); + lv_obj_t *section = lv_menu_section_create(page); + lv_obj_t *container = create_menu_container(section); lv_obj_set_scrollbar_mode(menu, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_scrollbar_mode(page, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_scrollbar_mode(section, LV_SCROLLBAR_MODE_OFF); - - lv_obj_remove_flag(page, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_remove_flag(section, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_scrollbar_mode(page, LV_SCROLLBAR_MODE_AUTO); + lv_obj_add_flag(page, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_scroll_dir(page, LV_DIR_VER); lv_obj_set_style_pad_all(page, 0, 0); - lv_obj_set_style_pad_all(section, 0, 0); lv_obj_set_style_border_width(page, 0, 0); - lv_obj_set_style_border_width(section, 0, 0); - + lv_obj_set_style_bg_color(page, lv_color_hex(0x1E1E1E), 0); lv_obj_set_style_bg_opa(page, 0, 0); + + lv_obj_set_scrollbar_mode(section, LV_SCROLLBAR_MODE_AUTO); + lv_obj_add_flag(section, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_scroll_dir(section, LV_DIR_VER); + lv_obj_set_style_pad_all(section, 0, 0); + lv_obj_set_style_border_width(section, 0, 0); + lv_obj_set_style_bg_color(section, lv_color_hex(0x1E1E1E), 0); lv_obj_set_style_bg_opa(section, 0, 0); + lv_obj_set_style_pad_right(section, 8, LV_PART_SCROLLBAR); return {container, page}; } -static lv_obj_t * create_text(lv_obj_t * parent, const char * txt) { - lv_obj_t * obj = lv_menu_cont_create(parent); +static lv_obj_t *create_text(lv_obj_t *parent, const char *txt) +{ + lv_obj_t *label = NULL; + + lv_obj_t *obj = lv_menu_cont_create(parent); lv_obj_set_style_bg_color(obj, lv_color_hex(0x3A3A3A), LV_STATE_DEFAULT); lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_PRESSED); - lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUSED); + lv_obj_set_style_bg_color(obj, lv_color_hex(0x3A3A3A), LV_STATE_FOCUSED); lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_CHECKED); lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_EDITED); - lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUS_KEY); + lv_obj_set_style_bg_color(obj, lv_color_hex(0x3A3A3A), LV_STATE_FOCUS_KEY); lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF9500), LV_STATE_PRESSED | LV_STATE_CHECKED); lv_obj_set_style_bg_opa(obj, 255, 0); lv_obj_set_style_radius(obj, 6, 0); lv_obj_set_style_pad_all(obj, 10, 0); lv_obj_set_style_margin_bottom(obj, 4, 0); - lv_obj_set_style_border_width(obj, 15, LV_STATE_FOCUSED); - lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUSED); + lv_obj_set_style_border_width(obj, 0, LV_STATE_FOCUSED); lv_obj_set_style_border_width(obj, 15, LV_STATE_CHECKED); lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_CHECKED); lv_obj_set_style_border_width(obj, 15, LV_STATE_PRESSED); lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_PRESSED); lv_obj_set_style_border_width(obj, 15, LV_STATE_EDITED); lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_EDITED); - lv_obj_set_style_border_width(obj, 15, LV_STATE_FOCUS_KEY); - lv_obj_set_style_border_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUS_KEY); - lv_obj_set_style_shadow_width(obj, 15, LV_STATE_FOCUSED); - lv_obj_set_style_shadow_color(obj, lv_color_hex(0xFF9500), LV_STATE_FOCUSED); + lv_obj_set_style_border_width(obj, 0, LV_STATE_FOCUS_KEY); + lv_obj_set_style_shadow_width(obj, 0, LV_STATE_FOCUSED); lv_obj_set_style_shadow_width(obj, 15, LV_STATE_CHECKED); lv_obj_set_style_shadow_color(obj, lv_color_hex(0xFF9500), LV_STATE_CHECKED); lv_obj_set_style_shadow_width(obj, 15, LV_STATE_PRESSED); lv_obj_set_style_shadow_color(obj, lv_color_hex(0xFF9500), LV_STATE_PRESSED); - lv_obj_set_style_shadow_opa(obj, 180, LV_STATE_FOCUSED); + lv_obj_set_style_shadow_opa(obj, 0, LV_STATE_FOCUSED); lv_obj_set_style_shadow_opa(obj, 180, LV_STATE_CHECKED); lv_obj_set_style_shadow_opa(obj, 180, LV_STATE_PRESSED); lv_obj_set_size(obj, LV_PCT(95), 36); - lv_obj_t * label = NULL; - - if(txt) { + if (txt) { label = lv_label_create(obj); lv_label_set_text(label, txt); lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); @@ -198,18 +214,41 @@ static lv_obj_t * create_text(lv_obj_t * parent, const char * txt) { return obj; } +/** @brief Event handler for menu page changes to control Save button visibility. + * @note Hides Save button when USB or Flash settings are active because + * filesystem is locked during USB mode and Flash operations don't + * require explicit saving. + * @param e Pointer to the event + */ +static void on_menu_page_changed(lv_event_t *e) +{ + lv_obj_t *menu_obj = static_cast(lv_event_get_target(e)); + lv_obj_t *cur_page = lv_menu_get_cur_main_page(menu_obj); + + if (cur_page == NULL) { + return; + } + + /* Hide Save button on USB and Flash pages */ + if ((cur_page == usb_Page) || (cur_page == flash_Page)) { + lv_obj_add_flag(ui_Button_Menu_Save, LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_remove_flag(ui_Button_Menu_Save, LV_OBJ_FLAG_HIDDEN); + } +} + /** @brief Creates the About page. * @param p_Menu Pointer to the menu object */ -static lv_obj_t * ui_Settings_Create_About_Page(lv_obj_t *p_parent) +static lv_obj_t *ui_Settings_Create_About_Page(lv_obj_t *p_parent) { - lv_obj_t * cont; - lv_obj_t * section; - lv_obj_t * about_page; - lv_obj_t * about_container; + lv_obj_t *cont; + lv_obj_t *section; + lv_obj_t *about_page; + lv_obj_t *about_container; Menu_Page_Result_t about_result; - lv_obj_t * sub_software_info_page; - lv_obj_t * sub_legal_info_page; + lv_obj_t *sub_software_info_page; + lv_obj_t *sub_legal_info_page; char Buffer[64]; about_result = create_menu_page_with_container(p_parent); @@ -234,7 +273,8 @@ static lv_obj_t * ui_Settings_Create_About_Page(lv_obj_t *p_parent) create_text(section, Buffer); memset(Buffer, 0, sizeof(Buffer)); - snprintf(Buffer, sizeof(Buffer), "LVGL Version: %d.%d.%d\n", LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, LVGL_VERSION_PATCH); + snprintf(Buffer, sizeof(Buffer), "LVGL Version: %d.%d.%d\n", LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, + LVGL_VERSION_PATCH); create_text(section, Buffer); sub_legal_info_page = lv_menu_page_create(p_parent, NULL); @@ -243,13 +283,13 @@ static lv_obj_t * ui_Settings_Create_About_Page(lv_obj_t *p_parent) lv_obj_set_style_bg_opa(section, 255, 0); lv_obj_set_style_pad_all(section, 8, 0); - lv_obj_t * license_label = lv_label_create(section); - lv_label_set_text(license_label, - "(c) 2026 PyroVision Project\n" - "Licensed under GNU GPL v3\n" - "\n" - "This program is free software.\n" - "See LICENSE file for details."); + lv_obj_t *license_label = lv_label_create(section); + lv_label_set_text(license_label, + "(c) 2026 PyroVision Project\n" + "Licensed under GNU GPL v3\n" + "\n" + "This program is free software.\n" + "See LICENSE file for details."); lv_obj_set_width(license_label, LV_PCT(95)); lv_obj_set_style_text_color(license_label, lv_color_white(), 0); lv_obj_set_style_text_align(license_label, LV_TEXT_ALIGN_LEFT, 0); @@ -266,55 +306,72 @@ static lv_obj_t * ui_Settings_Create_About_Page(lv_obj_t *p_parent) /** @brief Creates the WiFi settings page and load it with the values from the settings. * @param p_Menu Pointer to the menu object */ -static lv_obj_t* ui_Settings_Create_WiFi_Page(lv_obj_t *p_Menu) +static lv_obj_t *ui_Settings_Create_WiFi_Page(lv_obj_t *p_Menu) { Menu_Page_Result_t WiFiResult = create_menu_page_with_container(p_Menu); - lv_obj_t * WiFiContainer = WiFiResult.Container; - lv_obj_t * WiFiPage = WiFiResult.Page; + lv_obj_t *WiFiContainer = WiFiResult.Container; + lv_obj_t *WiFiPage = WiFiResult.Page; App_Settings_WiFi_t WiFiSettings; SettingsManager_GetWiFi(&WiFiSettings); - lv_obj_t * wifi_row1 = create_row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); - lv_obj_t * wifi_label = lv_label_create(wifi_row1); + lv_obj_t *wifi_row1 = create_row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *wifi_label = lv_label_create(wifi_row1); lv_label_set_text(wifi_label, "Autoconnect"); lv_obj_set_style_text_color(wifi_label, lv_color_white(), 0); - lv_obj_t * wifi_switch = lv_switch_create(wifi_row1); + lv_obj_t *wifi_switch = lv_switch_create(wifi_row1); lv_obj_set_style_bg_color(wifi_switch, lv_color_hex(0x7B3FF0), 0); lv_obj_set_style_bg_color(wifi_switch, lv_color_hex(0xFF9500), LV_PART_KNOB); lv_obj_add_event_cb(wifi_switch, on_WiFi_Autoconnect_Callback, LV_EVENT_VALUE_CHANGED, NULL); - if(WiFiSettings.AutoConnect) { + if (WiFiSettings.AutoConnect) { lv_obj_add_state(wifi_switch, LV_STATE_CHECKED); } else { lv_obj_remove_state(wifi_switch, LV_STATE_CHECKED); } - lv_obj_t * wifi_row2 = create_row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); - lv_obj_t * ssid_label = lv_label_create(wifi_row2); + lv_obj_t *wifi_row2 = create_row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *ssid_label = lv_label_create(wifi_row2); lv_label_set_text(ssid_label, "Status"); lv_obj_set_style_text_color(ssid_label, lv_color_white(), 0); wifi_status_label = lv_label_create(wifi_row2); lv_label_set_text(wifi_status_label, "Offline"); lv_obj_set_style_text_color(wifi_status_label, lv_color_hex(0xFF9500), 0); + /* WiFi Connect Button */ + lv_obj_t *wifi_btn_row = create_row(WiFiContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_set_height(wifi_btn_row, LV_SIZE_CONTENT); + lv_obj_set_style_pad_top(wifi_btn_row, 12, 0); + lv_obj_set_style_pad_bottom(wifi_btn_row, 8, 0); + lv_obj_t *wifi_connect_btn = lv_btn_create(wifi_btn_row); + lv_obj_set_size(wifi_connect_btn, 140, 36); + lv_obj_set_style_bg_color(wifi_connect_btn, lv_color_hex(0xFF9500), LV_STATE_DEFAULT); + lv_obj_set_style_radius(wifi_connect_btn, 6, 0); + lv_obj_set_style_shadow_width(wifi_connect_btn, 0, 0); + lv_obj_add_event_cb(wifi_connect_btn, on_WiFi_Connect_Callback, LV_EVENT_CLICKED, NULL); + lv_obj_t *wifi_btn_label = lv_label_create(wifi_connect_btn); + lv_label_set_text(wifi_btn_label, "Connect WiFi"); + lv_obj_set_style_text_color(wifi_btn_label, lv_color_white(), 0); + lv_obj_center(wifi_btn_label); + return WiFiPage; } /** @brief Creates the display settings page and load it with the values from the settings. * @param p_Menu Pointer to the menu object */ -static lv_obj_t* ui_Settings_Create_Display_Page(lv_obj_t *p_Menu) +static lv_obj_t *ui_Settings_Create_Display_Page(lv_obj_t *p_Menu) { Menu_Page_Result_t DisplayResult = create_menu_page_with_container(p_Menu); - lv_obj_t * DisplayContainer = DisplayResult.Container; - lv_obj_t * DisplayPage = DisplayResult.Page; + lv_obj_t *DisplayContainer = DisplayResult.Container; + lv_obj_t *DisplayPage = DisplayResult.Page; App_Settings_Display_t DisplaySettings; SettingsManager_GetDisplay(&DisplaySettings); - lv_obj_t *brightness_slider = create_compact_slider(DisplayContainer, "Brightness", 0, 100, DisplaySettings.Brightness, &brightness_widgets); + lv_obj_t *brightness_slider = create_compact_slider(DisplayContainer, "Brightness", 0, 100, DisplaySettings.Brightness, + &brightness_widgets); lv_obj_add_event_cb(brightness_slider, on_Display_Brightness_Slider_Callback, LV_EVENT_VALUE_CHANGED, NULL); @@ -324,26 +381,27 @@ static lv_obj_t* ui_Settings_Create_Display_Page(lv_obj_t *p_Menu) /** @brief Creates the Lepton settings page and load it with the values from the settings. * @param p_Menu Pointer to the menu object */ -static lv_obj_t* ui_Settings_Create_Lepton_Page(lv_obj_t *p_Menu) +static lv_obj_t *ui_Settings_Create_Lepton_Page(lv_obj_t *p_Menu) { std::string Buffer; Menu_Page_Result_t LeptonResult = create_menu_page_with_container(p_Menu); - lv_obj_t * LeptonContainer = LeptonResult.Container; - lv_obj_t * LeptonPage = LeptonResult.Page; + lv_obj_t *LeptonContainer = LeptonResult.Container; + lv_obj_t *LeptonPage = LeptonResult.Page; App_Settings_Lepton_t LeptonSettings; SettingsManager_GetLepton(&LeptonSettings); - for(size_t i = 0; i < LeptonSettings.EmissivityCount; i++) { + for (size_t i = 0; i < LeptonSettings.EmissivityCount; i++) { Buffer += LeptonSettings.EmissivityPresets[i].Description + std::string("\n"); } - lv_obj_t *emissivity_slider = create_compact_slider(LeptonContainer, "Emissivity", 0, 100, LeptonSettings.CurrentEmissivity, &emissivity_widgets); + lv_obj_t *emissivity_slider = create_compact_slider(LeptonContainer, "Emissivity", 0, 100, + LeptonSettings.CurrentEmissivity, &emissivity_widgets); lv_obj_add_event_cb(emissivity_slider, on_Lepton_Emissivity_Slider_Callback, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_add_event_cb(emissivity_slider, on_Lepton_Emissivity_Slider_Callback, LV_EVENT_RELEASED, NULL); - lv_obj_t * dropdown_row = create_row(LeptonContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_t *dropdown_row = create_row(LeptonContainer, LV_FLEX_ALIGN_CENTER); emissivity_Dropdown = lv_dropdown_create(dropdown_row); lv_obj_set_width(emissivity_Dropdown, LV_PCT(95)); lv_obj_set_style_bg_color(emissivity_Dropdown, lv_color_hex(0x3A3A3A), LV_PART_MAIN); @@ -362,90 +420,288 @@ static lv_obj_t* ui_Settings_Create_Lepton_Page(lv_obj_t *p_Menu) return LeptonPage; } +/** @brief Creates the USB settings page. + * @param p_Menu Pointer to the menu object + */ +static lv_obj_t *ui_Settings_Create_USB_Page(lv_obj_t *p_Menu) +{ + Menu_Page_Result_t USBResult = create_menu_page_with_container(p_Menu); + lv_obj_t *USBContainer = USBResult.Container; + lv_obj_t *USBPage = USBResult.Page; + + lv_obj_t *usb_section_label = lv_label_create(USBContainer); + lv_label_set_text(usb_section_label, "USB Mass Storage"); + lv_obj_set_style_text_color(usb_section_label, lv_color_hex(0xFF9500), 0); + lv_obj_set_style_text_font(usb_section_label, &lv_font_montserrat_14, 0); + lv_obj_set_style_pad_top(usb_section_label, 0, 0); + lv_obj_set_style_pad_bottom(usb_section_label, 8, 0); + + lv_obj_t *usb_desc_label = lv_label_create(USBContainer); + lv_label_set_text(usb_desc_label, "Expose storage via USB to PC"); + lv_obj_set_style_text_color(usb_desc_label, lv_color_hex(0xAAAAAA), 0); + lv_obj_set_style_text_font(usb_desc_label, &lv_font_montserrat_12, 0); + lv_obj_set_style_pad_bottom(usb_desc_label, 8, 0); + + lv_obj_t *usb_warning_label = lv_label_create(USBContainer); + lv_label_set_text(usb_warning_label, "⚠️ App cannot save while USB is active!"); + lv_obj_set_style_text_color(usb_warning_label, lv_color_hex(0xFF9500), 0); + lv_obj_set_style_text_font(usb_warning_label, &lv_font_montserrat_10, 0); + lv_obj_set_style_pad_bottom(usb_warning_label, 12, 0); + + lv_obj_t *usb_switch_row = create_row(USBContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_set_style_pad_top(usb_switch_row, 4, 0); + lv_obj_set_style_pad_bottom(usb_switch_row, 4, 0); + + lv_obj_t *usb_mode_label = lv_label_create(usb_switch_row); + lv_label_set_text(usb_mode_label, "USB Mode"); + lv_obj_set_style_text_color(usb_mode_label, lv_color_white(), 0); + lv_obj_set_style_text_font(usb_mode_label, &lv_font_montserrat_14, 0); + + usb_mode_switch = lv_switch_create(usb_switch_row); + lv_obj_set_size(usb_mode_switch, 50, 25); + lv_obj_set_style_bg_color(usb_mode_switch, lv_color_hex(0x7B3FF0), 0); + lv_obj_set_style_bg_color(usb_mode_switch, lv_color_hex(0xFF9500), LV_PART_KNOB); + lv_obj_add_event_cb(usb_mode_switch, on_USB_Mode_Switch_Callback, LV_EVENT_VALUE_CHANGED, NULL); + + return USBPage; +} + /** @brief Creates the Flash settings page and load it with the values from the settings. * @param p_Menu Pointer to the menu object */ -static lv_obj_t* ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) +static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) { Menu_Page_Result_t FlashResult = create_menu_page_with_container(p_Menu); - lv_obj_t * FlashContainer = FlashResult.Container; - lv_obj_t * FlashPage = FlashResult.Page; - - lv_obj_t * flash_row1 = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); - lv_obj_t * flash_label1 = lv_label_create(flash_row1); - lv_label_set_text(flash_label1, "Used"); - lv_obj_set_style_text_color(flash_label1, lv_color_white(), 0); - lv_obj_t * flash_value1 = lv_label_create(flash_row1); - lv_label_set_text(flash_value1, "2.1 MB"); - lv_obj_set_style_text_color(flash_value1, lv_color_hex(0xB998FF), 0); - - lv_obj_t * flash_row2 = create_row(FlashContainer, LV_FLEX_ALIGN_CENTER); - lv_obj_t * flash_btn = lv_btn_create(flash_row2); - lv_obj_set_width(flash_btn, 90); - lv_obj_set_style_bg_color(flash_btn, lv_color_hex(0xFF3B3B), LV_STATE_DEFAULT); - lv_obj_set_style_radius(flash_btn, 6, 0); - lv_obj_t * flash_btn_label = lv_label_create(flash_btn); - lv_label_set_text(flash_btn_label, "Clear"); - lv_obj_set_style_text_color(flash_btn_label, lv_color_white(), 0); - lv_obj_center(flash_btn_label); + lv_obj_t *FlashContainer = FlashResult.Container; + lv_obj_t *FlashPage = FlashResult.Page; + + lv_obj_t *nvs_section_label = lv_label_create(FlashContainer); + lv_label_set_text(nvs_section_label, "NVS Settings"); + lv_obj_set_style_text_color(nvs_section_label, lv_color_hex(0xFF9500), 0); + lv_obj_set_style_text_font(nvs_section_label, &lv_font_montserrat_14, 0); + lv_obj_set_style_pad_top(nvs_section_label, 0, 0); + lv_obj_set_style_pad_bottom(nvs_section_label, 8, 0); + + lv_obj_t *nvs_desc_label = lv_label_create(FlashContainer); + lv_label_set_text(nvs_desc_label, "Factory reset"); + lv_obj_set_style_text_color(nvs_desc_label, lv_color_hex(0xAAAAAA), 0); + lv_obj_set_style_text_font(nvs_desc_label, &lv_font_montserrat_12, 0); + lv_obj_set_style_pad_bottom(nvs_desc_label, 8, 0); + + lv_obj_t *nvs_btn_row = create_row(FlashContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_set_height(nvs_btn_row, LV_SIZE_CONTENT); + lv_obj_set_style_pad_top(nvs_btn_row, 4, 0); + lv_obj_set_style_pad_bottom(nvs_btn_row, 4, 0); + lv_obj_t *nvs_clear_btn = lv_btn_create(nvs_btn_row); + lv_obj_set_size(nvs_clear_btn, 120, 36); + lv_obj_set_style_bg_color(nvs_clear_btn, lv_color_hex(0xFF3B3B), LV_STATE_DEFAULT); + lv_obj_set_style_radius(nvs_clear_btn, 6, 0); + lv_obj_set_style_shadow_width(nvs_clear_btn, 0, 0); + lv_obj_add_event_cb(nvs_clear_btn, on_Flash_ClearNVS_Callback, LV_EVENT_CLICKED, NULL); + lv_obj_t *nvs_btn_label = lv_label_create(nvs_clear_btn); + lv_label_set_text(nvs_btn_label, "Reset"); + lv_obj_set_style_text_color(nvs_btn_label, lv_color_white(), 0); + lv_obj_center(nvs_btn_label); + + /* Separator */ + lv_obj_t *separator1 = lv_obj_create(FlashContainer); + lv_obj_set_size(separator1, LV_PCT(100), 1); + lv_obj_set_style_bg_color(separator1, lv_color_hex(0x505050), 0); + lv_obj_set_style_border_width(separator1, 0, 0); + lv_obj_set_style_pad_all(separator1, 0, 0); + lv_obj_set_style_margin_top(separator1, 12, 0); + lv_obj_set_style_margin_bottom(separator1, 12, 0); + + lv_obj_t *storage_section_label = lv_label_create(FlashContainer); + lv_label_set_text(storage_section_label, "Storage Partition"); + lv_obj_set_style_text_color(storage_section_label, lv_color_hex(0xFF9500), 0); + lv_obj_set_style_text_font(storage_section_label, &lv_font_montserrat_14, 0); + lv_obj_set_style_pad_top(storage_section_label, 0, 0); + lv_obj_set_style_pad_bottom(storage_section_label, 8, 0); + + lv_obj_t *storage_info_row = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *storage_used_label = lv_label_create(storage_info_row); + lv_label_set_text(storage_used_label, "Used:"); + lv_obj_set_style_text_color(storage_used_label, lv_color_white(), 0); + flash_storage_used_label = lv_label_create(storage_info_row); + lv_label_set_text(flash_storage_used_label, "-- KB"); + lv_obj_set_style_text_color(flash_storage_used_label, lv_color_hex(0xB998FF), 0); + + lv_obj_t *storage_free_row = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *storage_free_label = lv_label_create(storage_free_row); + lv_label_set_text(storage_free_label, "Free:"); + lv_obj_set_style_text_color(storage_free_label, lv_color_white(), 0); + flash_storage_free_label = lv_label_create(storage_free_row); + lv_label_set_text(flash_storage_free_label, "-- KB"); + lv_obj_set_style_text_color(flash_storage_free_label, lv_color_hex(0xB998FF), 0); + + lv_obj_t *storage_btn_row = create_row(FlashContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_set_height(storage_btn_row, LV_SIZE_CONTENT); + lv_obj_set_style_pad_top(storage_btn_row, 8, 0); + lv_obj_set_style_pad_bottom(storage_btn_row, 8, 0); + lv_obj_t *storage_clear_btn = lv_btn_create(storage_btn_row); + lv_obj_set_size(storage_clear_btn, 120, 36); + lv_obj_set_style_bg_color(storage_clear_btn, lv_color_hex(0xFF3B3B), LV_STATE_DEFAULT); + lv_obj_set_style_radius(storage_clear_btn, 6, 0); + lv_obj_set_style_shadow_width(storage_clear_btn, 0, 0); + lv_obj_add_event_cb(storage_clear_btn, on_Flash_ClearStorage_Callback, LV_EVENT_CLICKED, NULL); + lv_obj_t *storage_btn_label = lv_label_create(storage_clear_btn); + lv_label_set_text(storage_btn_label, "Clear"); + lv_obj_set_style_text_color(storage_btn_label, lv_color_white(), 0); + lv_obj_center(storage_btn_label); + + /* Separator */ + lv_obj_t *separator2 = lv_obj_create(FlashContainer); + lv_obj_set_size(separator2, LV_PCT(100), 1); + lv_obj_set_style_bg_color(separator2, lv_color_hex(0x505050), 0); + lv_obj_set_style_border_width(separator2, 0, 0); + lv_obj_set_style_pad_all(separator2, 0, 0); + lv_obj_set_style_margin_top(separator2, 12, 0); + lv_obj_set_style_margin_bottom(separator2, 12, 0); + + lv_obj_t *coredump_section_label = lv_label_create(FlashContainer); + lv_label_set_text(coredump_section_label, "Coredump Partition"); + lv_obj_set_style_text_color(coredump_section_label, lv_color_hex(0xFF9500), 0); + lv_obj_set_style_text_font(coredump_section_label, &lv_font_montserrat_14, 0); + lv_obj_set_style_pad_top(coredump_section_label, 0, 0); + lv_obj_set_style_pad_bottom(coredump_section_label, 8, 0); + + lv_obj_t *coredump_info_row = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *coredump_used_label = lv_label_create(coredump_info_row); + lv_label_set_text(coredump_used_label, "Used:"); + lv_obj_set_style_text_color(coredump_used_label, lv_color_white(), 0); + flash_coredump_used_label = lv_label_create(coredump_info_row); + lv_label_set_text(flash_coredump_used_label, "-- KB"); + lv_obj_set_style_text_color(flash_coredump_used_label, lv_color_hex(0xB998FF), 0); + + lv_obj_t *coredump_total_row = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *coredump_total_label = lv_label_create(coredump_total_row); + lv_label_set_text(coredump_total_label, "Total:"); + lv_obj_set_style_text_color(coredump_total_label, lv_color_white(), 0); + flash_coredump_total_label = lv_label_create(coredump_total_row); + lv_label_set_text(flash_coredump_total_label, "-- KB"); + lv_obj_set_style_text_color(flash_coredump_total_label, lv_color_hex(0xB998FF), 0); + + lv_obj_t *coredump_btn_row = create_row(FlashContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_set_height(coredump_btn_row, LV_SIZE_CONTENT); + lv_obj_set_style_pad_top(coredump_btn_row, 8, 0); + lv_obj_set_style_pad_bottom(coredump_btn_row, 16, 0); + lv_obj_t *coredump_clear_btn = lv_btn_create(coredump_btn_row); + lv_obj_set_size(coredump_clear_btn, 120, 36); + lv_obj_set_style_bg_color(coredump_clear_btn, lv_color_hex(0xFF3B3B), LV_STATE_DEFAULT); + lv_obj_set_style_radius(coredump_clear_btn, 6, 0); + lv_obj_set_style_shadow_width(coredump_clear_btn, 0, 0); + lv_obj_add_event_cb(coredump_clear_btn, on_Flash_ClearCoredump_Callback, LV_EVENT_CLICKED, NULL); + lv_obj_t *coredump_btn_label = lv_label_create(coredump_clear_btn); + lv_label_set_text(coredump_btn_label, "Clear"); + lv_obj_set_style_text_color(coredump_btn_label, lv_color_white(), 0); + lv_obj_center(coredump_btn_label); return FlashPage; } void ui_settings_build(lv_obj_t *p_Parent) { - menu = lv_menu_create(p_Parent); - settings_Menu = menu; - lv_obj_set_size(menu, lv_pct(100), lv_pct(100)); - lv_obj_center(menu); - lv_obj_set_style_bg_color(menu, lv_color_hex(0x1E1E1E), 0); - lv_obj_set_style_bg_opa(menu, 255, 0); - - lv_menu_set_mode_header(menu, LV_MENU_HEADER_TOP_FIXED); - - wifi_Page = ui_Settings_Create_WiFi_Page(menu); - display_Page = ui_Settings_Create_Display_Page(menu); - lepton_Page = ui_Settings_Create_Lepton_Page(menu); - flash_Page = ui_Settings_Create_Flash_Page(menu); - about_Page = ui_Settings_Create_About_Page(menu); - - root_page = lv_menu_page_create(menu, NULL); + settings_Menu = lv_menu_create(p_Parent); + + lv_obj_set_size(settings_Menu, lv_pct(100), lv_pct(100)); + lv_obj_center(settings_Menu); + lv_obj_set_style_bg_color(settings_Menu, lv_color_hex(0x1E1E1E), 0); + lv_obj_set_style_bg_opa(settings_Menu, 0, 0); + lv_menu_set_mode_header(settings_Menu, LV_MENU_HEADER_TOP_FIXED); + + wifi_Page = ui_Settings_Create_WiFi_Page(settings_Menu); + display_Page = ui_Settings_Create_Display_Page(settings_Menu); + lepton_Page = ui_Settings_Create_Lepton_Page(settings_Menu); + flash_Page = ui_Settings_Create_Flash_Page(settings_Menu); + usb_Page = ui_Settings_Create_USB_Page(settings_Menu); + about_Page = ui_Settings_Create_About_Page(settings_Menu); + + root_page = lv_menu_page_create(settings_Menu, NULL); lv_obj_set_style_bg_color(root_page, lv_color_hex(0x1E1E1E), 0); - lv_obj_set_style_bg_opa(root_page, 255, 0); + lv_obj_set_style_bg_opa(root_page, 0, 0); section = lv_menu_section_create(root_page); lv_obj_set_style_bg_color(section, lv_color_hex(0x1E1E1E), 0); - lv_obj_set_style_bg_opa(section, 255, 0); + lv_obj_set_style_bg_opa(section, 0, 0); lv_obj_set_style_pad_all(section, 8, 0); cont = create_text(section, "WiFi"); - lv_menu_set_load_page_event(menu, cont, wifi_Page); + lv_menu_set_load_page_event(settings_Menu, cont, wifi_Page); cont = create_text(section, "Display"); - lv_menu_set_load_page_event(menu, cont, display_Page); + lv_menu_set_load_page_event(settings_Menu, cont, display_Page); cont = create_text(section, "Lepton"); - lv_menu_set_load_page_event(menu, cont, lepton_Page); + lv_menu_set_load_page_event(settings_Menu, cont, lepton_Page); cont = create_text(section, "Flash"); - lv_menu_set_load_page_event(menu, cont, flash_Page); + lv_menu_set_load_page_event(settings_Menu, cont, flash_Page); + lv_obj_add_event_cb(cont, [](lv_event_t *e) { + if (lv_event_get_code(e) == LV_EVENT_CLICKED) { + ui_settings_update_flash_usage(); + } + }, LV_EVENT_CLICKED, NULL); + + cont = create_text(section, "USB"); + lv_menu_set_load_page_event(settings_Menu, cont, usb_Page); cont = create_text(section, "About"); - lv_menu_set_load_page_event(menu, cont, about_Page); + lv_menu_set_load_page_event(settings_Menu, cont, about_Page); + + lv_menu_set_sidebar_page(settings_Menu, root_page); - lv_menu_set_sidebar_page(menu, root_page); + /* Register event handler for menu page changes to control Save button visibility */ + lv_obj_add_event_cb(settings_Menu, on_menu_page_changed, LV_EVENT_VALUE_CHANGED, NULL); + /* Initially check current page (root page doesn't need Save button hidden) */ + lv_obj_remove_flag(ui_Button_Menu_Save, LV_OBJ_FLAG_HIDDEN); + + esp_event_handler_register(USB_EVENTS, ESP_EVENT_ANY_ID, on_USB_Event_Handler, NULL); esp_event_handler_register(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler, NULL); esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL); } void ui_settings_deinit(lv_obj_t *p_Parent) { - if(ui_Splash) { + if (ui_Splash) { lv_obj_del(settings_Menu); lv_obj_delete(settings_Menu); + esp_event_handler_unregister(USB_EVENTS, ESP_EVENT_ANY_ID, on_USB_Event_Handler); esp_event_handler_unregister(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler); esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); } +} + +void ui_settings_update_flash_usage(void) +{ + MemoryManager_Usage_t Usage; + + if ((flash_storage_used_label != NULL) && (flash_storage_free_label != NULL)) { + esp_err_t Error = MemoryManager_GetStorageUsage(&Usage); + if (Error == ESP_OK) { + if (Usage.TotalBytes >= (1024 * 1024)) { + lv_label_set_text_fmt(flash_storage_used_label, "%.2f MB", Usage.UsedBytes / (1024.0f * 1024.0f)); + lv_label_set_text_fmt(flash_storage_free_label, "%.2f MB", Usage.FreeBytes / (1024.0f * 1024.0f)); + } else { + lv_label_set_text_fmt(flash_storage_used_label, "%.1f KB", Usage.UsedBytes / 1024.0f); + lv_label_set_text_fmt(flash_storage_free_label, "%.1f KB", Usage.FreeBytes / 1024.0f); + } + } else { + lv_label_set_text(flash_storage_used_label, "Error"); + lv_label_set_text(flash_storage_free_label, "Error"); + } + } + + if ((flash_coredump_used_label != NULL) && (flash_coredump_total_label != NULL)) { + esp_err_t Error = MemoryManager_GetCoredumpUsage(&Usage); + if (Error == ESP_OK) { + lv_label_set_text_fmt(flash_coredump_used_label, "%u KB", Usage.UsedBytes / 1024); + lv_label_set_text_fmt(flash_coredump_total_label, "%u KB", Usage.TotalBytes / 1024); + } else { + lv_label_set_text(flash_coredump_used_label, "Error"); + lv_label_set_text(flash_coredump_total_label, "Error"); + } + } } \ No newline at end of file diff --git a/main/Application/Tasks/GUI/UI/ui_Settings.h b/main/Application/Tasks/GUI/UI/ui_Settings.h index 2f74b5e..299ef45 100644 --- a/main/Application/Tasks/GUI/UI/ui_Settings.h +++ b/main/Application/Tasks/GUI/UI/ui_Settings.h @@ -28,11 +28,19 @@ #include -extern lv_obj_t * wifi_status_label; +extern lv_obj_t *wifi_status_label; /** @brief Builds the settings UI. * @param p_Parent Pointer to the parent object where the settings UI will be attached */ -void ui_settings_build(lv_obj_t * p_Parent); +void ui_settings_build(lv_obj_t *p_Parent); + +/** @brief Updates flash partition usage information in the Flash settings page. + * Call this when the Flash settings page becomes visible to show + * current storage and coredump partition usage. + * @note This function queries the FlashManager for current partition usage + * and updates the UI labels accordingly. + */ +void ui_settings_update_flash_usage(void); #endif /* UI_SETTINGS_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp index bfe1167..f5409b8 100644 --- a/main/Application/Tasks/GUI/guiTask.cpp +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -33,6 +33,9 @@ #include #include +#include +#include +#include #include "guiTask.h" #include "Export/ui.h" @@ -40,16 +43,54 @@ #include "Application/Manager/managers.h" #include "Application/Manager/Network/Server/server.h" #include "Private/guiHelper.h" +#include "Private/guiImageSave.h" #include "lepton.h" ESP_EVENT_DEFINE_BASE(GUI_EVENTS); -static GUI_Task_State_t _GUITask_State; +GUI_Task_State_t _GUI_Task_State; -static const char *TAG = "gui_task"; +static const char *TAG = "GUI-Task"; -/** @brief +/** @brief Event handler for GUI events (e.g., image save completion). + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data + */ +static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) +{ + ESP_LOGD(TAG, "GUI event received: ID=%d", ID); + + switch (ID) { + case GUI_EVENT_THERMAL_IMAGE_SAVED: { + ESP_LOGI(TAG, "Thermal image saved successfully"); + + /* Show success message box */ + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "Image Saved"); + lv_msgbox_add_text(msgbox, "Thermal image saved successfully!"); + lv_msgbox_add_close_button(msgbox); + + break; + } + case GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED: { + ESP_LOGE(TAG, "Thermal image save failed"); + + /* Show error message box */ + lv_obj_t *msgbox = lv_msgbox_create(NULL); + lv_msgbox_add_title(msgbox, "Save Failed"); + lv_msgbox_add_text(msgbox, "Failed to save thermal image!\\nCheck storage or USB mode."); + lv_msgbox_add_close_button(msgbox); + lv_obj_set_style_bg_color(msgbox, lv_color_hex(0xFF0000), LV_PART_MAIN); + + break; + } + } +} + +/** @brief Event handler for the Devices events to receive updates when settings are changed. * @param p_HandlerArgs Handler argument * @param Base Event base * @param ID Event ID @@ -61,25 +102,29 @@ static void on_Devices_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, switch (ID) { case DEVICE_EVENT_RESPONSE_BATTERY_VOLTAGE: { - memcpy(&_GUITask_State.BatteryInfo, p_Data, sizeof(App_Devices_Battery_t)); + if (p_Data != NULL) { + memcpy(&_GUI_Task_State.BatteryInfo, p_Data, sizeof(App_Devices_Battery_t)); - xEventGroupSetBits(_GUITask_State.EventGroup, BATTERY_VOLTAGE_READY); + xEventGroupSetBits(_GUI_Task_State.EventGroup, BATTERY_VOLTAGE_READY); + } else { + ESP_LOGE(TAG, "DEVICE_EVENT_RESPONSE_BATTERY_VOLTAGE received with NULL data"); + } break; } case DEVICE_EVENT_RESPONSE_CHARGING: { - xEventGroupSetBits(_GUITask_State.EventGroup, BATTERY_CHARGING_STATUS_READY); + xEventGroupSetBits(_GUI_Task_State.EventGroup, BATTERY_CHARGING_STATUS_READY); break; } } } -/** @brief Time event handler. - * @param p_HandlerArgs Handler argument - * @param Base Event base - * @param ID Event ID - * @param p_Data Event-specific data +/** @brief Event handler for the SNTP events to receive updates when time is synchronized or updated. + * @param p_HandlerArgs Handler argument + * @param Base Event base + * @param ID Event ID + * @param p_Data Event-specific data */ static void on_Time_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) { @@ -95,7 +140,7 @@ static void on_Time_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, in } } -/** @brief +/** @brief Event handler for the Network events to receive updates when network events are triggered (e.g., WiFi connection changes). * @param p_HandlerArgs Handler argument * @param Base Event base * @param ID Event ID @@ -110,62 +155,59 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, break; } case NETWORK_EVENT_WIFI_GOT_IP: { - memcpy(&_GUITask_State.IP_Info, p_Data, sizeof(Network_IP_Info_t)); - _GUITask_State.WiFiConnected = true; + memcpy(&_GUI_Task_State.IP_Info, p_Data, sizeof(Network_IP_Info_t)); + _GUI_Task_State.WiFiConnected = true; - xEventGroupSetBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + xEventGroupSetBits(_GUI_Task_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); break; } case NETWORK_EVENT_WIFI_DISCONNECTED: { - _GUITask_State.WiFiConnected = false; + _GUI_Task_State.WiFiConnected = false; - xEventGroupSetBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + xEventGroupSetBits(_GUI_Task_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); break; } case NETWORK_EVENT_PROV_STARTED: { - _GUITask_State.ProvisioningActive = true; - _GUITask_State.WiFiConnected = false; + _GUI_Task_State.ProvisioningActive = true; + _GUI_Task_State.WiFiConnected = false; - xEventGroupSetBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + xEventGroupSetBits(_GUI_Task_State.EventGroup, PROVISIONING_STATE_CHANGED); break; } case NETWORK_EVENT_PROV_STOPPED: { - _GUITask_State.ProvisioningActive = false; - _GUITask_State.WiFiConnected = false; - - xEventGroupSetBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + _GUI_Task_State.ProvisioningActive = false; + _GUI_Task_State.WiFiConnected = false; - /* Also trigger WiFi status update to show correct connection state */ - xEventGroupSetBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + xEventGroupSetBits(_GUI_Task_State.EventGroup, PROVISIONING_STATE_CHANGED); + xEventGroupSetBits(_GUI_Task_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); break; } case NETWORK_EVENT_PROV_SUCCESS: { - _GUITask_State.ProvisioningActive = false; + _GUI_Task_State.ProvisioningActive = false; - xEventGroupSetBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + xEventGroupSetBits(_GUI_Task_State.EventGroup, PROVISIONING_STATE_CHANGED); break; } case NETWORK_EVENT_PROV_TIMEOUT: { - _GUITask_State.ProvisioningActive = false; - _GUITask_State.WiFiConnected = false; + _GUI_Task_State.ProvisioningActive = false; + _GUI_Task_State.WiFiConnected = false; - xEventGroupSetBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); - - /* Also trigger WiFi status update to show correct connection state */ - xEventGroupSetBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + xEventGroupSetBits(_GUI_Task_State.EventGroup, PROVISIONING_STATE_CHANGED); + xEventGroupSetBits(_GUI_Task_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); break; } case NETWORK_EVENT_SERVER_STARTED: { - /* Register thermal frame with server (called after server is started) */ - Server_SetThermalFrame(&_GUITask_State.NetworkFrame); ESP_LOGD(TAG, "Network frame registered with server"); + /* Register thermal frame with server (called after server is started) */ + Server_SetThermalFrame(&_GUI_Task_State.NetworkFrame); + break; } case NETWORK_EVENT_AP_STA_CONNECTED: { @@ -176,48 +218,7 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, } } } - -/** @brief SD card event handler. - * @param p_HandlerArgs Handler argument - * @param Base Event base - * @param ID Event ID - * @param p_Data Event-specific data - */ -static void on_SD_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int32_t ID, void *p_Data) -{ - ESP_LOGD(TAG, "SD card event received: ID=%ld", ID); - - switch (ID) { - case SD_EVENT_CARD_CHANGED: { - _GUITask_State.CardPresent = *(bool *)p_Data; - ESP_LOGI(TAG, "SD card %s", (_GUITask_State.CardPresent) ? "inserted" : "removed"); - - xEventGroupSetBits(_GUITask_State.EventGroup, SD_CARD_STATE_CHANGED); - - break; - } - case SD_EVENT_MOUNTED: { - ESP_LOGI(TAG, "SD card mounted successfully event"); - - xEventGroupSetBits(_GUITask_State.EventGroup, SD_CARD_MOUNTED); - - break; - } - case SD_EVENT_MOUNT_ERROR: { - ESP_LOGE(TAG, "SD card mount error event"); - - xEventGroupSetBits(_GUITask_State.EventGroup, SD_CARD_MOUNT_ERROR); - - break; - } - default: { - ESP_LOGW(TAG, "Unknown SD event ID: %ld", ID); - break; - } - } -} - -/** @brief +/** @brief Event handler for the Lepton events to receive updates when Lepton events are triggered (e.g., new frame ready, camera errors). * @param p_HandlerArgs Handler argument * @param Base Event base * @param ID Event ID @@ -229,54 +230,79 @@ static void on_Lepton_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, switch (ID) { case LEPTON_EVENT_CAMERA_READY: { - memcpy(&_GUITask_State.LeptonDeviceInfo, ((App_Lepton_Device_t *)p_Data), sizeof(App_Lepton_Device_t)); + if (p_Data != NULL) { + memcpy(&_GUI_Task_State.LeptonDeviceInfo, ((App_Lepton_Device_t *)p_Data), sizeof(App_Lepton_Device_t)); - xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_CAMERA_READY); + xEventGroupSetBits(_GUI_Task_State.EventGroup, LEPTON_CAMERA_READY); + } else { + ESP_LOGE(TAG, "LEPTON_EVENT_CAMERA_READY received with NULL data"); + } break; } case LEPTON_EVENT_CAMERA_ERROR: { - xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_CAMERA_ERROR); + xEventGroupSetBits(_GUI_Task_State.EventGroup, LEPTON_CAMERA_ERROR); break; } case LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP: { - memcpy(&_GUITask_State.LeptonTemperatures, p_Data, sizeof(App_Lepton_Temperatures_t)); + if (p_Data != NULL) { + memcpy(&_GUI_Task_State.LeptonTemperatures, p_Data, sizeof(App_Lepton_Temperatures_t)); - xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_TEMP_READY); + xEventGroupSetBits(_GUI_Task_State.EventGroup, LEPTON_TEMP_READY); + } else { + ESP_LOGE(TAG, "LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP received with NULL data"); + } break; } case LEPTON_EVENT_RESPONSE_SPOTMETER: { - memcpy(&_GUITask_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); + if (p_Data != NULL) { + memcpy(&_GUI_Task_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); - xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_SPOTMETER_READY); + xEventGroupSetBits(_GUI_Task_State.EventGroup, LEPTON_SPOTMETER_READY); + } else { + ESP_LOGE(TAG, "LEPTON_EVENT_RESPONSE_SPOTMETER received with NULL data"); + } break; } case LEPTON_EVENT_RESPONSE_SCENE_STATISTICS: { - memcpy(&_GUITask_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); + if (p_Data != NULL) { + memcpy(&_GUI_Task_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); - xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_SCENE_STATISTICS_READY); + xEventGroupSetBits(_GUI_Task_State.EventGroup, LEPTON_SCENE_STATISTICS_READY); + } else { + ESP_LOGE(TAG, "LEPTON_EVENT_RESPONSE_SCENE_STATISTICS received with NULL data"); + } break; } case LEPTON_EVENT_RESPONSE_UPTIME: { - memcpy(&_GUITask_State.LeptonUptime, p_Data, sizeof(uint32_t)); + if (p_Data != NULL) { + memcpy(&_GUI_Task_State.LeptonUptime, p_Data, sizeof(uint32_t)); - xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_UPTIME_READY); + xEventGroupSetBits(_GUI_Task_State.EventGroup, LEPTON_UPTIME_READY); + } else { + ESP_LOGE(TAG, "LEPTON_EVENT_RESPONSE_UPTIME received with NULL data"); + } break; } case LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE: { - memcpy(&_GUITask_State.SpotTemperature, p_Data, sizeof(float)); + if (p_Data != NULL) { + memcpy(&_GUI_Task_State.SpotTemperature, p_Data, sizeof(float)); - xEventGroupSetBits(_GUITask_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); + xEventGroupSetBits(_GUI_Task_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); + } else { + ESP_LOGE(TAG, "LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE received with NULL data"); + } break; } default: { ESP_LOGW(TAG, "Unhandled Lepton event ID: %d", ID); + break; } } @@ -286,17 +312,17 @@ static void on_Lepton_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, */ static void GUI_Update_Info(void) { - uint8_t mac[6]; - char mac_str[19]; + uint8_t MAC[6]; + char Buffer[19]; - esp_efuse_mac_get_default(mac); - snprintf(mac_str, sizeof(mac_str), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + esp_efuse_mac_get_default(MAC); + snprintf(Buffer, sizeof(Buffer), "%02X:%02X:%02X:%02X:%02X:%02X", MAC[0], MAC[1], MAC[2], MAC[3], MAC[4], MAC[5]); - lv_label_set_text(ui_Label_Info_Lepton_Serial, _GUITask_State.LeptonDeviceInfo.SerialNumber); - lv_label_set_text(ui_Label_Info_Lepton_Part, _GUITask_State.LeptonDeviceInfo.PartNumber); - lv_label_set_text(ui_Label_Info_Lepton_GPP_Revision, _GUITask_State.LeptonDeviceInfo.SoftwareRevision.GPP_Revision); - lv_label_set_text(ui_Label_Info_Lepton_DSP_Revision, _GUITask_State.LeptonDeviceInfo.SoftwareRevision.DSP_Revision); - lv_label_set_text(ui_Label_Info_MAC, mac_str); + lv_label_set_text(ui_Label_Info_Lepton_Serial, _GUI_Task_State.LeptonDeviceInfo.SerialNumber); + lv_label_set_text(ui_Label_Info_Lepton_Part, _GUI_Task_State.LeptonDeviceInfo.PartNumber); + lv_label_set_text(ui_Label_Info_Lepton_GPP_Revision, _GUI_Task_State.LeptonDeviceInfo.SoftwareRevision.GPP_Revision); + lv_label_set_text(ui_Label_Info_Lepton_DSP_Revision, _GUI_Task_State.LeptonDeviceInfo.SoftwareRevision.DSP_Revision); + lv_label_set_text(ui_Label_Info_MAC, Buffer); } /** @brief Update the ROI rectangle on the GUI and on the Lepton. @@ -378,6 +404,7 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) } default: { ESP_LOGW(TAG, "Invalid GUI ROI type: %d", ROI.Type); + return; } } @@ -390,6 +417,7 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) (SettingsLepton.ROI[ROI.Type].w == ROI.w) && (SettingsLepton.ROI[ROI.Type].h == ROI.h)) { ESP_LOGW(TAG, "ROI unchanged, not updating NVS"); + return; } @@ -419,16 +447,16 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) static void UI_Canvas_AddTempGradient(void) { /* Generate gradient pixel by pixel */ - uint16_t *buffer = (uint16_t *)_GUITask_State.GradientCanvasBuffer; + uint16_t *buffer = reinterpret_cast(_GUI_Task_State.GradientCanvasBuffer); - for (uint32_t y = 0; y < _GUITask_State.GradientImageDescriptor.header.h; y++) { + for (uint32_t y = 0; y < _GUI_Task_State.GradientImageDescriptor.header.h; y++) { uint32_t index; /* Map y position to palette index (0 = top/hot = white, 179 = bottom/cold = black) * Iron palette: index 0 = black (cold), index 255 = white (hot) * So we need to invert: top (y=0) should be index 255, bottom (y=179) should be index 0 */ - index = 255 - (y * 255 / (_GUITask_State.GradientImageDescriptor.header.h - 1)); + index = 255 - (y * 255 / (_GUI_Task_State.GradientImageDescriptor.header.h - 1)); /* Get RGB888 values from palette */ uint8_t r8 = Lepton_Palette_Iron[index][0]; @@ -441,8 +469,8 @@ static void UI_Canvas_AddTempGradient(void) uint16_t b5 = (b8 >> 3) & 0x1F; /* Fill entire row with same color */ - for (uint32_t x = 0; x < _GUITask_State.GradientImageDescriptor.header.w; x++) { - buffer[y * _GUITask_State.GradientImageDescriptor.header.w + x] = (r5 << 11) | (g6 << 5) | b5; + for (uint32_t x = 0; x < _GUI_Task_State.GradientImageDescriptor.header.w; x++) { + buffer[y * _GUI_Task_State.GradientImageDescriptor.header.w + x] = (r5 << 11) | (g6 << 5) | b5; } } } @@ -453,19 +481,21 @@ static void UI_Canvas_AddTempGradient(void) */ static void Touch_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data) { - uint8_t Count = 0; + uint8_t Count; esp_lcd_touch_point_data_t Data[1]; esp_lcd_touch_handle_t Touch; - Touch = (esp_lcd_touch_handle_t)lv_indev_get_user_data(p_Indev); - + Touch = static_cast(lv_indev_get_user_data(p_Indev)); + /* Check if touch controller is available */ if (Touch == NULL) { p_Data->state = LV_INDEV_STATE_RELEASED; + return; } - if ((esp_lcd_touch_read_data(Touch) == ESP_OK) && (esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])) == ESP_OK) && (Count > 0)) { + if ((esp_lcd_touch_read_data(Touch) == ESP_OK) && + (esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])) == ESP_OK) && (Count > 0)) { p_Data->point.x = CONFIG_GUI_WIDTH - Data[0].x; p_Data->point.y = Data[0].y; @@ -476,17 +506,17 @@ static void Touch_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data #ifdef CONFIG_GUI_TOUCH_DEBUG /* Update touch debug visualization */ - if (_GUITask_State.TouchDebugCircle != NULL) { - lv_obj_set_pos(_GUITask_State.TouchDebugCircle, p_Data->point.x - 10, p_Data->point.y - 10); - lv_obj_clear_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_HIDDEN); + if (_GUI_Task_State.TouchDebugCircle != NULL) { + lv_obj_set_pos(_GUI_Task_State.TouchDebugCircle, p_Data->point.x - 10, p_Data->point.y - 10); + lv_obj_clear_flag(_GUI_Task_State.TouchDebugCircle, LV_OBJ_FLAG_HIDDEN); } - if (_GUITask_State.TouchDebugLabel != NULL) { + if (_GUI_Task_State.TouchDebugLabel != NULL) { char buf[64]; snprintf(buf, sizeof(buf), "Raw: %u,%u\nMap: %li,%li", Data[0].x, Data[0].y, p_Data->point.x, p_Data->point.y); - lv_label_set_text(_GUITask_State.TouchDebugLabel, buf); - lv_obj_clear_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); + lv_label_set_text(_GUI_Task_State.TouchDebugLabel, buf); + lv_obj_clear_flag(_GUI_Task_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); } #endif } else { @@ -494,12 +524,12 @@ static void Touch_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data #ifdef CONFIG_GUI_TOUCH_DEBUG /* Hide touch debug visualization when released */ - if (_GUITask_State.TouchDebugCircle != NULL) { - lv_obj_add_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_HIDDEN); + if (_GUI_Task_State.TouchDebugCircle != NULL) { + lv_obj_add_flag(_GUI_Task_State.TouchDebugCircle, LV_OBJ_FLAG_HIDDEN); } - if (_GUITask_State.TouchDebugLabel != NULL) { - lv_obj_add_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); + if (_GUI_Task_State.TouchDebugLabel != NULL) { + lv_obj_add_flag(_GUI_Task_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); } #endif } @@ -515,7 +545,8 @@ void Task_GUI(void *p_Parameters) esp_task_wdt_add(NULL); - App_Context = reinterpret_cast(p_Parameters); + App_Context = static_cast(p_Parameters); + _GUI_Task_State.AppContext = App_Context; ESP_LOGD(TAG, "GUI Task started on core %d", xPortGetCoreID()); /* Show splash screen first and wait for all components to become ready before starting the application. */ @@ -527,16 +558,16 @@ void Task_GUI(void *p_Parameters) esp_task_wdt_reset(); - EventBits = xEventGroupGetBits(_GUITask_State.EventGroup); + EventBits = xEventGroupGetBits(_GUI_Task_State.EventGroup); if (EventBits & LEPTON_CAMERA_READY) { lv_bar_set_value(ui_SplashScreen_LoadingBar, 100, LV_ANIM_OFF); - xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_CAMERA_READY); + xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_CAMERA_READY); } else if (EventBits & LEPTON_CAMERA_ERROR) { lv_label_set_text(ui_SplashScreen_StatusText, "Camera Error"); - xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_CAMERA_ERROR); + xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_CAMERA_ERROR); } // TODO: Add timeout @@ -561,7 +592,7 @@ void Task_GUI(void *p_Parameters) esp_event_post(GUI_EVENTS, GUI_EVENT_APP_STARTED, NULL, 0, portMAX_DELAY); - while (_GUITask_State.isRunning) { + while (_GUI_Task_State.isRunning) { EventBits_t EventBits; App_Lepton_FrameReady_t LeptonFrame; @@ -605,13 +636,14 @@ void Task_GUI(void *p_Parameters) esp_task_wdt_reset(); /* Scale from source (160x120) to destination (240x180) using bilinear interpolation */ - Dst = _GUITask_State.ThermalCanvasBuffer; + Dst = _GUI_Task_State.ThermalCanvasBuffer; Image_Width = lv_obj_get_width(ui_Image_Thermal); Image_Height = lv_obj_get_height(ui_Image_Thermal); /* Skip if image widget not properly initialized yet */ if ((Image_Width == 0) || (Image_Height == 0)) { ESP_LOGW(TAG, "Image widget not ready yet (size: %ux%u), skipping frame", Image_Width, Image_Height); + continue; } @@ -666,7 +698,7 @@ void Task_GUI(void *p_Parameters) /* Max Label */ if ((x_rot >= SceneLabel_x0[0]) && - (x_rot < (SceneLabel_x0[0] + SceneLabel_w[0])) && + (x_rot < (SceneLabel_x0[0] + SceneLabel_w[0])) && (y >= SceneLabel_y0[0]) && (y < (SceneLabel_y0[0] + SceneLabel_h[0]))) { SceneLabelIlluminance[0] += static_cast((0.299f * r) + (0.587f * g) + (0.114f * b)); @@ -675,7 +707,7 @@ void Task_GUI(void *p_Parameters) /* Min Label */ if ((x_rot >= SceneLabel_x0[1]) && - (x_rot < (SceneLabel_x0[1] + SceneLabel_w[1])) && + (x_rot < (SceneLabel_x0[1] + SceneLabel_w[1])) && (y >= SceneLabel_y0[1]) && (y < (SceneLabel_y0[1] + SceneLabel_h[1]))) { SceneLabelIlluminance[1] += static_cast((0.299f * r) + (0.587f * g) + (0.114f * b)); @@ -684,7 +716,7 @@ void Task_GUI(void *p_Parameters) /* Mean Label */ if ((x_rot >= SceneLabel_x0[2]) && - (x_rot < (SceneLabel_x0[2] + SceneLabel_w[2])) && + (x_rot < (SceneLabel_x0[2] + SceneLabel_w[2])) && (y >= SceneLabel_y0[2]) && (y < (SceneLabel_y0[2] + SceneLabel_h[2]))) { SceneLabelIlluminance[2] += static_cast((0.299f * r) + (0.587f * g) + (0.114f * b)); @@ -713,9 +745,12 @@ void Task_GUI(void *p_Parameters) } } - lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Max, (SceneLabelAverageLuminance[0] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); - lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Min, (SceneLabelAverageLuminance[1] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); - lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Mean, (SceneLabelAverageLuminance[2] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Max, + (SceneLabelAverageLuminance[0] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Min, + (SceneLabelAverageLuminance[1] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); + lv_obj_set_style_text_color(ui_Label_Main_Thermal_Scene_Mean, + (SceneLabelAverageLuminance[2] > 128) ? lv_color_black() : lv_color_white(), LV_PART_MAIN); /* Reset watchdog after image processing */ esp_task_wdt_reset(); @@ -735,11 +770,33 @@ void Task_GUI(void *p_Parameters) ESP_LOGD(TAG, "Updated thermal image display (src: %ux%u -> dst: %ux%u)", LeptonFrame.Width, LeptonFrame.Height, Image_Width, Image_Height); + /* Save frame if requested */ + if (_GUI_Task_State.SaveNextFrameRequested) { + _GUI_Task_State.SaveNextFrameRequested = false; + + /* Prepare frame data for save task (using scaled RGB565 buffer) */ + App_Lepton_FrameReady_t SaveFrame; + SaveFrame.Buffer = _GUI_Task_State.ThermalCanvasBuffer; /* Use scaled display buffer */ + SaveFrame.Width = Image_Width; + SaveFrame.Height = Image_Height; + SaveFrame.Channels = 2; /* RGB565 = 2 bytes per pixel */ + SaveFrame.Min = LeptonFrame.Min; + SaveFrame.Max = LeptonFrame.Max; + + /* Send to background save task (non-blocking) */ + if (xQueueSend(_GUI_Task_State.ImageSaveQueue, &SaveFrame, 0) != pdTRUE) { + ESP_LOGW(TAG, "Image save queue full, skipping save"); + + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + } + } + /* Update network frame for server streaming if server is running */ - if (Server_isRunning()) { - if (xSemaphoreTake(_GUITask_State.NetworkFrame.Mutex, 0) == pdTRUE) { + if (Server_IsRunning()) { + if (xSemaphoreTake(_GUI_Task_State.NetworkFrame.Mutex, 0) == pdTRUE) { /* Convert scaled RGB565 buffer to RGB888 for network transmission */ - uint8_t *rgb888_dst = _GUITask_State.NetworkRGBBuffer; + uint8_t *rgb888_dst = _GUI_Task_State.NetworkRGBBuffer; + for (uint32_t i = 0; i < (Image_Width * Image_Height); i++) { /* Read RGB565 value (little endian) */ uint16_t rgb565 = Dst[(i * 2) + 0] | (Dst[(i * 2) + 1] << 8); @@ -755,12 +812,12 @@ void Task_GUI(void *p_Parameters) rgb888_dst[(i * 3) + 2] = b; } - _GUITask_State.NetworkFrame.Buffer = _GUITask_State.NetworkRGBBuffer; - _GUITask_State.NetworkFrame.Width = Image_Width; - _GUITask_State.NetworkFrame.Height = Image_Height; - _GUITask_State.NetworkFrame.Timestamp = esp_timer_get_time() / 1000; + _GUI_Task_State.NetworkFrame.Buffer = _GUI_Task_State.NetworkRGBBuffer; + _GUI_Task_State.NetworkFrame.Width = Image_Width; + _GUI_Task_State.NetworkFrame.Height = Image_Height; + _GUI_Task_State.NetworkFrame.Timestamp = esp_timer_get_time() / 1000; - xSemaphoreGive(_GUITask_State.NetworkFrame.Mutex); + xSemaphoreGive(_GUI_Task_State.NetworkFrame.Mutex); } Server_NotifyClients(); @@ -768,131 +825,135 @@ void Task_GUI(void *p_Parameters) } /* Process the recieved system events */ - EventBits = xEventGroupGetBits(_GUITask_State.EventGroup); + EventBits = xEventGroupGetBits(_GUI_Task_State.EventGroup); if (EventBits & GUI_TASK_STOP_REQUEST) { ESP_LOGD(TAG, "Stop request received"); - _GUITask_State.isRunning = false; + _GUI_Task_State.isRunning = false; - xEventGroupClearBits(_GUITask_State.EventGroup, GUI_TASK_STOP_REQUEST); + xEventGroupClearBits(_GUI_Task_State.EventGroup, GUI_TASK_STOP_REQUEST); break; } else if (EventBits & BATTERY_VOLTAGE_READY) { char Buffer[16]; - snprintf(Buffer, sizeof(Buffer), "%d%%", _GUITask_State.BatteryInfo.Percentage); + snprintf(Buffer, sizeof(Buffer), "%d%%", _GUI_Task_State.BatteryInfo.Percentage); - if (_GUITask_State.BatteryInfo.Percentage == 100) { - snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_FULL " %d%%", _GUITask_State.BatteryInfo.Percentage); + if (_GUI_Task_State.BatteryInfo.Percentage == 100) { + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_FULL " %d%%", _GUI_Task_State.BatteryInfo.Percentage); lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0x00FF00), 0); - } else if (_GUITask_State.BatteryInfo.Percentage >= 75) { - snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_3 " %d%%", _GUITask_State.BatteryInfo.Percentage); + } else if (_GUI_Task_State.BatteryInfo.Percentage >= 75) { + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_3 " %d%%", _GUI_Task_State.BatteryInfo.Percentage); lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0x00FF00), 0); - } else if (_GUITask_State.BatteryInfo.Percentage >= 50) { - snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_2 " %d%%", _GUITask_State.BatteryInfo.Percentage); + } else if (_GUI_Task_State.BatteryInfo.Percentage >= 50) { + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_2 " %d%%", _GUI_Task_State.BatteryInfo.Percentage); lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0xFFFF00), 0); - } else if (_GUITask_State.BatteryInfo.Percentage >= 25) { - snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_1 " %d%%", _GUITask_State.BatteryInfo.Percentage); + } else if (_GUI_Task_State.BatteryInfo.Percentage >= 25) { + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_1 " %d%%", _GUI_Task_State.BatteryInfo.Percentage); lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0xFFFF00), 0); } else { - snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_EMPTY " %d%%", _GUITask_State.BatteryInfo.Percentage); + snprintf(Buffer, sizeof(Buffer), LV_SYMBOL_BATTERY_EMPTY " %d%%", _GUI_Task_State.BatteryInfo.Percentage); lv_obj_set_style_bg_color(ui_Label_Main_Battery_Remaining, lv_color_hex(0xFF0000), 0); } lv_label_set_text(ui_Label_Main_Battery_Remaining, Buffer); - xEventGroupClearBits(_GUITask_State.EventGroup, BATTERY_VOLTAGE_READY); + xEventGroupClearBits(_GUI_Task_State.EventGroup, BATTERY_VOLTAGE_READY); } else if ( EventBits & BATTERY_CHARGING_STATUS_READY) { - xEventGroupClearBits(_GUITask_State.EventGroup, BATTERY_CHARGING_STATUS_READY); + xEventGroupClearBits(_GUI_Task_State.EventGroup, BATTERY_CHARGING_STATUS_READY); } else if (EventBits & WIFI_CONNECTION_STATE_CHANGED) { - if (_GUITask_State.WiFiConnected) { + if (_GUI_Task_State.WiFiConnected) { char Buffer[16]; snprintf(Buffer, sizeof(Buffer), "%lu.%lu.%lu.%lu", - (_GUITask_State.IP_Info.IP >> 0) & 0xFF, - (_GUITask_State.IP_Info.IP >> 8) & 0xFF, - (_GUITask_State.IP_Info.IP >> 16) & 0xFF, - (_GUITask_State.IP_Info.IP >> 24) & 0xFF); + (_GUI_Task_State.IP_Info.IP >> 0) & 0xFF, + (_GUI_Task_State.IP_Info.IP >> 8) & 0xFF, + (_GUI_Task_State.IP_Info.IP >> 16) & 0xFF, + (_GUI_Task_State.IP_Info.IP >> 24) & 0xFF); lv_label_set_text(ui_Label_Info_IP, Buffer); lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0x00FF00), LV_PART_MAIN); - lv_obj_remove_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); + + // TODO: Disable WiFi buttons in the menu + //lv_obj_remove_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); } else { lv_label_set_text(ui_Label_Info_IP, "Not connected"); lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0xFF0000), LV_PART_MAIN); - lv_obj_add_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); + + // TODO: Disable WiFi buttons in the menu + //lv_obj_add_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); } - xEventGroupClearBits(_GUITask_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); + xEventGroupClearBits(_GUI_Task_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); } else if (EventBits & PROVISIONING_STATE_CHANGED) { - if ((_GUITask_State.WiFiConnected == false) && _GUITask_State.ProvisioningActive) { + if ((_GUI_Task_State.WiFiConnected == false) && _GUI_Task_State.ProvisioningActive) { lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0xFF8800), LV_PART_MAIN); } else { lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0xFF0000), LV_PART_MAIN); } - xEventGroupClearBits(_GUITask_State.EventGroup, PROVISIONING_STATE_CHANGED); + xEventGroupClearBits(_GUI_Task_State.EventGroup, PROVISIONING_STATE_CHANGED); } else if (EventBits & SD_CARD_STATE_CHANGED) { - ESP_LOGI(TAG, "SD card state changed: %s", _GUITask_State.CardPresent ? "present" : "removed"); + ESP_LOGI(TAG, "SD card state changed: %s", _GUI_Task_State.CardPresent ? "present" : "removed"); - xEventGroupClearBits(_GUITask_State.EventGroup, SD_CARD_STATE_CHANGED); + xEventGroupClearBits(_GUI_Task_State.EventGroup, SD_CARD_STATE_CHANGED); } else if (EventBits & SD_CARD_MOUNTED) { ESP_LOGI(TAG, "SD card mounted - updating GUI"); - xEventGroupClearBits(_GUITask_State.EventGroup, SD_CARD_MOUNTED); + xEventGroupClearBits(_GUI_Task_State.EventGroup, SD_CARD_MOUNTED); } else if (EventBits & SD_CARD_MOUNT_ERROR) { ESP_LOGE(TAG, "SD card mount failed - keeping card present status"); - xEventGroupClearBits(_GUITask_State.EventGroup, SD_CARD_MOUNT_ERROR); + xEventGroupClearBits(_GUI_Task_State.EventGroup, SD_CARD_MOUNT_ERROR); } else if (EventBits & LEPTON_SPOTMETER_READY) { - xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_SPOTMETER_READY); + xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_SPOTMETER_READY); } else if (EventBits & LEPTON_UPTIME_READY) { char Buffer[32]; uint32_t Uptime; - Uptime = _GUITask_State.LeptonUptime / 1000; + Uptime = _GUI_Task_State.LeptonUptime / 1000; snprintf(Buffer, sizeof(Buffer), "%02lu:%02lu:%02lu", Uptime / 3600, (Uptime % 3600) / 60, Uptime % 60); lv_label_set_text(ui_Label_Info_Lepton_Uptime, Buffer); - xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_UPTIME_READY); + xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_UPTIME_READY); } else if (EventBits & LEPTON_TEMP_READY) { char Buffer[32]; - snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUITask_State.LeptonTemperatures.FPA); + snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUI_Task_State.LeptonTemperatures.FPA); lv_label_set_text(ui_Label_Info_Lepton_FPA, Buffer); - snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUITask_State.LeptonTemperatures.AUX); + snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUI_Task_State.LeptonTemperatures.AUX); lv_label_set_text(ui_Label_Info_Lepton_AUX, Buffer); - xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_TEMP_READY); + xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_TEMP_READY); } else if (EventBits & LEPTON_PIXEL_TEMPERATURE_READY) { char Buffer[16]; - snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUITask_State.SpotTemperature); + snprintf(Buffer, sizeof(Buffer), "%.2f °C", _GUI_Task_State.SpotTemperature); lv_label_set_text(ui_Label_Main_Thermal_PixelTemperature, Buffer); - xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); + xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); } else if (EventBits & LEPTON_SCENE_STATISTICS_READY) { char Buffer[16]; - float temp_max_celsius = _GUITask_State.ROIResult.Max; + float temp_max_celsius = _GUI_Task_State.ROIResult.Max; snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_max_celsius); lv_label_set_text(ui_Label_Main_Thermal_Scene_Max, Buffer); - float temp_min_celsius = _GUITask_State.ROIResult.Min; + float temp_min_celsius = _GUI_Task_State.ROIResult.Min; snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_min_celsius); lv_label_set_text(ui_Label_Main_Thermal_Scene_Min, Buffer); - float temp_mean_celsius = _GUITask_State.ROIResult.Mean ; + float temp_mean_celsius = _GUI_Task_State.ROIResult.Mean ; snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_mean_celsius); lv_label_set_text(ui_Label_Main_Thermal_Scene_Mean, Buffer); - xEventGroupClearBits(_GUITask_State.EventGroup, LEPTON_SCENE_STATISTICS_READY); + xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_SCENE_STATISTICS_READY); } - _lock_acquire(&_GUITask_State.LVGL_API_Lock); + _lock_acquire(&_GUI_Task_State.LVGL_API_Lock); uint32_t time_till_next = lv_timer_handler(); - _lock_release(&_GUITask_State.LVGL_API_Lock); + _lock_release(&_GUI_Task_State.LVGL_API_Lock); uint32_t delay_ms = (time_till_next > 0) ? time_till_next : 10; esp_task_wdt_reset(); @@ -900,7 +961,7 @@ void Task_GUI(void *p_Parameters) vTaskDelay(delay_ms / portTICK_PERIOD_MS); } - _GUITask_State.TaskHandle = NULL; + _GUI_Task_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); vTaskDelete(NULL); @@ -908,147 +969,153 @@ void Task_GUI(void *p_Parameters) esp_err_t GUI_Task_Init(void) { - if (_GUITask_State.isInitialized) { + if (_GUI_Task_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; } - ESP_ERROR_CHECK(GUI_Helper_Init(&_GUITask_State, Touch_LVGL_ReadCallback)); + ESP_ERROR_CHECK(GUI_Helper_Init(&_GUI_Task_State, Touch_LVGL_ReadCallback)); ui_init(); - _GUITask_State.ThermalCanvasBuffer = (uint8_t *)heap_caps_malloc(240 * 180 * 2, MALLOC_CAP_SPIRAM); - _GUITask_State.GradientCanvasBuffer = (uint8_t *)heap_caps_malloc(20 * 180 * 2, MALLOC_CAP_SPIRAM); - _GUITask_State.NetworkRGBBuffer = (uint8_t *)heap_caps_malloc(240 * 180 * 3, MALLOC_CAP_SPIRAM); + _GUI_Task_State.ThermalCanvasBuffer = static_cast(heap_caps_malloc(240 * 180 * 2, MALLOC_CAP_SPIRAM)); + _GUI_Task_State.GradientCanvasBuffer = static_cast(heap_caps_malloc(20 * 180 * 2, MALLOC_CAP_SPIRAM)); + _GUI_Task_State.NetworkRGBBuffer = static_cast(heap_caps_malloc(240 * 180 * 3, MALLOC_CAP_SPIRAM)); - if (_GUITask_State.ThermalCanvasBuffer == NULL) { + if (_GUI_Task_State.ThermalCanvasBuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate thermal canvas buffer!"); return ESP_ERR_NO_MEM; } - if (_GUITask_State.GradientCanvasBuffer == NULL) { + if (_GUI_Task_State.GradientCanvasBuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate gradient canvas buffer!"); - heap_caps_free(_GUITask_State.ThermalCanvasBuffer); + + heap_caps_free(_GUI_Task_State.ThermalCanvasBuffer); return ESP_ERR_NO_MEM; } - if (_GUITask_State.NetworkRGBBuffer == NULL) { + if (_GUI_Task_State.NetworkRGBBuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate network RGB buffer!"); - heap_caps_free(_GUITask_State.ThermalCanvasBuffer); - heap_caps_free(_GUITask_State.GradientCanvasBuffer); + + heap_caps_free(_GUI_Task_State.ThermalCanvasBuffer); + heap_caps_free(_GUI_Task_State.GradientCanvasBuffer); return ESP_ERR_NO_MEM; } + /* Create image save queue and task */ + _GUI_Task_State.ImageSaveQueue = xQueueCreate(1, sizeof(App_Lepton_FrameReady_t)); + if (_GUI_Task_State.ImageSaveQueue == NULL) { + ESP_LOGE(TAG, "Failed to create image save queue!"); + + heap_caps_free(_GUI_Task_State.ThermalCanvasBuffer); + heap_caps_free(_GUI_Task_State.GradientCanvasBuffer); + heap_caps_free(_GUI_Task_State.NetworkRGBBuffer); + + return ESP_ERR_NO_MEM; + } + + BaseType_t Result = xTaskCreatePinnedToCore( + Task_ImageSave, + "Task_ImgSave", + 8192, + NULL, + CONFIG_GUI_TASK_PRIO - 1, /* Lower priority than GUI */ + &_GUI_Task_State.ImageSaveTaskHandle, + 1 + ); + + if (Result != pdPASS) { + ESP_LOGE(TAG, "Failed to create image save task!"); + + vQueueDelete(_GUI_Task_State.ImageSaveQueue); + + heap_caps_free(_GUI_Task_State.ThermalCanvasBuffer); + heap_caps_free(_GUI_Task_State.GradientCanvasBuffer); + heap_caps_free(_GUI_Task_State.NetworkRGBBuffer); + + _GUI_Task_State.ImageSaveQueue = NULL; + _GUI_Task_State.ThermalCanvasBuffer = NULL; + _GUI_Task_State.GradientCanvasBuffer = NULL; + _GUI_Task_State.NetworkRGBBuffer = NULL; + + return ESP_FAIL; + } + /* Initialize buffers with black pixels (RGB565 = 0x0000) */ - memset(_GUITask_State.ThermalCanvasBuffer, 0x00, 240 * 180 * 2); - memset(_GUITask_State.GradientCanvasBuffer, 0x00, 20 * 180 * 2); + memset(_GUI_Task_State.ThermalCanvasBuffer, 0x00, 240 * 180 * 2); + memset(_GUI_Task_State.GradientCanvasBuffer, 0x00, 20 * 180 * 2); /* Now configure the image descriptors with allocated buffers */ - _GUITask_State.ThermalImageDescriptor.header.cf = LV_COLOR_FORMAT_RGB565; - _GUITask_State.ThermalImageDescriptor.header.w = 240; - _GUITask_State.ThermalImageDescriptor.header.h = 180; - _GUITask_State.ThermalImageDescriptor.data = _GUITask_State.ThermalCanvasBuffer; - _GUITask_State.ThermalImageDescriptor.data_size = 240 * 180 * 2; - - _GUITask_State.GradientImageDescriptor.header.cf = LV_COLOR_FORMAT_RGB565; - _GUITask_State.GradientImageDescriptor.header.w = 20; - _GUITask_State.GradientImageDescriptor.header.h = 180; - _GUITask_State.GradientImageDescriptor.data = _GUITask_State.GradientCanvasBuffer; - _GUITask_State.GradientImageDescriptor.data_size = 20 * 180 * 2; + _GUI_Task_State.ThermalImageDescriptor.header.cf = LV_COLOR_FORMAT_RGB565; + _GUI_Task_State.ThermalImageDescriptor.header.w = 240; + _GUI_Task_State.ThermalImageDescriptor.header.h = 180; + _GUI_Task_State.ThermalImageDescriptor.data = _GUI_Task_State.ThermalCanvasBuffer; + _GUI_Task_State.ThermalImageDescriptor.data_size = 240 * 180 * 2; + + _GUI_Task_State.GradientImageDescriptor.header.cf = LV_COLOR_FORMAT_RGB565; + _GUI_Task_State.GradientImageDescriptor.header.w = 20; + _GUI_Task_State.GradientImageDescriptor.header.h = 180; + _GUI_Task_State.GradientImageDescriptor.data = _GUI_Task_State.GradientCanvasBuffer; + _GUI_Task_State.GradientImageDescriptor.data_size = 20 * 180 * 2; UI_Canvas_AddTempGradient(); /* Set the images */ - lv_img_set_src(ui_Image_Thermal, &_GUITask_State.ThermalImageDescriptor); - lv_img_set_src(ui_Image_Gradient, &_GUITask_State.GradientImageDescriptor); - -#ifdef CONFIG_GUI_TOUCH_DEBUG - /* Create touch debug visualization overlay on main screen */ - _GUITask_State.TouchDebugOverlay = lv_obj_create(ui_Main); - lv_obj_set_size(_GUITask_State.TouchDebugOverlay, CONFIG_GUI_WIDTH, CONFIG_GUI_HEIGHT); - lv_obj_set_pos(_GUITask_State.TouchDebugOverlay, 0, 0); - lv_obj_set_style_bg_opa(_GUITask_State.TouchDebugOverlay, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_width(_GUITask_State.TouchDebugOverlay, 0, 0); - lv_obj_remove_flag(_GUITask_State.TouchDebugOverlay, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_add_flag(_GUITask_State.TouchDebugOverlay, LV_OBJ_FLAG_FLOATING); - lv_obj_add_flag(_GUITask_State.TouchDebugOverlay, LV_OBJ_FLAG_CLICKABLE); - lv_obj_move_to_index(_GUITask_State.TouchDebugOverlay, -1); /* Move to top layer */ - - /* Create touch indicator circle */ - _GUITask_State.TouchDebugCircle = lv_obj_create(_GUITask_State.TouchDebugOverlay); - lv_obj_set_size(_GUITask_State.TouchDebugCircle, 20, 20); - lv_obj_set_style_radius(_GUITask_State.TouchDebugCircle, LV_RADIUS_CIRCLE, 0); - lv_obj_set_style_bg_color(_GUITask_State.TouchDebugCircle, lv_color_hex(0xFF0000), 0); - lv_obj_set_style_bg_opa(_GUITask_State.TouchDebugCircle, LV_OPA_70, 0); - lv_obj_set_style_border_color(_GUITask_State.TouchDebugCircle, lv_color_hex(0xFFFFFF), 0); - lv_obj_set_style_border_width(_GUITask_State.TouchDebugCircle, 2, 0); - lv_obj_add_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_HIDDEN); - lv_obj_remove_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_CLICKABLE); - lv_obj_remove_flag(_GUITask_State.TouchDebugCircle, LV_OBJ_FLAG_SCROLLABLE); - - /* Create coordinate label */ - _GUITask_State.TouchDebugLabel = lv_label_create(_GUITask_State.TouchDebugOverlay); - lv_obj_set_pos(_GUITask_State.TouchDebugLabel, 5, 5); - lv_label_set_text(_GUITask_State.TouchDebugLabel, "Touch Debug"); - lv_obj_set_style_text_color(_GUITask_State.TouchDebugLabel, lv_color_hex(0xFFFFFF), 0); - lv_obj_set_style_bg_color(_GUITask_State.TouchDebugLabel, lv_color_hex(0x000000), 0); - lv_obj_set_style_bg_opa(_GUITask_State.TouchDebugLabel, LV_OPA_70, 0); - lv_obj_set_style_pad_all(_GUITask_State.TouchDebugLabel, 3, 0); - lv_obj_add_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); - lv_obj_remove_flag(_GUITask_State.TouchDebugLabel, LV_OBJ_FLAG_CLICKABLE); - - ESP_LOGD(TAG, "Touch debug visualization enabled on ui_Main screen"); -#endif + lv_img_set_src(ui_Image_Thermal, &_GUI_Task_State.ThermalImageDescriptor); + lv_img_set_src(ui_Image_Gradient, &_GUI_Task_State.GradientImageDescriptor); /* Initialize network frame for server streaming */ - _GUITask_State.NetworkFrame.Mutex = xSemaphoreCreateMutex(); - if (_GUITask_State.NetworkFrame.Mutex == NULL) { + _GUI_Task_State.NetworkFrame.Mutex = xSemaphoreCreateMutex(); + if (_GUI_Task_State.NetworkFrame.Mutex == NULL) { ESP_LOGE(TAG, "Failed to create NetworkFrame mutex!"); - heap_caps_free(_GUITask_State.ThermalCanvasBuffer); - heap_caps_free(_GUITask_State.GradientCanvasBuffer); - heap_caps_free(_GUITask_State.NetworkRGBBuffer); + + heap_caps_free(_GUI_Task_State.ThermalCanvasBuffer); + heap_caps_free(_GUI_Task_State.GradientCanvasBuffer); + heap_caps_free(_GUI_Task_State.NetworkRGBBuffer); return ESP_ERR_NO_MEM; } /* Use the event loop to receive control signals from other tasks */ + esp_event_handler_register(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler, NULL); esp_event_handler_register(DEVICE_EVENTS, ESP_EVENT_ANY_ID, on_Devices_Event_Handler, NULL); esp_event_handler_register(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler, NULL); esp_event_handler_register(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler, NULL); esp_event_handler_register(TIME_EVENTS, ESP_EVENT_ANY_ID, on_Time_Event_Handler, NULL); - esp_event_handler_register(SD_EVENTS, ESP_EVENT_ANY_ID, on_SD_Event_Handler, NULL); - _GUITask_State.isInitialized = true; + _GUI_Task_State.SaveNextFrameRequested = false; + _GUI_Task_State.isInitialized = true; return ESP_OK; } void GUI_Task_Deinit(void) { - if (_GUITask_State.isInitialized == false) { + if (_GUI_Task_State.isInitialized == false) { return; } + esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); esp_event_handler_unregister(DEVICE_EVENTS, ESP_EVENT_ANY_ID, on_Devices_Event_Handler); esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); esp_event_handler_unregister(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler); esp_event_handler_unregister(TIME_EVENTS, ESP_EVENT_ANY_ID, on_Time_Event_Handler); - esp_event_handler_unregister(SD_EVENTS, ESP_EVENT_ANY_ID, on_SD_Event_Handler); ui_destroy(); - GUI_Helper_Deinit(&_GUITask_State); + GUI_Helper_Deinit(&_GUI_Task_State); - if (_GUITask_State.NetworkFrame.Mutex != NULL) { - vSemaphoreDelete(_GUITask_State.NetworkFrame.Mutex); - _GUITask_State.NetworkFrame.Mutex = NULL; + if (_GUI_Task_State.NetworkFrame.Mutex != NULL) { + vSemaphoreDelete(_GUI_Task_State.NetworkFrame.Mutex); + _GUI_Task_State.NetworkFrame.Mutex = NULL; } - _GUITask_State.Display = NULL; - _GUITask_State.isInitialized = false; + _GUI_Task_State.Display = NULL; + _GUI_Task_State.isInitialized = false; } esp_err_t GUI_Task_Start(App_Context_t *p_AppContext) @@ -1057,14 +1124,15 @@ esp_err_t GUI_Task_Start(App_Context_t *p_AppContext) if (p_AppContext == NULL) { return ESP_ERR_INVALID_ARG; - } else if (_GUITask_State.isInitialized == false) { + } else if (_GUI_Task_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_GUITask_State.isRunning) { + } else if (_GUI_Task_State.isRunning) { ESP_LOGW(TAG, "Task already running"); + return ESP_OK; } - _GUITask_State.isRunning = true; + _GUI_Task_State.isRunning = true; ESP_LOGD(TAG, "Starting GUI Task"); @@ -1074,12 +1142,13 @@ esp_err_t GUI_Task_Start(App_Context_t *p_AppContext) CONFIG_GUI_TASK_STACKSIZE, p_AppContext, CONFIG_GUI_TASK_PRIO, - &_GUITask_State.TaskHandle, + &_GUI_Task_State.TaskHandle, CONFIG_GUI_TASK_CORE ); if (ret != pdPASS) { ESP_LOGE(TAG, "Failed to create GUI task: %d!", ret); + return ESP_ERR_NO_MEM; } @@ -1088,16 +1157,32 @@ esp_err_t GUI_Task_Start(App_Context_t *p_AppContext) esp_err_t GUI_Task_Stop(void) { - if (_GUITask_State.isRunning == false) { + if (_GUI_Task_State.isRunning == false) { return ESP_OK; } - xEventGroupSetBits(_GUITask_State.EventGroup, GUI_TASK_STOP_REQUEST); + xEventGroupSetBits(_GUI_Task_State.EventGroup, GUI_TASK_STOP_REQUEST); return ESP_OK; } -bool GUI_Task_isRunning(void) +bool GUI_Task_IsRunning(void) +{ + return _GUI_Task_State.isRunning; +} + +esp_err_t GUI_SaveThermalImage(void) { - return _GUITask_State.isRunning; + /* Check if filesystem is locked (USB active) */ + if (MemoryManager_IsFilesystemLocked()) { + ESP_LOGW(TAG, "Cannot save image - USB mode active!"); + + return ESP_ERR_INVALID_STATE; + } + + /* Set flag to trigger save on next frame update */ + _GUI_Task_State.SaveNextFrameRequested = true; + ESP_LOGI(TAG, "Image save requested - will capture next frame"); + + return ESP_OK; } \ No newline at end of file diff --git a/main/Application/Tasks/GUI/guiTask.h b/main/Application/Tasks/GUI/guiTask.h index f57dad6..ea9b2b0 100644 --- a/main/Application/Tasks/GUI/guiTask.h +++ b/main/Application/Tasks/GUI/guiTask.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: GUI task implementation. + * File info: GUI task definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,7 +56,7 @@ esp_err_t GUI_Task_Stop(void); /** @brief Check if the GUI task is running. * @return true if running, false otherwise */ -bool GUI_Task_isRunning(void); +bool GUI_Task_IsRunning(void); /** @brief Toggle ROI (Region of Interest) edit mode. * When enabled, shows a draggable rectangle overlay on the thermal image @@ -64,4 +64,14 @@ bool GUI_Task_isRunning(void); */ void GUI_Toggle_ROI_EditMode(void); +/** @brief Request to save the next thermal image to storage as PNG file. + * @note Sets a flag that triggers image save on the next frame update. + * The actual save happens in background task (non-blocking). + * A message box will be displayed upon completion or error. + * Saves the scaled 240x180 display image (not the raw 160x120 frame). + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if filesystem is locked (USB active) + */ +esp_err_t GUI_SaveThermalImage(void); + #endif /* GUI_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/Lepton/leptonTask.cpp b/main/Application/Tasks/Lepton/leptonTask.cpp index b94614d..cc7088f 100644 --- a/main/Application/Tasks/Lepton/leptonTask.cpp +++ b/main/Application/Tasks/Lepton/leptonTask.cpp @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Main lepton task implementation. + * File info: Lepton camera task definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +35,7 @@ #include "lepton.h" #include "leptonTask.h" #include "Application/application.h" +#include "Application/Manager/Devices/devicesManager.h" #define LEPTON_TASK_STOP_REQUEST BIT0 #define LEPTON_TASK_UPDATE_ROI_REQUEST BIT1 @@ -65,11 +66,11 @@ typedef struct { SettingsManager_Setting_t NewSetting; } Lepton_Task_State_t; -static Lepton_Task_State_t _LeptonTask_State; +static Lepton_Task_State_t _Lepton_Task_State; -static const char *TAG = "lepton_task"; +static const char *TAG = "Lepton-Task"; -/** @brief +/** @brief Event handler for the Settings task to receive updates when settings are changed. * @param p_HandlerArgs Handler argument * @param Base Event base * @param ID Event ID @@ -81,13 +82,17 @@ static void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base switch (ID) { case SETTINGS_EVENT_LEPTON_CHANGED: { - memcpy(&_LeptonTask_State.NewSetting, p_Data, sizeof(SettingsManager_Setting_t)); + if (p_Data != NULL) { + memcpy(&_Lepton_Task_State.NewSetting, p_Data, sizeof(SettingsManager_Setting_t)); - ESP_LOGD(TAG, "Lepton settings changed: ID=%d", _LeptonTask_State.NewSetting.ID); - ESP_LOGD(TAG, "Lepton settings changed: Value=%d", _LeptonTask_State.NewSetting.Value); + ESP_LOGD(TAG, "Lepton settings changed: ID=%d", _Lepton_Task_State.NewSetting.ID); + ESP_LOGD(TAG, "Lepton settings changed: Value=%d", _Lepton_Task_State.NewSetting.Value); - if(_LeptonTask_State.NewSetting.ID == SETTINGS_ID_LEPTON_EMISSIVITY) { - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); + if (_Lepton_Task_State.NewSetting.ID == SETTINGS_ID_LEPTON_EMISSIVITY) { + xEventGroupSetBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); + } + } else { + ESP_LOGD(TAG, "Lepton settings changed (no specific setting data provided)"); } break; @@ -95,7 +100,7 @@ static void on_Settings_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base } } -/** @brief +/** @brief Event handler for the GUI task to receive updates when GUI events are triggered (e.g., ROI change requests). * @param p_HandlerArgs Handler argument * @param Base Event base * @param ID Event ID @@ -109,45 +114,54 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int case GUI_EVENT_APP_STARTED: { ESP_LOGD(TAG, "Application started event received"); - _LeptonTask_State.ApplicationStarted = true; + _Lepton_Task_State.ApplicationStarted = true; break; } case GUI_EVENT_REQUEST_ROI: { - memcpy(&_LeptonTask_State.ROI, p_Data, sizeof(App_Settings_ROI_t)); + if (p_Data != NULL) { + memcpy(&_Lepton_Task_State.ROI, p_Data, sizeof(App_Settings_ROI_t)); - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_ROI_REQUEST); + xEventGroupSetBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_ROI_REQUEST); + } else { + ESP_LOGE(TAG, "GUI_EVENT_REQUEST_ROI received with NULL data"); + } break; } case GUI_EVENT_REQUEST_FPA_AUX_TEMP: { - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_TEMP_REQUEST); + xEventGroupSetBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_TEMP_REQUEST); break; } case GUI_EVENT_REQUEST_UPTIME: { - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_UPTIME_REQUEST); + xEventGroupSetBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_UPTIME_REQUEST); break; } case GUI_EVENT_REQUEST_PIXEL_TEMPERATURE: { - _LeptonTask_State.ScreenPosition = *(App_GUI_Screenposition_t *)p_Data; + if (p_Data != NULL) { + _Lepton_Task_State.ScreenPosition = *(App_GUI_Screenposition_t *)p_Data; - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); + xEventGroupSetBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); + } else { + ESP_LOGE(TAG, "GUI_EVENT_REQUEST_PIXEL_TEMPERATURE received with NULL data"); + } break; } case GUI_EVENT_REQUEST_SPOTMETER: { - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SPOTMETER); + xEventGroupSetBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_SPOTMETER); break; } case GUI_EVENT_REQUEST_SCENE_STATISTICS: { - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SCENE_STATISTICS); + xEventGroupSetBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_SCENE_STATISTICS); break; } default: { ESP_LOGW(TAG, "Unhandled GUI event ID: %d", ID); + break; } } @@ -164,7 +178,7 @@ static void Lepton_LoadSettings(void) ESP_LOGI(TAG, "Loading Lepton settings..."); ESP_LOGI(TAG, "Emissivity: %d", LeptonSettings.CurrentEmissivity); - Lepton_SetEmissivity(&_LeptonTask_State.Lepton, static_cast(LeptonSettings.CurrentEmissivity)); + Lepton_SetEmissivity(&_Lepton_Task_State.Lepton, static_cast(LeptonSettings.CurrentEmissivity)); } /** @brief Lepton camera task main loop. @@ -177,40 +191,40 @@ static void Task_Lepton(void *p_Parameters) App_Lepton_Device_t DeviceInfo; esp_task_wdt_add(NULL); - App_Context = reinterpret_cast(p_Parameters); + App_Context = static_cast(p_Parameters); ESP_LOGD(TAG, "Lepton task started on core %d", xPortGetCoreID()); - /* Initialize Lepton (this creates I2C device handle) before framebuffer allocation */ - Lepton_Error = Lepton_Init(&_LeptonTask_State.Lepton, &_LeptonTask_State.LeptonConf); + Lepton_Error = Lepton_Init(&_Lepton_Task_State.Lepton, &_Lepton_Task_State.LeptonConf); if (Lepton_Error != LEPTON_ERR_OK) { ESP_LOGE(TAG, "Lepton initialization failed with error: %d!", Lepton_Error); - esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); + esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); esp_task_wdt_delete(NULL); + vTaskDelete(NULL); } /* Format serial number as readable string: XXXX-XXXX-XXXX-XXXX */ snprintf(DeviceInfo.SerialNumber, sizeof(DeviceInfo.SerialNumber), "%02X%02X-%02X%02X-%02X%02X-%02X%02X", - _LeptonTask_State.Lepton.SerialNumber[0], _LeptonTask_State.Lepton.SerialNumber[1], - _LeptonTask_State.Lepton.SerialNumber[2], _LeptonTask_State.Lepton.SerialNumber[3], - _LeptonTask_State.Lepton.SerialNumber[4], _LeptonTask_State.Lepton.SerialNumber[5], - _LeptonTask_State.Lepton.SerialNumber[6], _LeptonTask_State.Lepton.SerialNumber[7]); - memcpy(DeviceInfo.PartNumber, _LeptonTask_State.Lepton.PartNumber, sizeof(DeviceInfo.PartNumber)); + _Lepton_Task_State.Lepton.SerialNumber[0], _Lepton_Task_State.Lepton.SerialNumber[1], + _Lepton_Task_State.Lepton.SerialNumber[2], _Lepton_Task_State.Lepton.SerialNumber[3], + _Lepton_Task_State.Lepton.SerialNumber[4], _Lepton_Task_State.Lepton.SerialNumber[5], + _Lepton_Task_State.Lepton.SerialNumber[6], _Lepton_Task_State.Lepton.SerialNumber[7]); + memcpy(DeviceInfo.PartNumber, _Lepton_Task_State.Lepton.PartNumber, sizeof(DeviceInfo.PartNumber)); snprintf(DeviceInfo.SoftwareRevision.GPP_Revision, sizeof(DeviceInfo.SoftwareRevision.GPP_Revision), "%u.%u.%u", - _LeptonTask_State.Lepton.SoftwareVersion.gpp_major, - _LeptonTask_State.Lepton.SoftwareVersion.gpp_minor, - _LeptonTask_State.Lepton.SoftwareVersion.gpp_build); + _Lepton_Task_State.Lepton.SoftwareVersion.gpp_major, + _Lepton_Task_State.Lepton.SoftwareVersion.gpp_minor, + _Lepton_Task_State.Lepton.SoftwareVersion.gpp_build); snprintf(DeviceInfo.SoftwareRevision.DSP_Revision, sizeof(DeviceInfo.SoftwareRevision.DSP_Revision), "%u.%u.%u", - _LeptonTask_State.Lepton.SoftwareVersion.dsp_major, - _LeptonTask_State.Lepton.SoftwareVersion.dsp_minor, - _LeptonTask_State.Lepton.SoftwareVersion.dsp_build); + _Lepton_Task_State.Lepton.SoftwareVersion.dsp_major, + _Lepton_Task_State.Lepton.SoftwareVersion.dsp_minor, + _Lepton_Task_State.Lepton.SoftwareVersion.dsp_build); ESP_LOGD(TAG, " Part number: %s", DeviceInfo.PartNumber); ESP_LOGD(TAG, " Serial number: %s", DeviceInfo.SerialNumber); @@ -219,13 +233,13 @@ static void Task_Lepton(void *p_Parameters) esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_READY, &DeviceInfo, sizeof(App_Lepton_Device_t), portMAX_DELAY); - while (_LeptonTask_State.ApplicationStarted == false) { + while (_Lepton_Task_State.ApplicationStarted == false) { esp_task_wdt_reset(); vTaskDelay(100 / portTICK_PERIOD_MS); } Lepton_FluxLinearParams_t FluxParams; - Lepton_GetFluxLinearParameters(&_LeptonTask_State.Lepton, &FluxParams); + Lepton_GetFluxLinearParameters(&_Lepton_Task_State.Lepton, &FluxParams); ESP_LOGI(TAG, "Flux Linear Parameters - Scene Emissivity: %u, TBkgK: %u, TauWindow: %u, TWindowK: %u, TauAtm: %u, TAtmK: %u, ReflWindow: %u, TReflK: %u", FluxParams.SceneEmissivity, @@ -241,13 +255,13 @@ static void Task_Lepton(void *p_Parameters) Lepton_LoadSettings(); - if (Lepton_StartCapture(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrameQueue) != LEPTON_ERR_OK) { + if (Lepton_StartCapture(&_Lepton_Task_State.Lepton, _Lepton_Task_State.RawFrameQueue) != LEPTON_ERR_OK) { ESP_LOGE(TAG, "Can not start image capturing!"); esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_CAMERA_ERROR, NULL, 0, portMAX_DELAY); /* Critical error - cannot continue without capture task */ - _LeptonTask_State.isRunning = false; - _LeptonTask_State.TaskHandle = NULL; + _Lepton_Task_State.isRunning = false; + _Lepton_Task_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); vTaskDelete(NULL); @@ -255,22 +269,22 @@ static void Task_Lepton(void *p_Parameters) return; } - while (_LeptonTask_State.isRunning) { + while (_Lepton_Task_State.isRunning) { EventBits_t EventBits; esp_task_wdt_reset(); /* Wait for a new raw frame with longer timeout to avoid busy waiting */ - if (xQueueReceive(_LeptonTask_State.RawFrameQueue, &_LeptonTask_State.RawFrame, 500 / portTICK_PERIOD_MS) == pdTRUE) { + if (xQueueReceive(_Lepton_Task_State.RawFrameQueue, &_Lepton_Task_State.RawFrame, 500 / portTICK_PERIOD_MS) == pdTRUE) { uint8_t WriteBufferIdx; uint8_t *WriteBuffer; - Lepton_Telemetry_t Telemetry; - Lepton_VideoFormat_t VideoFormat; int16_t Min = 0; int16_t Max = 0; + Lepton_Telemetry_t Telemetry; + Lepton_VideoFormat_t VideoFormat; - if (_LeptonTask_State.RawFrame.Telemetry_Buffer != NULL) { - memcpy(&Telemetry, _LeptonTask_State.RawFrame.Telemetry_Buffer, sizeof(Lepton_Telemetry_t)); + if (_Lepton_Task_State.RawFrame.Telemetry_Buffer != NULL) { + memcpy(&Telemetry, _Lepton_Task_State.RawFrame.Telemetry_Buffer, sizeof(Lepton_Telemetry_t)); ESP_LOGD(TAG, "Telemetry - FrameCounter: %u, FPA_Temp: %uK, Housing_Temp: %uK", Telemetry.FrameCounter, Telemetry.FPA_Temp, @@ -280,47 +294,51 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGD(TAG, "Processing frame..."); /* Determine which buffer to write to (ping-pong) */ - if (xSemaphoreTake(_LeptonTask_State.BufferMutex, 100 / portTICK_PERIOD_MS) == pdTRUE) { + if (xSemaphoreTake(_Lepton_Task_State.BufferMutex, 100 / portTICK_PERIOD_MS) == pdTRUE) { /* Find a buffer that's not currently being read */ - WriteBufferIdx = (_LeptonTask_State.CurrentReadBuffer + 1) % 2; - WriteBuffer = _LeptonTask_State.RGB_Buffer[WriteBufferIdx]; - xSemaphoreGive(_LeptonTask_State.BufferMutex); + WriteBufferIdx = (_Lepton_Task_State.CurrentReadBuffer + 1) % 2; + WriteBuffer = _Lepton_Task_State.RGB_Buffer[WriteBufferIdx]; + xSemaphoreGive(_Lepton_Task_State.BufferMutex); } else { ESP_LOGW(TAG, "Failed to acquire mutex for buffer selection!"); + continue; } /* Process frame based on video format */ - Lepton_GetVideoFormat(&_LeptonTask_State.Lepton, &VideoFormat); + Lepton_GetVideoFormat(&_Lepton_Task_State.Lepton, &VideoFormat); if (VideoFormat == LEPTON_FORMAT_RGB888) { /* RGB888: Data is already in RGB format, just copy it */ - size_t ImageSize = _LeptonTask_State.RawFrame.Width * _LeptonTask_State.RawFrame.Height * - _LeptonTask_State.RawFrame.BytesPerPixel; - memcpy(WriteBuffer, _LeptonTask_State.RawFrame.Image_Buffer, ImageSize); - ESP_LOGD(TAG, "Copied RGB888 frame: %ux%u (%u bytes)", _LeptonTask_State.RawFrame.Width, - _LeptonTask_State.RawFrame.Height, static_cast(ImageSize)); + size_t ImageSize = _Lepton_Task_State.RawFrame.Width * _Lepton_Task_State.RawFrame.Height * + _Lepton_Task_State.RawFrame.BytesPerPixel; + + memcpy(WriteBuffer, _Lepton_Task_State.RawFrame.Image_Buffer, ImageSize); + + ESP_LOGD(TAG, "Copied RGB888 frame: %ux%u (%u bytes)", _Lepton_Task_State.RawFrame.Width, + _Lepton_Task_State.RawFrame.Height, static_cast(ImageSize)); } else { /* RAW14: Convert to RGB */ - Lepton_Raw14ToRGB(&_LeptonTask_State.Lepton, _LeptonTask_State.RawFrame.Image_Buffer, WriteBuffer, &Min, &Max, - _LeptonTask_State.RawFrame.Width, - _LeptonTask_State.RawFrame.Height); + Lepton_Raw14ToRGB(&_Lepton_Task_State.Lepton, _Lepton_Task_State.RawFrame.Image_Buffer, WriteBuffer, &Min, &Max, + _Lepton_Task_State.RawFrame.Width, + _Lepton_Task_State.RawFrame.Height); } /* Mark buffer as ready and update read buffer index */ - if (xSemaphoreTake(_LeptonTask_State.BufferMutex, 100 / portTICK_PERIOD_MS) == pdTRUE) { - _LeptonTask_State.CurrentReadBuffer = WriteBufferIdx; - xSemaphoreGive(_LeptonTask_State.BufferMutex); + if (xSemaphoreTake(_Lepton_Task_State.BufferMutex, 100 / portTICK_PERIOD_MS) == pdTRUE) { + _Lepton_Task_State.CurrentReadBuffer = WriteBufferIdx; + xSemaphoreGive(_Lepton_Task_State.BufferMutex); } else { ESP_LOGW(TAG, "Failed to acquire mutex for buffer ready!"); + continue; } /* Send frame notification to network task */ App_Lepton_FrameReady_t FrameEvent = { .Buffer = WriteBuffer, - .Width = _LeptonTask_State.RawFrame.Width, - .Height = _LeptonTask_State.RawFrame.Height, + .Width = _Lepton_Task_State.RawFrame.Width, + .Height = _Lepton_Task_State.RawFrame.Height, .Channels = 3, .Min = Min, .Max = Max @@ -330,82 +348,84 @@ static void Task_Lepton(void *p_Parameters) xQueueOverwrite(App_Context->Lepton_FrameEventQueue, &FrameEvent); ESP_LOGD(TAG, "Frame sent to queue successfully"); } else { - /* Timeout waiting for frame */ ESP_LOGW(TAG, "No raw frame received from VoSPI"); } - EventBits = xEventGroupGetBits(_LeptonTask_State.EventGroup); + EventBits = xEventGroupGetBits(_Lepton_Task_State.EventGroup); if (EventBits & LEPTON_TASK_UPDATE_ROI_REQUEST) { Lepton_ROI_t ROI; Lepton_Error_t Error; - ROI.Start_Col = _LeptonTask_State.ROI.x; - ROI.Start_Row = _LeptonTask_State.ROI.y; - ROI.End_Col = _LeptonTask_State.ROI.x + _LeptonTask_State.ROI.w - 1; - ROI.End_Row = _LeptonTask_State.ROI.y + _LeptonTask_State.ROI.h - 1; + ROI.Start_Col = _Lepton_Task_State.ROI.x; + ROI.Start_Row = _Lepton_Task_State.ROI.y; + ROI.End_Col = _Lepton_Task_State.ROI.x + _Lepton_Task_State.ROI.w - 1; + ROI.End_Row = _Lepton_Task_State.ROI.y + _Lepton_Task_State.ROI.h - 1; - switch (_LeptonTask_State.ROI.Type) { + switch (_Lepton_Task_State.ROI.Type) { case ROI_TYPE_SPOTMETER: { - Error = Lepton_SetSpotmeterROI(&_LeptonTask_State.Lepton, &ROI); + Error = Lepton_SetSpotmeterROI(&_Lepton_Task_State.Lepton, &ROI); + break; } case ROI_TYPE_SCENE: { - Error = Lepton_SetSceneROI(&_LeptonTask_State.Lepton, &ROI); + Error = Lepton_SetSceneROI(&_Lepton_Task_State.Lepton, &ROI); + break; } case ROI_TYPE_AGC: { - Error = Lepton_SetAGCROI(&_LeptonTask_State.Lepton, &ROI); + Error = Lepton_SetAGCROI(&_Lepton_Task_State.Lepton, &ROI); + break; } case ROI_TYPE_VIDEO_FOCUS: { - Error = Lepton_SetVideoFocusROI(&_LeptonTask_State.Lepton, &ROI); + Error = Lepton_SetVideoFocusROI(&_Lepton_Task_State.Lepton, &ROI); + break; } default: { - ESP_LOGW(TAG, "Invalid ROI type in GUI event: %d", _LeptonTask_State.ROI.Type); + ESP_LOGW(TAG, "Invalid ROI type in GUI event: %d", _Lepton_Task_State.ROI.Type); + return; } } if (Error == LEPTON_ERR_OK) { ESP_LOGD(TAG, "New Lepton ROI (Type %d) - Start_Col: %u, Start_Row: %u, End_Col: %u, End_Row: %u", - _LeptonTask_State.ROI.Type, + _Lepton_Task_State.ROI.Type, ROI.Start_Col, ROI.Start_Row, ROI.End_Col, ROI.End_Row); } else { - ESP_LOGE(TAG, "Failed to update Lepton ROI with type %d!", _LeptonTask_State.ROI.Type); + ESP_LOGE(TAG, "Failed to update Lepton ROI with type %d!", _Lepton_Task_State.ROI.Type); } - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_ROI_REQUEST); + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_ROI_REQUEST); } else if (EventBits & LEPTON_TASK_UPDATE_TEMP_REQUEST) { uint16_t FPA_Temp; uint16_t AUX_Temp; App_Lepton_Temperatures_t Temperatures; - Lepton_GetTemperature(&_LeptonTask_State.Lepton, &FPA_Temp, &AUX_Temp); + Lepton_GetTemperature(&_Lepton_Task_State.Lepton, &FPA_Temp, &AUX_Temp); Temperatures.FPA = (static_cast(FPA_Temp) * 0.01f) - 273.0f; Temperatures.AUX = (static_cast(AUX_Temp) * 0.01f) - 273.0f; - esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP, &Temperatures, sizeof(App_Lepton_Temperatures_t), 0); - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_TEMP_REQUEST); + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_TEMP_REQUEST); } else if (EventBits & LEPTON_TASK_UPDATE_UPTIME_REQUEST) { uint32_t Uptime; - Uptime = Lepton_GetUptime(&_LeptonTask_State.Lepton); - + Uptime = Lepton_GetUptime(&_Lepton_Task_State.Lepton); esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_UPTIME, &Uptime, sizeof(uint32_t), 0); - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_UPTIME_REQUEST); + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_UPTIME_REQUEST); } else if (EventBits & LEPTON_TASK_STOP_REQUEST) { ESP_LOGI(TAG, "Stop request received"); - _LeptonTask_State.isRunning = false; + _Lepton_Task_State.isRunning = false; - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_STOP_REQUEST); + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_STOP_REQUEST); break; } else if (EventBits & LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE) { @@ -414,24 +434,27 @@ static void Task_Lepton(void *p_Parameters) float Temperature; Lepton_VideoFormat_t VideoFormat; - Lepton_GetVideoFormat(&_LeptonTask_State.Lepton, &VideoFormat); - if (((_LeptonTask_State.RawFrame.Width == 0) || (_LeptonTask_State.RawFrame.Height == 0)) && + Lepton_GetVideoFormat(&_Lepton_Task_State.Lepton, &VideoFormat); + if (((_Lepton_Task_State.RawFrame.Width == 0) || (_Lepton_Task_State.RawFrame.Height == 0)) && (VideoFormat != LEPTON_FORMAT_RAW14)) { ESP_LOGW(TAG, "Invalid Lepton frame! Cannot get pixel temperature!"); - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); + + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); + continue; } /* Convert the screen position to the Lepton frame coordinates */ - x = (_LeptonTask_State.ScreenPosition.x * _LeptonTask_State.RawFrame.Width) / _LeptonTask_State.ScreenPosition.Width; - y = (_LeptonTask_State.ScreenPosition.y * _LeptonTask_State.RawFrame.Height) / _LeptonTask_State.ScreenPosition.Height; + x = (_Lepton_Task_State.ScreenPosition.x * _Lepton_Task_State.RawFrame.Width) / _Lepton_Task_State.ScreenPosition.Width; + y = (_Lepton_Task_State.ScreenPosition.y * _Lepton_Task_State.RawFrame.Height) / + _Lepton_Task_State.ScreenPosition.Height; - ESP_LOGD(TAG, "Crosshair center in Lepton Frame: (%d,%d), size (%d,%d)", x, y, _LeptonTask_State.RawFrame.Width, - _LeptonTask_State.RawFrame.Height); + ESP_LOGD(TAG, "Crosshair center in Lepton Frame: (%d,%d), size (%d,%d)", x, y, _Lepton_Task_State.RawFrame.Width, + _Lepton_Task_State.RawFrame.Height); - if (_LeptonTask_State.RawFrame.Image_Buffer != NULL) { - if (Lepton_GetPixelTemperature(&_LeptonTask_State.Lepton, - _LeptonTask_State.RawFrame.Image_Buffer[(y * _LeptonTask_State.RawFrame.Width) + x], + if (_Lepton_Task_State.RawFrame.Image_Buffer != NULL) { + if (Lepton_GetPixelTemperature(&_Lepton_Task_State.Lepton, + _Lepton_Task_State.RawFrame.Image_Buffer[(y * _Lepton_Task_State.RawFrame.Width) + x], &Temperature) == LEPTON_ERR_OK) { esp_event_post(LEPTON_EVENTS, LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE, &Temperature, sizeof(float), 0); } else { @@ -441,15 +464,15 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGW(TAG, "Image buffer is NULL, cannot get pixel temperature"); } - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_PIXEL_TEMPERATURE); } else if (EventBits & LEPTON_TASK_UPDATE_SPOTMETER) { Lepton_Spotmeter_t Spotmeter; ESP_LOGD(TAG, "Getting spotmeter - I2C Bus: %p, I2C Dev: %p", - _LeptonTask_State.Lepton.Internal.CCI.I2C_Bus_Handle, - _LeptonTask_State.Lepton.Internal.CCI.I2C_Dev_Handle); + _Lepton_Task_State.Lepton.Internal.CCI.I2C_Bus_Handle, + _Lepton_Task_State.Lepton.Internal.CCI.I2C_Dev_Handle); - if (Lepton_GetSpotmeter(&_LeptonTask_State.Lepton, &Spotmeter) == LEPTON_ERR_OK) { + if (Lepton_GetSpotmeter(&_Lepton_Task_State.Lepton, &Spotmeter) == LEPTON_ERR_OK) { App_Lepton_ROI_Result_t App_Lepton_Spotmeter; ESP_LOGD(TAG, "Spotmeter: Spot=%uK, Min=%uK, Max=%uK", @@ -467,11 +490,11 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGW(TAG, "Failed to read spotmeter!"); } - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SPOTMETER); + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_SPOTMETER); } else if (EventBits & LEPTON_TASK_UPDATE_SCENE_STATISTICS) { Lepton_SceneStatistics_t SceneStats; - if (Lepton_GetSceneStatistics(&_LeptonTask_State.Lepton, &SceneStats) == LEPTON_ERR_OK) { + if (Lepton_GetSceneStatistics(&_Lepton_Task_State.Lepton, &SceneStats) == LEPTON_ERR_OK) { App_Lepton_ROI_Result_t App_Lepton_Scene; App_Lepton_Scene.Min = SceneStats.MinIntensity; @@ -487,25 +510,26 @@ static void Task_Lepton(void *p_Parameters) ESP_LOGW(TAG, "Failed to read scene statistics!"); } - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_SCENE_STATISTICS); + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_SCENE_STATISTICS); } else if (EventBits & LEPTON_TASK_UPDATE_EMISSIVITY) { Lepton_Error_t Error; - Error = Lepton_SetEmissivity(&_LeptonTask_State.Lepton, static_cast(_LeptonTask_State.NewSetting.Value)); + Error = Lepton_SetEmissivity(&_Lepton_Task_State.Lepton, + static_cast(_Lepton_Task_State.NewSetting.Value)); if (Error == LEPTON_ERR_OK) { - ESP_LOGD(TAG, "Updated emissivity to %u", _LeptonTask_State.NewSetting.Value); + ESP_LOGD(TAG, "Updated emissivity to %u", _Lepton_Task_State.NewSetting.Value); } else { - ESP_LOGE(TAG, "Failed to update emissivity to %u!", _LeptonTask_State.NewSetting.Value); + ESP_LOGE(TAG, "Failed to update emissivity to %u!", _Lepton_Task_State.NewSetting.Value); } - xEventGroupClearBits(_LeptonTask_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); + xEventGroupClearBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_UPDATE_EMISSIVITY); } } ESP_LOGD(TAG, "Lepton task shutting down"); - Lepton_Deinit(&_LeptonTask_State.Lepton); + Lepton_Deinit(&_Lepton_Task_State.Lepton); - _LeptonTask_State.TaskHandle = NULL; + _Lepton_Task_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); vTaskDelete(NULL); @@ -513,32 +537,36 @@ static void Task_Lepton(void *p_Parameters) esp_err_t Lepton_Task_Init(void) { - if (_LeptonTask_State.isInitialized) { + if (_Lepton_Task_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); + return ESP_OK; } ESP_LOGD(TAG, "Initializing Lepton Task"); - _LeptonTask_State.CurrentReadBuffer = 0; + _Lepton_Task_State.CurrentReadBuffer = 0; /* Create event group */ - _LeptonTask_State.EventGroup = xEventGroupCreate(); - if (_LeptonTask_State.EventGroup == NULL) { + _Lepton_Task_State.EventGroup = xEventGroupCreate(); + if (_Lepton_Task_State.EventGroup == NULL) { ESP_LOGE(TAG, "Failed to create event group!"); + return ESP_ERR_NO_MEM; } /* Create mutex for buffer synchronization */ - _LeptonTask_State.BufferMutex = xSemaphoreCreateMutex(); - if (_LeptonTask_State.BufferMutex == NULL) { + _Lepton_Task_State.BufferMutex = xSemaphoreCreateMutex(); + if (_Lepton_Task_State.BufferMutex == NULL) { ESP_LOGE(TAG, "Failed to create buffer mutex!"); - vEventGroupDelete(_LeptonTask_State.EventGroup); + + vEventGroupDelete(_Lepton_Task_State.EventGroup); + return ESP_ERR_NO_MEM; } - _LeptonTask_State.LeptonConf = LEPTON_DEFAULT_CONF; - LEPTON_ASSIGN_FUNC(_LeptonTask_State.LeptonConf, NULL, NULL, I2CM_Write, I2CM_Read); - LEPTON_ASSIGN_I2C_HANDLE(_LeptonTask_State.LeptonConf, DevicesManager_GetI2CBusHandle()); + _Lepton_Task_State.LeptonConf = LEPTON_DEFAULT_CONF; + LEPTON_ASSIGN_FUNC(_Lepton_Task_State.LeptonConf, NULL, NULL, I2CM_Write, I2CM_Read); + LEPTON_ASSIGN_I2C_HANDLE(_Lepton_Task_State.LeptonConf, DevicesManager_GetI2CBusHandle()); /* Allocate RGB buffers - both RAW14 and RGB888 use 160x120 resolution * RAW14: 160x120x3 = 57,600 bytes (after conversion to RGB) @@ -546,23 +574,23 @@ esp_err_t Lepton_Task_Init(void) */ size_t RGB_Buffer_Size = 160 * 120 * 3; - _LeptonTask_State.RGB_Buffer[0] = reinterpret_cast(heap_caps_malloc(RGB_Buffer_Size, MALLOC_CAP_SPIRAM)); - _LeptonTask_State.RGB_Buffer[1] = reinterpret_cast(heap_caps_malloc(RGB_Buffer_Size, MALLOC_CAP_SPIRAM)); + _Lepton_Task_State.RGB_Buffer[0] = static_cast(heap_caps_malloc(RGB_Buffer_Size, MALLOC_CAP_SPIRAM)); + _Lepton_Task_State.RGB_Buffer[1] = static_cast(heap_caps_malloc(RGB_Buffer_Size, MALLOC_CAP_SPIRAM)); - if ((_LeptonTask_State.RGB_Buffer[0] == NULL) || (_LeptonTask_State.RGB_Buffer[1] == NULL)) { + if ((_Lepton_Task_State.RGB_Buffer[0] == NULL) || (_Lepton_Task_State.RGB_Buffer[1] == NULL)) { ESP_LOGE(TAG, "Can not allocate RGB buffers!"); - if (_LeptonTask_State.RGB_Buffer[0]) { - heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); + if (_Lepton_Task_State.RGB_Buffer[0]) { + heap_caps_free(_Lepton_Task_State.RGB_Buffer[0]); } - if (_LeptonTask_State.RGB_Buffer[1]) { - heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); + if (_Lepton_Task_State.RGB_Buffer[1]) { + heap_caps_free(_Lepton_Task_State.RGB_Buffer[1]); } - Lepton_Deinit(&_LeptonTask_State.Lepton); - vSemaphoreDelete(_LeptonTask_State.BufferMutex); - vEventGroupDelete(_LeptonTask_State.EventGroup); + Lepton_Deinit(&_Lepton_Task_State.Lepton); + vSemaphoreDelete(_Lepton_Task_State.BufferMutex); + vEventGroupDelete(_Lepton_Task_State.EventGroup); return ESP_ERR_NO_MEM; } @@ -570,15 +598,15 @@ esp_err_t Lepton_Task_Init(void) ESP_LOGD(TAG, "RGB buffers allocated: 2 x %u bytes", static_cast(RGB_Buffer_Size)); /* Create internal queue to receive raw frames from VoSPI capture task */ - _LeptonTask_State.RawFrameQueue = xQueueCreate(1, sizeof(Lepton_FrameBuffer_t)); - if (_LeptonTask_State.RawFrameQueue == NULL) { + _Lepton_Task_State.RawFrameQueue = xQueueCreate(1, sizeof(Lepton_FrameBuffer_t)); + if (_Lepton_Task_State.RawFrameQueue == NULL) { ESP_LOGE(TAG, "Failed to create raw frame queue!"); - heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); - heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); - Lepton_Deinit(&_LeptonTask_State.Lepton); - vSemaphoreDelete(_LeptonTask_State.BufferMutex); - vEventGroupDelete(_LeptonTask_State.EventGroup); + heap_caps_free(_Lepton_Task_State.RGB_Buffer[0]); + heap_caps_free(_Lepton_Task_State.RGB_Buffer[1]); + Lepton_Deinit(&_Lepton_Task_State.Lepton); + vSemaphoreDelete(_Lepton_Task_State.BufferMutex); + vEventGroupDelete(_Lepton_Task_State.EventGroup); return ESP_ERR_NO_MEM; } @@ -589,54 +617,54 @@ esp_err_t Lepton_Task_Init(void) ESP_LOGD(TAG, "Lepton Task initialized"); - _LeptonTask_State.isInitialized = true; + _Lepton_Task_State.isInitialized = true; return ESP_OK; } void Lepton_Task_Deinit(void) { - if (_LeptonTask_State.isInitialized == false) { + if (_Lepton_Task_State.isInitialized == false) { return; } - if (_LeptonTask_State.isRunning) { + if (_Lepton_Task_State.isRunning) { Lepton_Task_Stop(); } ESP_LOGI(TAG, "Deinitializing Lepton Task"); - if (_LeptonTask_State.EventGroup != NULL) { - vEventGroupDelete(_LeptonTask_State.EventGroup); - _LeptonTask_State.EventGroup = NULL; + if (_Lepton_Task_State.EventGroup != NULL) { + vEventGroupDelete(_Lepton_Task_State.EventGroup); + _Lepton_Task_State.EventGroup = NULL; } esp_event_handler_unregister(SETTINGS_EVENTS, ESP_EVENT_ANY_ID, on_Settings_Event_Handler); esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); - Lepton_Deinit(&_LeptonTask_State.Lepton); + Lepton_Deinit(&_Lepton_Task_State.Lepton); - if (_LeptonTask_State.BufferMutex != NULL) { - vSemaphoreDelete(_LeptonTask_State.BufferMutex); - _LeptonTask_State.BufferMutex = NULL; + if (_Lepton_Task_State.BufferMutex != NULL) { + vSemaphoreDelete(_Lepton_Task_State.BufferMutex); + _Lepton_Task_State.BufferMutex = NULL; } - if (_LeptonTask_State.RGB_Buffer[0] != NULL) { - heap_caps_free(_LeptonTask_State.RGB_Buffer[0]); - _LeptonTask_State.RGB_Buffer[0] = NULL; + if (_Lepton_Task_State.RGB_Buffer[0] != NULL) { + heap_caps_free(_Lepton_Task_State.RGB_Buffer[0]); + _Lepton_Task_State.RGB_Buffer[0] = NULL; } - if (_LeptonTask_State.RGB_Buffer[1] != NULL) { - heap_caps_free(_LeptonTask_State.RGB_Buffer[1]); - _LeptonTask_State.RGB_Buffer[1] = NULL; + if (_Lepton_Task_State.RGB_Buffer[1] != NULL) { + heap_caps_free(_Lepton_Task_State.RGB_Buffer[1]); + _Lepton_Task_State.RGB_Buffer[1] = NULL; } - if (_LeptonTask_State.RawFrameQueue != NULL) { - vQueueDelete(_LeptonTask_State.RawFrameQueue); - _LeptonTask_State.RawFrameQueue = NULL; + if (_Lepton_Task_State.RawFrameQueue != NULL) { + vQueueDelete(_Lepton_Task_State.RawFrameQueue); + _Lepton_Task_State.RawFrameQueue = NULL; } - _LeptonTask_State.isInitialized = false; + _Lepton_Task_State.isInitialized = false; } esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext) @@ -645,14 +673,15 @@ esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext) if (p_AppContext == NULL) { return ESP_ERR_INVALID_ARG; - } else if (_LeptonTask_State.isInitialized == false) { + } else if (_Lepton_Task_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_LeptonTask_State.isRunning) { + } else if (_Lepton_Task_State.isRunning) { ESP_LOGW(TAG, "Task already Running"); + return ESP_OK; } - _LeptonTask_State.isRunning = true; + _Lepton_Task_State.isRunning = true; ESP_LOGD(TAG, "Starting Lepton Task"); @@ -662,12 +691,13 @@ esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext) CONFIG_LEPTON_TASK_STACKSIZE, p_AppContext, CONFIG_LEPTON_TASK_PRIO, - &_LeptonTask_State.TaskHandle, + &_Lepton_Task_State.TaskHandle, CONFIG_LEPTON_TASK_CORE ); if (Ret != pdPASS) { ESP_LOGE(TAG, "Failed to create Lepton Task: %d!", Ret); + return ESP_ERR_NO_MEM; } @@ -676,18 +706,18 @@ esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext) esp_err_t Lepton_Task_Stop(void) { - if (_LeptonTask_State.isRunning == false) { + if (_Lepton_Task_State.isRunning == false) { return ESP_OK; } ESP_LOGI(TAG, "Stopping Lepton Task"); - xEventGroupSetBits(_LeptonTask_State.EventGroup, LEPTON_TASK_STOP_REQUEST); + xEventGroupSetBits(_Lepton_Task_State.EventGroup, LEPTON_TASK_STOP_REQUEST); return ESP_OK; } -bool Lepton_Task_isRunning(void) +bool Lepton_Task_IsRunning(void) { - return _LeptonTask_State.isRunning; + return _Lepton_Task_State.isRunning; } \ No newline at end of file diff --git a/main/Application/Tasks/Lepton/leptonTask.h b/main/Application/Tasks/Lepton/leptonTask.h index 791a6f4..a218657 100644 --- a/main/Application/Tasks/Lepton/leptonTask.h +++ b/main/Application/Tasks/Lepton/leptonTask.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Lepton camera task for thermal image processing. + * File info: Lepton camera task definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,31 +30,57 @@ #include #include "Application/application.h" -#include "Application/Manager/Devices/devices.h" -/** @brief Initialize the Lepton task. - * @return ESP_OK on success, error code otherwise +/** @brief Initialize the Lepton camera task. + * Creates FreeRTOS task for Lepton thermal camera frame acquisition. + * Sets up queues, event handlers, and camera interface. + * @note Task priority and stack size defined in task header. + * Call this before Lepton_Task_Start(). + * Requires Lepton camera connected via SPI. + * @return ESP_OK on success + * ESP_ERR_NO_MEM if task or queue creation fails + * ESP_FAIL if Lepton initialization fails */ esp_err_t Lepton_Task_Init(void); -/** @brief Deinitialize the Lepton task. +/** @brief Deinitialize the Lepton camera task. + * Stops the task, deletes queues, and frees all resources. + * Camera is left in its current state. + * @note Task must be stopped before calling this. + * @warning All frame data and queues are lost. */ void Lepton_Task_Deinit(void); -/** @brief Start the Lepton task. +/** @brief Start the Lepton camera task. + * Resumes the FreeRTOS task to begin frame acquisition from the + * Lepton thermal camera. Frames are posted as events. + * @note Frame rate depends on Lepton model (9 Hz typical). + * Posts APP_EVENT_LEPTON_FRAME_READY with frame data. * @param p_AppContext Pointer to the application context - * @return ESP_OK on success, error code otherwise + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_AppContext is NULL + * ESP_ERR_INVALID_STATE if not initialized + * ESP_FAIL if camera start fails */ esp_err_t Lepton_Task_Start(App_Context_t *p_AppContext); -/** @brief Stop the Lepton task - * @return ESP_OK on success, error code otherwise +/** @brief Stop the Lepton camera task. + * Suspends frame acquisition. Camera remains initialized and can + * be restarted with Lepton_Task_Start(). + * @note Frame events stop being posted. + * Camera power remains on (low power mode). + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not running + * ESP_FAIL if stop operation fails */ esp_err_t Lepton_Task_Stop(void); -/** @brief Check if the Lepton task is currently running - * @return true if running, false otherwise +/** @brief Check if the Lepton task is currently running. + * Returns the current task execution status. + * @note Thread-safe. + * @return true if task is running and acquiring frames + * false if task is stopped or not initialized */ -bool Lepton_Task_isRunning(void); +bool Lepton_Task_IsRunning(void); #endif /* LEPTON_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index cc8fd7c..bd16582 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -64,11 +64,11 @@ typedef struct { App_Lepton_ROI_Result_t ROIResult; } Network_Task_State_t; -static Network_Task_State_t _NetworkTask_State; +static Network_Task_State_t _Network_Task_State; -static const char *TAG = "network_task"; +static const char *TAG = "Network-Task"; -/** @brief +/** @brief Event handler for the Lepton event to receive updates when Lepton events are triggered (e.g., new frame ready, camera errors). * @param p_HandlerArgs Handler argument * @param Base Event base * @param ID Event ID @@ -80,16 +80,20 @@ static void on_Lepton_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, switch (ID) { case LEPTON_EVENT_RESPONSE_SPOTMETER: { - memcpy(&_NetworkTask_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); + if (p_Data != NULL) { + memcpy(&_Network_Task_State.ROIResult, p_Data, sizeof(App_Lepton_ROI_Result_t)); - xEventGroupSetBits(_NetworkTask_State.EventGroup, LEPTON_SPOTMETER_READY); + xEventGroupSetBits(_Network_Task_State.EventGroup, LEPTON_SPOTMETER_READY); + } else { + ESP_LOGE(TAG, "LEPTON_EVENT_RESPONSE_SPOTMETER received with NULL data"); + } break; } } } -/** @brief SNTP event handler for task coordination. +/** @brief Event handler for the SNTP events to receive updates when SNTP events are triggered (e.g., time synchronization, timezone changes). * @param p_HandlerArgs Handler argument * @param Base Event base * @param ID Event ID @@ -101,16 +105,16 @@ static void on_SNTP_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, in case SNTP_EVENT_TZ_CHANGED: { ESP_LOGD(TAG, "Timezone set"); - _NetworkTask_State.Timezone = static_cast(p_Data); + _Network_Task_State.Timezone = static_cast(p_Data); - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); + xEventGroupSetBits(_Network_Task_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); break; } case SNTP_EVENT_SNTP_SYNCED: { ESP_LOGD(TAG, "SNTP time synchronized"); - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIME_SYNCED); + xEventGroupSetBits(_Network_Task_State.EventGroup, NETWORK_TASK_SNTP_TIME_SYNCED); break; } @@ -134,14 +138,14 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, ESP_LOGD(TAG, "WiFi credentials updated"); - memcpy(&_NetworkTask_State.SSID, + memcpy(&_Network_Task_State.SSID, Credentials->SSID, - sizeof(_NetworkTask_State.SSID)); - memcpy(&_NetworkTask_State.Password, + sizeof(_Network_Task_State.SSID)); + memcpy(&_Network_Task_State.Password, Credentials->Password, - sizeof(_NetworkTask_State.Password)); + sizeof(_Network_Task_State.Password)); - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); + xEventGroupSetBits(_Network_Task_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); break; } @@ -153,25 +157,25 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, case NETWORK_EVENT_WIFI_DISCONNECTED: { ESP_LOGD(TAG, "WiFi disconnected"); - _NetworkTask_State.State = NETWORK_STATE_DISCONNECTED; - _NetworkTask_State.isConnected = false; + _Network_Task_State.State = NETWORK_STATE_DISCONNECTED; + _Network_Task_State.isConnected = false; - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_DISCONNECTED); + xEventGroupSetBits(_Network_Task_State.EventGroup, NETWORK_TASK_WIFI_DISCONNECTED); break; } case NETWORK_EVENT_WIFI_GOT_IP: { - _NetworkTask_State.State = NETWORK_STATE_CONNECTED; - _NetworkTask_State.isConnected = true; + _Network_Task_State.State = NETWORK_STATE_CONNECTED; + _Network_Task_State.isConnected = true; - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CONNECTED); + xEventGroupSetBits(_Network_Task_State.EventGroup, NETWORK_TASK_WIFI_CONNECTED); break; } case NETWORK_EVENT_PROV_SUCCESS: { ESP_LOGD(TAG, "Provisioning success"); - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); + xEventGroupSetBits(_Network_Task_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); break; } @@ -190,7 +194,7 @@ static void on_Network_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, case NETWORK_EVENT_OPEN_WIFI_REQUEST: { ESP_LOGD(TAG, "Open WiFi request received"); - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); + xEventGroupSetBits(_Network_Task_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); break; } @@ -212,7 +216,7 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int case GUI_EVENT_APP_STARTED: { ESP_LOGD(TAG, "Application started event received"); - _NetworkTask_State.ApplicationStarted = true; + _Network_Task_State.ApplicationStarted = true; break; } @@ -233,7 +237,7 @@ static void Task_Network(void *p_Parameters) ESP_LOGD(TAG, "Network task started on core %d", xPortGetCoreID()); - while (_NetworkTask_State.ApplicationStarted == false) { + while (_Network_Task_State.ApplicationStarted == false) { esp_task_wdt_reset(); vTaskDelay(100 / portTICK_PERIOD_MS); } @@ -247,33 +251,33 @@ static void Task_Network(void *p_Parameters) if (WaitingForWiFiRequest == false) { /* Check if WiFi credentials are available */ - if (strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0) { + if (strlen(_Network_Task_State.AppContext->STA_Config.Credentials.SSID) == 0) { ESP_LOGW(TAG, "No credentials found, starting provisioning"); Provisioning_Start(); - _NetworkTask_State.State = NETWORK_STATE_PROVISIONING; + _Network_Task_State.State = NETWORK_STATE_PROVISIONING; } else { ESP_LOGD(TAG, "Credentials found, connecting to WiFi"); NetworkManager_StartSTA(); } } else { ESP_LOGD(TAG, "Waiting for WiFi open request..."); - _NetworkTask_State.State = NETWORK_STATE_IDLE; + _Network_Task_State.State = NETWORK_STATE_IDLE; } - while (_NetworkTask_State.isRunning) { + while (_Network_Task_State.isRunning) { EventBits_t EventBits; esp_task_wdt_reset(); - EventBits = xEventGroupGetBits(_NetworkTask_State.EventGroup); + EventBits = xEventGroupGetBits(_Network_Task_State.EventGroup); if (EventBits & NETWORK_TASK_STOP_REQUEST) { ESP_LOGD(TAG, "Stop request received"); - _NetworkTask_State.isRunning = false; + _Network_Task_State.isRunning = false; - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_STOP_REQUEST); + xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_STOP_REQUEST); break; } else if (EventBits & NETWORK_TASK_WIFI_CONNECTED) { @@ -281,21 +285,21 @@ static void Task_Network(void *p_Parameters) TimeManager_OnNetworkConnected(); /* Ensure we have valid server config */ - if (_NetworkTask_State.AppContext->Server_Config.HTTP_Server.Port == 0) { + if (_Network_Task_State.AppContext->Server_Config.HTTP_Server.Port == 0) { ESP_LOGW(TAG, "Server config port is 0, using default 8080"); - _NetworkTask_State.AppContext->Server_Config.HTTP_Server.Port = 8080; + _Network_Task_State.AppContext->Server_Config.HTTP_Server.Port = 8080; } - if (NetworkManager_StartServer(&_NetworkTask_State.AppContext->Server_Config) == ESP_OK) { + if (NetworkManager_StartServer(&_Network_Task_State.AppContext->Server_Config) == ESP_OK) { ESP_LOGD(TAG, "HTTP/WebSocket server started on port %d", - _NetworkTask_State.AppContext->Server_Config.HTTP_Server.Port); + _Network_Task_State.AppContext->Server_Config.HTTP_Server.Port); esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SERVER_STARTED, NULL, 0, portMAX_DELAY); } else { ESP_LOGE(TAG, "Failed to start HTTP/WebSocket server"); esp_event_post(NETWORK_EVENTS, NETWORK_EVENT_SERVER_ERROR, NULL, 0, portMAX_DELAY); } - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CONNECTED); + xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_WIFI_CONNECTED); } else if (EventBits & NETWORK_TASK_WIFI_DISCONNECTED) { ESP_LOGD(TAG, "Handling WiFi disconnection"); @@ -303,11 +307,11 @@ static void Task_Network(void *p_Parameters) TimeManager_OnNetworkDisconnected(); /* Only start provisioning if not already active and we have no credentials */ - if ((Provisioning_isActive() == false) && strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0) { + if ((Provisioning_IsActive() == false) && strlen(_Network_Task_State.AppContext->STA_Config.Credentials.SSID) == 0) { Provisioning_Start(); } - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_DISCONNECTED); + xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_WIFI_DISCONNECTED); } else if (EventBits & NETWORK_TASK_PROV_SUCCESS) { ESP_LOGI(TAG, "Provisioning success - stopping provisioning and connecting to WiFi"); @@ -327,7 +331,7 @@ static void Task_Network(void *p_Parameters) ESP_LOGI(TAG, "WiFi STA connection initiated"); - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); + xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_PROV_SUCCESS); } else if (EventBits & NETWORK_TASK_PROV_TIMEOUT) { ESP_LOGD(TAG, "Handling provisioning timeout"); @@ -335,7 +339,7 @@ static void Task_Network(void *p_Parameters) Provisioning_Stop(); esp_task_wdt_reset(); - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); + xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_PROV_TIMEOUT); } else if (EventBits & NETWORK_TASK_SNTP_TIMEZONE_SET) { App_Settings_System_t SystemSettings; @@ -343,25 +347,25 @@ static void Task_Network(void *p_Parameters) SettingsManager_GetSystem(&SystemSettings); - memcpy(&SystemSettings.Timezone, _NetworkTask_State.Timezone, sizeof(SystemSettings.Timezone)); + memcpy(&SystemSettings.Timezone, _Network_Task_State.Timezone, sizeof(SystemSettings.Timezone)); TimeManager_SetTimezone(SystemSettings.Timezone); SettingsManager_UpdateSystem(&SystemSettings); SettingsManager_Save(); - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); + xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_SNTP_TIMEZONE_SET); } else if (EventBits & NETWORK_TASK_OPEN_WIFI_REQUEST) { ESP_LOGD(TAG, "Handling WiFi open request"); /* Start WiFi connection if we were waiting */ if (WaitingForWiFiRequest) { if ((Provisioning_isProvisioned() == false) && - (strlen(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) == 0)) { + (strlen(_Network_Task_State.AppContext->STA_Config.Credentials.SSID) == 0)) { ESP_LOGW(TAG, "No credentials found, starting provisioning"); Provisioning_Start(); - _NetworkTask_State.State = NETWORK_STATE_PROVISIONING; + _Network_Task_State.State = NETWORK_STATE_PROVISIONING; } else { NetworkManager_StartSTA(); } @@ -369,24 +373,25 @@ static void Task_Network(void *p_Parameters) WaitingForWiFiRequest = false; } - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); + xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_OPEN_WIFI_REQUEST); } else if (EventBits & NETWORK_TASK_WIFI_CREDENTIALS_UPDATED) { App_Settings_WiFi_t WiFiSettings; SettingsManager_GetWiFi(&WiFiSettings); - memcpy(WiFiSettings.SSID, _NetworkTask_State.SSID, sizeof(WiFiSettings.SSID)); - memcpy(WiFiSettings.Password, _NetworkTask_State.Password, sizeof(WiFiSettings.Password)); + memcpy(WiFiSettings.SSID, _Network_Task_State.SSID, sizeof(WiFiSettings.SSID)); + memcpy(WiFiSettings.Password, _Network_Task_State.Password, sizeof(WiFiSettings.Password)); SettingsManager_UpdateWiFi(&WiFiSettings); SettingsManager_Save(); - xEventGroupClearBits(_NetworkTask_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); + xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); } else if (EventBits & LEPTON_SPOTMETER_READY) { - if (Server_isRunning()) { - + if (Server_IsRunning()) { + // TODO Update Spotmeter in the Server } - xEventGroupClearBits(_NetworkTask_State.EventGroup, LEPTON_SPOTMETER_READY); + + xEventGroupClearBits(_Network_Task_State.EventGroup, LEPTON_SPOTMETER_READY); } vTaskDelay(10 / portTICK_PERIOD_MS); @@ -396,7 +401,7 @@ static void Task_Network(void *p_Parameters) Provisioning_Stop(); NetworkManager_Stop(); - _NetworkTask_State.TaskHandle = NULL; + _Network_Task_State.TaskHandle = NULL; esp_task_wdt_delete(NULL); vTaskDelete(NULL); @@ -411,14 +416,14 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) if (p_AppContext == NULL) { return ESP_ERR_INVALID_ARG; - } else if (_NetworkTask_State.isInitialized) { + } else if (_Network_Task_State.isInitialized) { ESP_LOGW(TAG, "Already initialized"); return ESP_OK; } ESP_LOGD(TAG, "Initializing network task"); - _NetworkTask_State.AppContext = p_AppContext; + _Network_Task_State.AppContext = p_AppContext; /* Initialize NVS */ Error = nvs_flash_init(); @@ -433,8 +438,8 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) } /* Create event group */ - _NetworkTask_State.EventGroup = xEventGroupCreate(); - if (_NetworkTask_State.EventGroup == NULL) { + _Network_Task_State.EventGroup = xEventGroupCreate(); + if (_Network_Task_State.EventGroup == NULL) { ESP_LOGE(TAG, "Failed to create event group!"); return ESP_ERR_NO_MEM; } @@ -445,52 +450,52 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) (esp_event_handler_register(LEPTON_EVENTS, ESP_EVENT_ANY_ID, on_Lepton_Event_Handler, NULL) != ESP_OK)) { ESP_LOGE(TAG, "Failed to register event handler: %d!", Error); - vEventGroupDelete(_NetworkTask_State.EventGroup); + vEventGroupDelete(_Network_Task_State.EventGroup); return Error; } /* Copy the required WiFi settings from settings to network config */ SettingsManager_GetWiFi(&WiFiSettings); - strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID, WiFiSettings.SSID, - sizeof(_NetworkTask_State.AppContext->STA_Config.Credentials.SSID) - 1); - strncpy(_NetworkTask_State.AppContext->STA_Config.Credentials.Password, WiFiSettings.Password, - sizeof(_NetworkTask_State.AppContext->STA_Config.Credentials.Password) - 1); - _NetworkTask_State.AppContext->STA_Config.MaxRetries = WiFiSettings.MaxRetries; - _NetworkTask_State.AppContext->STA_Config.RetryInterval = WiFiSettings.RetryInterval; + strncpy(_Network_Task_State.AppContext->STA_Config.Credentials.SSID, WiFiSettings.SSID, + sizeof(_Network_Task_State.AppContext->STA_Config.Credentials.SSID) - 1); + strncpy(_Network_Task_State.AppContext->STA_Config.Credentials.Password, WiFiSettings.Password, + sizeof(_Network_Task_State.AppContext->STA_Config.Credentials.Password) - 1); + _Network_Task_State.AppContext->STA_Config.MaxRetries = WiFiSettings.MaxRetries; + _Network_Task_State.AppContext->STA_Config.RetryInterval = WiFiSettings.RetryInterval; /* Copy the required VISA settings from settings to network config */ SettingsManager_GetVISAServer(&VISASettings); - _NetworkTask_State.AppContext->Server_Config.VISA_Server.Port = VISASettings.Port; + _Network_Task_State.AppContext->Server_Config.VISA_Server.Port = VISASettings.Port; /* Copy the required Provisioning settings from settings to network config */ SettingsManager_GetProvisioning(&ProvisioningSettings); - strncpy(_NetworkTask_State.AppContext->Prov_Config.Name, + strncpy(_Network_Task_State.AppContext->Prov_Config.Name, ProvisioningSettings.Name, - sizeof(_NetworkTask_State.AppContext->Prov_Config.Name) - 1); - _NetworkTask_State.AppContext->Prov_Config.Timeout = ProvisioningSettings.Timeout; + sizeof(_Network_Task_State.AppContext->Prov_Config.Name) - 1); + _Network_Task_State.AppContext->Prov_Config.Timeout = ProvisioningSettings.Timeout; - Error = NetworkManager_Init(&_NetworkTask_State.AppContext->STA_Config); + Error = NetworkManager_Init(&_Network_Task_State.AppContext->STA_Config); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to init WiFi manager: 0x%x!", Error); esp_event_handler_unregister(SNTP_EVENTS, ESP_EVENT_ANY_ID, on_SNTP_Event_Handler); esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); - vEventGroupDelete(_NetworkTask_State.EventGroup); + vEventGroupDelete(_Network_Task_State.EventGroup); return Error; } - Error = Provisioning_Init(&_NetworkTask_State.AppContext->Prov_Config); + Error = Provisioning_Init(&_Network_Task_State.AppContext->Prov_Config); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to init provisioning: 0x%x!", Error); /* Continue anyway, provisioning is optional */ } - _NetworkTask_State.AppContext = p_AppContext; - _NetworkTask_State.State = NETWORK_STATE_IDLE; - _NetworkTask_State.isInitialized = true; + _Network_Task_State.AppContext = p_AppContext; + _Network_Task_State.State = NETWORK_STATE_IDLE; + _Network_Task_State.isInitialized = true; ESP_LOGD(TAG, "Network Task initialized"); @@ -499,7 +504,7 @@ esp_err_t Network_Task_Init(App_Context_t *p_AppContext) void Network_Task_Deinit(void) { - if (_NetworkTask_State.isInitialized == false) { + if (_Network_Task_State.isInitialized == false) { return; } @@ -514,26 +519,26 @@ void Network_Task_Deinit(void) esp_event_handler_unregister(NETWORK_EVENTS, ESP_EVENT_ANY_ID, on_Network_Event_Handler); esp_event_handler_unregister(GUI_EVENTS, ESP_EVENT_ANY_ID, on_GUI_Event_Handler); - if (_NetworkTask_State.EventGroup != NULL) { - vEventGroupDelete(_NetworkTask_State.EventGroup); - _NetworkTask_State.EventGroup = NULL; + if (_Network_Task_State.EventGroup != NULL) { + vEventGroupDelete(_Network_Task_State.EventGroup); + _Network_Task_State.EventGroup = NULL; } - _NetworkTask_State.isInitialized = false; + _Network_Task_State.isInitialized = false; } esp_err_t Network_Task_Start(void) { BaseType_t Ret; - if (_NetworkTask_State.isInitialized == false) { + if (_Network_Task_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; - } else if (_NetworkTask_State.isRunning) { + } else if (_Network_Task_State.isRunning) { ESP_LOGW(TAG, "Task already Running"); return ESP_OK; } - _NetworkTask_State.isRunning = true; + _Network_Task_State.isRunning = true; ESP_LOGD(TAG, "Starting Network Task"); @@ -543,7 +548,7 @@ esp_err_t Network_Task_Start(void) CONFIG_NETWORK_TASK_STACKSIZE, NULL, CONFIG_NETWORK_TASK_PRIO, - &_NetworkTask_State.TaskHandle, + &_Network_Task_State.TaskHandle, CONFIG_NETWORK_TASK_CORE ); @@ -552,25 +557,25 @@ esp_err_t Network_Task_Start(void) return ESP_ERR_NO_MEM; } - _NetworkTask_State.StartTime = xTaskGetTickCount() * portTICK_PERIOD_MS / 1000; + _Network_Task_State.StartTime = xTaskGetTickCount() * portTICK_PERIOD_MS / 1000; return ESP_OK; } esp_err_t Network_Task_Stop(void) { - if (_NetworkTask_State.isRunning == false) { + if (_Network_Task_State.isRunning == false) { return ESP_OK; } ESP_LOGD(TAG, "Stopping Network Task"); - xEventGroupSetBits(_NetworkTask_State.EventGroup, NETWORK_TASK_STOP_REQUEST); + xEventGroupSetBits(_Network_Task_State.EventGroup, NETWORK_TASK_STOP_REQUEST); return ESP_OK; } -bool Network_Task_isRunning(void) +bool Network_Task_IsRunning(void) { - return _NetworkTask_State.isRunning; + return _Network_Task_State.isRunning; } \ No newline at end of file diff --git a/main/Application/Tasks/Network/networkTask.h b/main/Application/Tasks/Network/networkTask.h index 273c834..7934f38 100644 --- a/main/Application/Tasks/Network/networkTask.h +++ b/main/Application/Tasks/Network/networkTask.h @@ -3,7 +3,7 @@ * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de - * File info: Network task for WiFi and HTTP server management. + * File info: Network task definition. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,28 +33,53 @@ #include "Application/Manager/Network/networkTypes.h" /** @brief Initialize the network task. + * Creates FreeRTOS task for network operations including WiFi + * management, HTTP server, WebSocket, and VISA server. + * @note Call this after NetworkManager_Init(). + * Task handles WiFi events and client connections. * @param p_AppContext Pointer to the application context - * @return ESP_OK on success, error code otherwise + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_AppContext is NULL + * ESP_ERR_NO_MEM if task creation fails + * ESP_FAIL if network initialization fails */ esp_err_t Network_Task_Init(App_Context_t *p_AppContext); -/** @brief Deinitialize the network task. +/** @brief Deinitialize the network task. + * Stops the task and frees all resources. Network connections are + * terminated. + * @note Task must be stopped before calling this. + * All client connections are closed. */ void Network_Task_Deinit(void); -/** @brief Start the network task. - * @return ESP_OK on success, error code otherwise +/** @brief Start the network task. + * Resumes the task to handle network operations and event processing. + * @note Task processes WiFi events and manages connections. + * Servers start when WiFi connection is established. + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not initialized + * ESP_FAIL if task start fails */ esp_err_t Network_Task_Start(void); -/** @brief Stop the network task. - * @return ESP_OK on success, error code otherwise +/** @brief Stop the network task. + * Suspends network task execution. Existing connections remain active + * but no new connections are accepted. + * @note WiFi remains connected. + * To disconnect WiFi, use NetworkManager_DisconnectWiFi(). + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not running + * ESP_FAIL if stop operation fails */ esp_err_t Network_Task_Stop(void); -/** @brief Check if the network task is running. - * @return true if running, false otherwise +/** @brief Check if the network task is running. + * Returns the current task execution status. + * @note Thread-safe. + * @return true if task is running and processing events + * false if task is stopped or not initialized */ -bool Network_Task_isRunning(void); +bool Network_Task_IsRunning(void); #endif /* NETWORK_TASK_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/tasks.h b/main/Application/Tasks/tasks.h index 58a9fc1..452e041 100644 --- a/main/Application/Tasks/tasks.h +++ b/main/Application/Tasks/tasks.h @@ -28,5 +28,6 @@ #include "Network/networkTask.h" #include "Devices/devicesTask.h" #include "GUI/guiTask.h" +#include "Camera/cameraTask.h" #endif /* TASKS_H_ */ \ No newline at end of file diff --git a/main/Application/application.h b/main/Application/application.h index acfb64a..65a94a1 100644 --- a/main/Application/application.h +++ b/main/Application/application.h @@ -33,7 +33,6 @@ ESP_EVENT_DECLARE_BASE(LEPTON_EVENTS); ESP_EVENT_DECLARE_BASE(DEVICE_EVENTS); ESP_EVENT_DECLARE_BASE(GUI_EVENTS); -ESP_EVENT_DECLARE_BASE(SD_EVENTS); /** @brief Lepton camera event identifiers. */ @@ -77,6 +76,9 @@ enum { Data is transmitted in a App_GUI_Screenposition_t structure. */ GUI_EVENT_REQUEST_SPOTMETER, /**< Request update of spotmeter data. */ GUI_EVENT_REQUEST_SCENE_STATISTICS, /**< Request update of scene statistics data. */ + GUI_EVENT_THERMAL_IMAGE_SAVED, /**< Thermal image successfully saved to storage. */ + GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, /**< Thermal image save operation failed. + Data is transmitted as an int representing the errno value. */ }; /** @brief Structure representing a screen position. diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f2fa6f2..ab77c9e 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -2,7 +2,7 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/main/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "Application/Manager" - REQUIRES esp_http_server esp_timer esp_wifi json nvs_flash driver + REQUIRES esp_http_server esp_timer esp_wifi json nvs_flash driver espressif__esp_tinyusb fatfs wear_levelling EMBED_TXTFILES "../webserver/provision.html" EMBED_TXTFILES "../webserver/logo.png" EMBED_TXTFILES "../LICENSE" diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index df89aa8..dc44e25 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -3,6 +3,20 @@ menu "PyroVision" config DEVICE_MANUFACTURER string "Device manufacturer" default "PyroVision" + + config DEVICE_NAME + string "Device name" + default "ThermalCam" + endmenu + + menu "USB" + config USB_VID + hex "USB Vendor ID" + default 0x1234 + + config USB_PID + hex "USB Product ID" + default 0x5678 endmenu menu "Settings" @@ -63,6 +77,12 @@ menu "PyroVision" endmenu menu "Network" + menu "Websocket" + config NETWORK_WEBSOCKET_CLIENTS + int "Maximum number of WebSocket clients" + default 4 + endmenu + menu "Task" config NETWORK_TASK_STACKSIZE int "Stack size" @@ -97,12 +117,35 @@ menu "PyroVision" endmenu endmenu + menu "Camera" + menu "Task" + config CAMERA_TASK_STACKSIZE + int "Stack size" + default 8192 + + config CAMERA_TASK_PRIO + int "Task prio" + default 12 + + config CAMERA_TASK_CORE + int "Task core" + default 1 + endmenu + endmenu + menu "Devices" menu "I2C" - config DEVICES_I2C_HOST - int "I2C interface" - range 0 2 - default 1 + choice + prompt "Peripheral I2C Bus" + default DEVICES_I2C_I2C1_HOST + help + Select the I2C Bus for the peripheral components. + + config DEVICES_I2C_I2C0_HOST + bool "I2C0_HOST" + config DEVICES_I2C_I2C1_HOST + bool "I2C1_HOST" + endchoice config DEVICES_I2C_SCL int "SCL pin number" @@ -140,7 +183,7 @@ menu "PyroVision" prompt "Touch I2C Bus" default TOUCH_I2C0_HOST help - Select the SPI Bus the Touch Controller is attached to. + Select the I2C Bus the Touch Controller is attached to. config TOUCH_I2C0_HOST bool "I2C0_HOST" diff --git a/main/idf_component.yml b/main/idf_component.yml index 94819cd..f3a87a3 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -9,6 +9,12 @@ dependencies: version: "^1.2.0" espressif/esp32-camera: version: "^2.1.0" + espressif/esp_tinyusb: + version: "^2.1.0" + espressif/libpng: + version: "^1.6.54" + espressif/max17048: + version: "^0.1.1" lvgl/lvgl: version: "^9.4.0" joltwallet/littlefs: diff --git a/main/main.cpp b/main/main.cpp index 0d9d910..2649f67 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -22,14 +22,13 @@ #include #include #include +#include #include +#include "managers.h" #include "Application/Tasks/tasks.h" #include "Application/application.h" -#include "Application/Manager/Time/timeManager.h" -#include "Application/Manager/Devices/devicesManager.h" -#include "Application/Manager/SD/sdManager.h" static App_Context_t _App_Context; @@ -47,15 +46,13 @@ extern "C" void app_main(void) _App_Context.Lepton_FrameEventQueue = xQueueCreate(1, sizeof(App_Lepton_FrameReady_t)); if (_App_Context.Lepton_FrameEventQueue == NULL) { ESP_LOGE(TAG, "Failed to create frame queue!"); + return; } ESP_ERROR_CHECK(SettingsManager_Init()); - - ESP_LOGI(TAG, "Loading settings..."); - - ESP_LOGI(TAG, "Initializing application tasks..."); - ESP_ERROR_CHECK(DevicesTask_Init()); + ESP_ERROR_CHECK(Devices_Task_Init()); + ESP_ERROR_CHECK(MemoryManager_Init()); /* Initialize Time Manager (requires RTC from DevicesManager) */ if (DevicesManager_GetRTCHandle(&RtcHandle) == ESP_OK) { @@ -71,15 +68,14 @@ extern "C" void app_main(void) ESP_LOGW(TAG, "RTC not available, Time Manager initialization skipped"); } - //SDManager_Init(); - ESP_ERROR_CHECK(GUI_Task_Init()); ESP_ERROR_CHECK(Lepton_Task_Init()); + ESP_ERROR_CHECK(Camera_Task_Init()); ESP_ERROR_CHECK(Network_Task_Init(&_App_Context)); ESP_LOGI(TAG, " Initialization successful"); ESP_LOGI(TAG, "Starting tasks..."); - ESP_ERROR_CHECK(DevicesTask_Start(&_App_Context)); + ESP_ERROR_CHECK(Devices_Task_Start(&_App_Context)); ESP_ERROR_CHECK(GUI_Task_Start(&_App_Context)); ESP_ERROR_CHECK(Lepton_Task_Start(&_App_Context)); ESP_ERROR_CHECK(Network_Task_Start()); diff --git a/partitions.csv b/partitions.csv index 7dcdaba..92f06c0 100644 --- a/partitions.csv +++ b/partitions.csv @@ -4,5 +4,6 @@ nvs_keys, data, nvs_keys, 0xD000, 0x1000, otadata, data, ota, 0xE000, 0x2000, app0, app, ota_0, 0x10000, 0x2F0000, app1, app, ota_1, 0x300000, 0x2F0000, -storage, data, spiffs, 0x5F0000, 0x160000, -settings, data, nvs, 0x750000, 0x10000, \ No newline at end of file +storage, data, fat, 0x5F0000, 0x160000, +settings, data, nvs, 0x750000, 0x10000, +coredump, data, coredump, 0x760000, 0x10000, \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 1912245..d7c79a2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -3,7 +3,7 @@ src_dir = main default_envs = debug [env] -platform = espressif32 +platform = espressif32@6.12.0 framework = espidf platform_packages = diff --git a/sdkconfig.debug b/sdkconfig.debug index 822a53b..10b403a 100644 --- a/sdkconfig.debug +++ b/sdkconfig.debug @@ -559,14 +559,14 @@ CONFIG_ESPTOOLPY_FLASHFREQ_80M=y # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set CONFIG_ESPTOOLPY_FLASHFREQ="80m" # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE="8MB" # CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set CONFIG_ESPTOOLPY_BEFORE_RESET=y # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set @@ -599,8 +599,16 @@ CONFIG_PARTITION_TABLE_MD5=y # Device # CONFIG_DEVICE_MANUFACTURER="PyroVision" +CONFIG_DEVICE_NAME="ThermalCam" # end of Device +# +# USB +# +CONFIG_USB_VID=0x1234 +CONFIG_USB_PID=0x5678 +# end of USB + # # Settings # @@ -627,6 +635,12 @@ CONFIG_BATTERY_ADC_R2=3300 # Network # +# +# Websocket +# +CONFIG_NETWORK_WEBSOCKET_CLIENTS=4 +# end of Websocket + # # Task # @@ -653,6 +667,19 @@ CONFIG_LEPTON_TASK_CORE=1 # end of Task # end of Lepton +# +# Camera +# + +# +# Task +# +CONFIG_CAMERA_TASK_STACKSIZE=8192 +CONFIG_CAMERA_TASK_PRIO=12 +CONFIG_CAMERA_TASK_CORE=1 +# end of Task +# end of Camera + # # Devices # @@ -660,7 +687,8 @@ CONFIG_LEPTON_TASK_CORE=1 # # I2C # -CONFIG_DEVICES_I2C_HOST=1 +# CONFIG_DEVICES_I2C_I2C0_HOST is not set +CONFIG_DEVICES_I2C_I2C1_HOST=y CONFIG_DEVICES_I2C_SCL=21 CONFIG_DEVICES_I2C_SDA=47 # end of I2C @@ -1354,7 +1382,7 @@ CONFIG_SPIRAM_USE_MALLOC=y CONFIG_SPIRAM_MEMTEST=y CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y -CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=163840 CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y # end of SPI RAM config @@ -1569,9 +1597,21 @@ CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y # # Core dump # -# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y # CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set -CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# CONFIG_ESP_COREDUMP_ENABLE_TO_NONE is not set +# CONFIG_ESP_COREDUMP_DATA_FORMAT_BIN is not set +CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y +CONFIG_ESP_COREDUMP_CHECKSUM_CRC32=y +# CONFIG_ESP_COREDUMP_CHECKSUM_SHA256 is not set +# CONFIG_ESP_COREDUMP_CAPTURE_DRAM is not set +CONFIG_ESP_COREDUMP_CHECK_BOOT=y +CONFIG_ESP_COREDUMP_ENABLE=y +CONFIG_ESP_COREDUMP_LOGS=y +CONFIG_ESP_COREDUMP_MAX_TASKS_NUM=64 +# CONFIG_ESP_COREDUMP_FLASH_NO_OVERWRITE is not set +CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y +CONFIG_ESP_COREDUMP_STACK_SIZE=1792 # end of Core dump # @@ -1673,7 +1713,7 @@ CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y # CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set # CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y -CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=2096 CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y # CONFIG_FREERTOS_FPU_IN_ISR is not set CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y @@ -2506,17 +2546,17 @@ CONFIG_OV5640_SUPPORT=y CONFIG_SCCB_HARDWARE_I2C_DRIVER_NEW=y # CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set CONFIG_SCCB_HARDWARE_I2C_PORT1=y -CONFIG_SCCB_CLK_FREQ=100000 +CONFIG_SCCB_CLK_FREQ=400000 CONFIG_CAMERA_TASK_STACK_SIZE=4096 CONFIG_CAMERA_CORE0=y # CONFIG_CAMERA_CORE1 is not set # CONFIG_CAMERA_NO_AFFINITY is not set CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768 -# CONFIG_CAMERA_PSRAM_DMA is not set +CONFIG_CAMERA_PSRAM_DMA=y CONFIG_CAMERA_JPEG_MODE_FRAME_SIZE_AUTO=y # CONFIG_CAMERA_JPEG_MODE_FRAME_SIZE_CUSTOM is not set # CONFIG_CAMERA_CONVERTER_ENABLED is not set -# CONFIG_LCD_CAM_ISR_IRAM_SAFE is not set +CONFIG_LCD_CAM_ISR_IRAM_SAFE=y # end of Camera configuration # @@ -2532,6 +2572,110 @@ CONFIG_ESP_LCD_TOUCH_MAX_POINTS=5 CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS=1 # end of ESP LCD TOUCH +# +# TinyUSB Stack +# +CONFIG_TINYUSB_DEBUG_LEVEL=0 + +# +# TinyUSB DCD +# +# CONFIG_TINYUSB_MODE_SLAVE is not set +CONFIG_TINYUSB_MODE_DMA=y +# end of TinyUSB DCD + +# +# TinyUSB callbacks +# +# CONFIG_TINYUSB_SUSPEND_CALLBACK is not set +# CONFIG_TINYUSB_RESUME_CALLBACK is not set +# end of TinyUSB callbacks + +# +# Descriptor configuration +# + +# +# You can provide your custom descriptors via tinyusb_driver_install() +# +# CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID is not set +CONFIG_TINYUSB_DESC_CUSTOM_VID=0x1234 +# CONFIG_TINYUSB_DESC_USE_DEFAULT_PID is not set +CONFIG_TINYUSB_DESC_CUSTOM_PID=0x5678 +CONFIG_TINYUSB_DESC_BCD_DEVICE=0x0100 +CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="PyroVision" +CONFIG_TINYUSB_DESC_PRODUCT_STRING="ThermalCam Storage" +CONFIG_TINYUSB_DESC_SERIAL_STRING="123456" +CONFIG_TINYUSB_DESC_MSC_STRING="Mass Storage" +# end of Descriptor configuration + +# +# Mass Storage Class (MSC) +# +CONFIG_TINYUSB_MSC_ENABLED=y +CONFIG_TINYUSB_MSC_BUFSIZE=4096 +CONFIG_TINYUSB_MSC_MOUNT_PATH="/data" +# end of Mass Storage Class (MSC) + +# +# Communication Device Class (CDC) +# +# CONFIG_TINYUSB_CDC_ENABLED is not set +# end of Communication Device Class (CDC) + +# +# Musical Instrument Digital Interface (MIDI) +# +CONFIG_TINYUSB_MIDI_COUNT=0 +# end of Musical Instrument Digital Interface (MIDI) + +# +# Human Interface Device Class (HID) +# +CONFIG_TINYUSB_HID_COUNT=0 +# end of Human Interface Device Class (HID) + +# +# Device Firmware Upgrade (DFU) +# +# CONFIG_TINYUSB_DFU_MODE_DFU is not set +# CONFIG_TINYUSB_DFU_MODE_DFU_RUNTIME is not set +CONFIG_TINYUSB_DFU_MODE_NONE=y +# end of Device Firmware Upgrade (DFU) + +# +# Bluetooth Host Class (BTH) +# +# CONFIG_TINYUSB_BTH_ENABLED is not set +# end of Bluetooth Host Class (BTH) + +# +# Network driver (ECM/NCM/RNDIS) +# +# CONFIG_TINYUSB_NET_MODE_ECM_RNDIS is not set +# CONFIG_TINYUSB_NET_MODE_NCM is not set +CONFIG_TINYUSB_NET_MODE_NONE=y +# end of Network driver (ECM/NCM/RNDIS) + +# +# Vendor Specific Interface +# +CONFIG_TINYUSB_VENDOR_COUNT=0 +# end of Vendor Specific Interface +# end of TinyUSB Stack + +# +# Bus Options +# + +# +# I2C Bus Options +# +# CONFIG_I2C_BUS_DYNAMIC_CONFIG is not set +CONFIG_I2C_MS_TO_WAIT=200 +# end of I2C Bus Options +# end of Bus Options + # # LittleFS # @@ -3100,9 +3244,16 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # CONFIG_WPA_WPS_STRICT is not set # CONFIG_WPA_DEBUG_PRINT is not set # CONFIG_WPA_TESTING_OPTIONS is not set -# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=y # CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set -CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE is not set +# CONFIG_ESP32_COREDUMP_DATA_FORMAT_BIN is not set +CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF=y +CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32=y +# CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 is not set +CONFIG_ESP32_ENABLE_COREDUMP=y +CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM=64 +CONFIG_ESP32_CORE_DUMP_STACK_SIZE=1792 CONFIG_TIMER_TASK_PRIORITY=1 CONFIG_TIMER_TASK_STACK_DEPTH=2048 CONFIG_TIMER_QUEUE_LENGTH=10 diff --git a/sdkconfig.release b/sdkconfig.release new file mode 100644 index 0000000..9d3450e --- /dev/null +++ b/sdkconfig.release @@ -0,0 +1,3303 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) 5.5.0 Project Configuration +# +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y +CONFIG_SOC_PCNT_SUPPORTED=y +CONFIG_SOC_PHY_SUPPORTED=y +CONFIG_SOC_WIFI_SUPPORTED=y +CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_GDMA_SUPPORTED=y +CONFIG_SOC_UHCI_SUPPORTED=y +CONFIG_SOC_AHB_GDMA_SUPPORTED=y +CONFIG_SOC_GPTIMER_SUPPORTED=y +CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y +CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y +CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +CONFIG_SOC_ULP_SUPPORTED=y +CONFIG_SOC_ULP_FSM_SUPPORTED=y +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_USB_OTG_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_EFUSE_SUPPORTED=y +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_CLK_TREE_SUPPORTED=y +CONFIG_SOC_MPU_SUPPORTED=y +CONFIG_SOC_WDT_SUPPORTED=y +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +CONFIG_SOC_RNG_SUPPORTED=y +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +CONFIG_SOC_PM_SUPPORTED=y +CONFIG_SOC_SIMD_INSTRUCTION_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=2 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +CONFIG_SOC_ADC_SHARED_POWER=y +CONFIG_SOC_APB_BACKUP_DMA=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED=y +CONFIG_SOC_CACHE_FREEZE_SUPPORTED=y +CONFIG_SOC_CACHE_ACS_INVALID_STATE_ON_PANIC=y +CONFIG_SOC_CPU_CORES_NUM=2 +CONFIG_SOC_CPU_INTR_NUM=32 +CONFIG_SOC_CPU_HAS_FPU=y +CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_AHB_GDMA_VERSION=1 +CONFIG_SOC_GDMA_NUM_GROUPS_MAX=1 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP=5 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX=5 +CONFIG_SOC_AHB_GDMA_SUPPORT_PSRAM=y +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=49 +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB=y +CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +CONFIG_SOC_GPIO_IN_RANGE_MAX=48 +CONFIG_SOC_GPIO_OUT_RANGE_MAX=48 +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000 +CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y +CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y +CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y +CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_HP_I2C_NUM=2 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_CMD_REG_NUM=8 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS=y +CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE=y +CONFIG_SOC_I2S_NUM=2 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_XTAL=y +CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y +CONFIG_SOC_I2S_SUPPORTS_PCM=y +CONFIG_SOC_I2S_SUPPORTS_PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_SUPPORTS_PCM2PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +CONFIG_SOC_I2S_SUPPORTS_PDM2PCM=y +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2 +CONFIG_SOC_I2S_PDM_MAX_RX_LINES=4 +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_TIMER_NUM=4 +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MCPWM_GROUPS=2 +CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 +CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 +CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 +CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y +CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 +CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3 +CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +CONFIG_SOC_MMU_PERIPH_NUM=1 +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +CONFIG_SOC_PCNT_GROUPS=1 +CONFIG_SOC_PCNT_UNITS_PER_GROUP=4 +CONFIG_SOC_PCNT_CHANNELS_PER_UNIT=2 +CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT=2 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8 +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y +CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_DMA=y +CONFIG_SOC_LCD_I80_SUPPORTED=y +CONFIG_SOC_LCD_RGB_SUPPORTED=y +CONFIG_SOC_LCD_I80_BUSES=1 +CONFIG_SOC_LCD_RGB_PANELS=1 +CONFIG_SOC_LCD_I80_BUS_WIDTH=16 +CONFIG_SOC_LCD_RGB_DATA_WIDTH=16 +CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_I80_NUM_BUSES=1 +CONFIG_SOC_LCDCAM_I80_BUS_WIDTH=16 +CONFIG_SOC_LCDCAM_RGB_NUM_PANELS=1 +CONFIG_SOC_LCDCAM_RGB_DATA_WIDTH=16 +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTCIO_PIN_COUNT=22 +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y +CONFIG_SOC_SDM_GROUPS=1 +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y +CONFIG_SOC_SPI_PERIPH_NUM=3 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y +CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_SUPPORT_OCT=y +CONFIG_SOC_SPI_SCT_SUPPORTED=y +CONFIG_SOC_SPI_SCT_REG_NUM=14 +CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y +CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA +CONFIG_SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SPIRAM_SUPPORTED=y +CONFIG_SOC_SPIRAM_XIP_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 +CONFIG_SOC_TOUCH_SENSOR_VERSION=2 +CONFIG_SOC_TOUCH_SENSOR_NUM=15 +CONFIG_SOC_TOUCH_MIN_CHAN_ID=1 +CONFIG_SOC_TOUCH_MAX_CHAN_ID=14 +CONFIG_SOC_TOUCH_SUPPORT_BENCHMARK=y +CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y +CONFIG_SOC_TOUCH_SUPPORT_WATERPROOF=y +CONFIG_SOC_TOUCH_SUPPORT_PROX_SENSING=y +CONFIG_SOC_TOUCH_SUPPORT_DENOISE_CHAN=y +CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3 +CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y +CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 +CONFIG_SOC_TWAI_MASK_FILTER_NUM=1 +CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y +CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_BRP_MAX=16384 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_HP_NUM=3 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +CONFIG_SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE=y +CONFIG_SOC_UHCI_NUM=1 +CONFIG_SOC_USB_OTG_PERIPH_NUM=1 +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +CONFIG_SOC_SHA_SUPPORT_DMA=y +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SHA_SUPPORT_SHA384=y +CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +CONFIG_SOC_MPI_OPERATIONS_NUM=3 +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y +CONFIG_SOC_CLK_LP_FAST_SUPPORT_XTAL_D2=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_DCACHE=y +CONFIG_SOC_EFUSE_HARD_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +CONFIG_SOC_EFUSE_DIS_ICACHE=y +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE=y +CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY=y +CONFIG_SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM=y +CONFIG_SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_EXTERNAL_COEX_LEADER_TX_LINE=y +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +CONFIG_SOC_SDMMC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_SDMMC_DELAY_PHASE_NUM=4 +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_BLE_50_SUPPORTED=y +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_ULP_HAS_ADC=y +CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TOOLCHAIN="gcc" +CONFIG_IDF_TOOLCHAIN_GCC=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET_ARCH="xtensa" +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_INIT_VERSION="5.4.1" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# Bootloader config +# + +# +# Bootloader manager +# +CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y +CONFIG_BOOTLOADER_PROJECT_VER=1 +# end of Bootloader manager + +# +# Application Rollback +# +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# end of Application Rollback + +# +# Bootloader Rollback +# +# end of Bootloader Rollback + +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set + +# +# Log +# +CONFIG_BOOTLOADER_LOG_VERSION_1=y +CONFIG_BOOTLOADER_LOG_VERSION=1 +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 + +# +# Format +# +# CONFIG_BOOTLOADER_LOG_COLORS is not set +CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y +# end of Format + +# +# Settings +# +CONFIG_BOOTLOADER_LOG_MODE_TEXT_EN=y +CONFIG_BOOTLOADER_LOG_MODE_TEXT=y +# end of Settings +# end of Log + +# +# Serial Flash Configurations +# +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations + +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 +# end of Application manager + +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_USB_OTG_NUM=3 +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +CONFIG_ESP_ROM_HAS_HAL_WDT=y +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y +CONFIG_ESP_ROM_HAS_SPI_FLASH=y +CONFIG_ESP_ROM_HAS_SPI_FLASH_MMAP=y +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y +CONFIG_ESP_ROM_HAS_NEWLIB=y +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG=y +CONFIG_ESP_ROM_HAS_SW_FLOAT=y +CONFIG_ESP_ROM_HAS_VERSION=y +CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y +CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC=y +CONFIG_ESP_ROM_CONSOLE_OUTPUT_SECONDARY=y + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="8MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# PyroVision +# + +# +# Device +# +CONFIG_DEVICE_MANUFACTURER="PyroVision" +CONFIG_DEVICE_NAME="ThermalCam" +# end of Device + +# +# USB +# +CONFIG_USB_VID=0x1234 +CONFIG_USB_PID=0x5678 +# end of USB + +# +# Settings +# +CONFIG_SETTINGS_NAMESPACE="Calendar" +# end of Settings + +# +# Battery +# +CONFIG_BATTERY_ADC_1=y +# CONFIG_BATTERY_ADC_2 is not set +CONFIG_BATTERY_ADC_CHANNEL=0 +CONFIG_BATTERY_ADC_ATT_0=y +# CONFIG_BATTERY_ADC_ATT_2_5 is not set +# CONFIG_BATTERY_ADC_ATT_6 is not set +# CONFIG_BATTERY_ADC_ATT_12 is not set +CONFIG_BATTERY_ADC_MIN_MV=3000 +CONFIG_BATTERY_ADC_MAX_MV=4200 +CONFIG_BATTERY_ADC_R1=10000 +CONFIG_BATTERY_ADC_R2=3300 +# end of Battery + +# +# Network +# + +# +# Websocket +# +CONFIG_NETWORK_WEBSOCKET_CLIENTS=4 +# end of Websocket + +# +# Task +# +CONFIG_NETWORK_TASK_STACKSIZE=8192 +CONFIG_NETWORK_TASK_PRIO=16 +CONFIG_NETWORK_TASK_CORE=1 +# end of Task + +# +# VISA +# +# end of Network + +# +# Lepton +# + +# +# Task +# +CONFIG_LEPTON_TASK_STACKSIZE=8192 +CONFIG_LEPTON_TASK_PRIO=16 +CONFIG_LEPTON_TASK_CORE=1 +# end of Task +# end of Lepton + +# +# Camera +# + +# +# Task +# +CONFIG_CAMERA_TASK_STACKSIZE=8192 +CONFIG_CAMERA_TASK_PRIO=12 +CONFIG_CAMERA_TASK_CORE=1 +# end of Task +# end of Camera + +# +# Devices +# + +# +# I2C +# +CONFIG_DEVICES_I2C_HOST=1 +CONFIG_DEVICES_I2C_SCL=21 +CONFIG_DEVICES_I2C_SDA=47 +# end of I2C + +# +# SPI +# +CONFIG_SPI_SCLK=46 +CONFIG_SPI_MOSI=48 +CONFIG_SPI_MISO=9 +CONFIG_SPI_TRANSFER_SIZE=4096 + +# +# Touch +# +CONFIG_TOUCH_I2C0_HOST=y +# CONFIG_TOUCH_I2C1_HOST is not set +CONFIG_TOUCH_CLOCK=400000 +CONFIG_TOUCH_SDA=39 +CONFIG_TOUCH_SCL=40 +CONFIG_TOUCH_IRQ=38 +CONFIG_TOUCH_RST=-1 +# end of Touch + +# +# SD-Card +# +# CONFIG_SD_CARD_SPI2_HOST is not set +CONFIG_SD_CARD_SPI3_HOST=y +CONFIG_SD_CARD_CLOCK=2000000 +CONFIG_SD_CARD_FORMAT_CARD=y +CONFIG_SD_CARD_PIN_CS=4 +CONFIG_SD_CARD_PIN_CD=-1 +# end of SD-Card + +# +# LCD +# +# CONFIG_LCD_SPI2_HOST is not set +CONFIG_LCD_SPI3_HOST=y +CONFIG_LCD_CLOCK=8000000 +CONFIG_LCD_CS=18 +CONFIG_LCD_DC=3 +CONFIG_LCD_RST=8 +CONFIG_LCD_BL=-1 +# end of LCD +# end of SPI + +# +# Task +# +CONFIG_DEVICES_TASK_STACKSIZE=4096 +CONFIG_DEVICES_TASK_PRIO=16 +CONFIG_DEVICES_TASK_CORE=1 +# end of Task +# end of Devices + +# +# GUI +# +CONFIG_GUI_WIDTH=320 +CONFIG_GUI_HEIGHT=240 +# CONFIG_GUI_TOUCH_DEBUG is not set +CONFIG_GUI_LVGL_TICK_PERIOD_MS=2 + +# +# Task +# +CONFIG_GUI_TASK_STACKSIZE=16384 +CONFIG_GUI_TASK_PRIO=2 +CONFIG_GUI_TASK_CORE=0 +# end of Task +# end of GUI +# end of PyroVision + +# +# Bootloader config (Custom) +# +# CONFIG_BOOTLOADER_COMPRESSED_ENABLED is not set +# CONFIG_BOOTLOADER_CUSTOM_DEBUG_ON is not set +# CONFIG_SKIP_VALIDATE_CUSTOM_COMPRESSED_HEADER is not set +# CONFIG_SKIP_VALIDATE_CUSTOM_COMPRESSED_DATA is not set +# end of Bootloader config (Custom) + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE=y +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS=y +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +CONFIG_COMPILER_RT_LIB_GCCLIB=y +CONFIG_COMPILER_RT_LIB_NAME="gcc" +CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y +# CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE is not set +# CONFIG_COMPILER_STATIC_ANALYZER is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +# CONFIG_APPTRACE_DEST_UART1 is not set +# CONFIG_APPTRACE_DEST_UART2 is not set +# CONFIG_APPTRACE_DEST_USB_CDC is not set +CONFIG_APPTRACE_DEST_UART_NONE=y +CONFIG_APPTRACE_UART_TASK_PRIO=1 +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set + +# +# Common Options +# +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# end of Common Options +# end of Bluetooth + +# +# Console Library +# +# CONFIG_CONSOLE_SORTED_HELP is not set +# end of Console Library + +# +# Driver Configurations +# + +# +# Legacy TWAI Driver Configurations +# +# CONFIG_TWAI_SKIP_LEGACY_CONFLICT_CHECK is not set +CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y +# end of Legacy TWAI Driver Configurations + +# +# Legacy ADC Driver Configuration +# +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set + +# +# Legacy ADC Calibration Configuration +# +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Driver Configuration + +# +# Legacy MCPWM Driver Configurations +# +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy MCPWM Driver Configurations + +# +# Legacy Timer Group Driver Configurations +# +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Timer Group Driver Configurations + +# +# Legacy RMT Driver Configurations +# +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy RMT Driver Configurations + +# +# Legacy I2S Driver Configurations +# +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2S Driver Configurations + +# +# Legacy I2C Driver Configurations +# +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations + +# +# Legacy PCNT Driver Configurations +# +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy PCNT Driver Configurations + +# +# Legacy SDM Driver Configurations +# +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy SDM Driver Configurations + +# +# Legacy Temperature Sensor Driver Configurations +# +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Temperature Sensor Driver Configurations + +# +# Legacy Touch Sensor Driver Configurations +# +# CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TOUCH_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Touch Sensor Driver Configurations +# end of Driver Configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set +# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ADC and ADC Calibration +# +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# CONFIG_ADC_ENABLE_DEBUG_LOG is not set +# end of ADC and ADC Calibration + +# +# Wireless Coexistence +# +CONFIG_ESP_COEX_ENABLED=y +# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_ESP_COEX_GPIO_DEBUG is not set +# end of Wireless Coexistence + +# +# Common ESP-related +# +# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set +CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# end of Common ESP-related + +# +# ESP-Driver:GPIO Configurations +# +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations + +# +# ESP-Driver:GPTimer Configurations +# +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_CACHE_SAFE is not set +CONFIG_GPTIMER_OBJ_CACHE_SAFE=y +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations + +# +# ESP-Driver:I2C Configurations +# +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 is not set +CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM=y +# end of ESP-Driver:I2C Configurations + +# +# ESP-Driver:I2S Configurations +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations + +# +# ESP-Driver:LEDC Configurations +# +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations + +# +# ESP-Driver:MCPWM Configurations +# +CONFIG_MCPWM_ISR_HANDLER_IN_IRAM=y +# CONFIG_MCPWM_ISR_CACHE_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +CONFIG_MCPWM_OBJ_CACHE_SAFE=y +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:MCPWM Configurations + +# +# ESP-Driver:PCNT Configurations +# +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:PCNT Configurations + +# +# ESP-Driver:RMT Configurations +# +CONFIG_RMT_ENCODER_FUNC_IN_IRAM=y +CONFIG_RMT_TX_ISR_HANDLER_IN_IRAM=y +CONFIG_RMT_RX_ISR_HANDLER_IN_IRAM=y +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# CONFIG_RMT_TX_ISR_CACHE_SAFE is not set +# CONFIG_RMT_RX_ISR_CACHE_SAFE is not set +CONFIG_RMT_OBJ_CACHE_SAFE=y +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# end of ESP-Driver:RMT Configurations + +# +# ESP-Driver:Sigma Delta Modulator Configurations +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations + +# +# ESP-Driver:SPI Configurations +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations + +# +# ESP-Driver:Touch Sensor Configurations +# +# CONFIG_TOUCH_CTRL_FUNC_IN_IRAM is not set +# CONFIG_TOUCH_ISR_IRAM_SAFE is not set +# CONFIG_TOUCH_ENABLE_DEBUG_LOG is not set +# CONFIG_TOUCH_SKIP_FSM_CHECK is not set +# end of ESP-Driver:Touch Sensor Configurations + +# +# ESP-Driver:Temperature Sensor Configurations +# +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Temperature Sensor Configurations + +# +# ESP-Driver:TWAI Configurations +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# CONFIG_TWAI_ISR_CACHE_SAFE is not set +# CONFIG_TWAI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:TWAI Configurations + +# +# ESP-Driver:UART Configurations +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of ESP-Driver:UART Configurations + +# +# ESP-Driver:UHCI Configurations +# +# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set +# CONFIG_UHCI_ISR_CACHE_SAFE is not set +# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:UHCI Configurations + +# +# ESP-Driver:USB Serial/JTAG Configuration +# +CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y +# end of ESP-Driver:USB Serial/JTAG Configuration + +# +# Ethernet +# +# CONFIG_ETH_USE_SPI_ETHERNET is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +CONFIG_ESP_GDBSTUB_ENABLED=y +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 +# end of GDB Stub + +# +# ESP HID +# +CONFIG_ESPHID_TASK_SIZE_BT=2048 +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set +CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +CONFIG_HTTPD_WS_SUPPORT=y +# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000 +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set +# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set +CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT=2000 +# CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# Chip revision +# +CONFIG_ESP32S3_REV_MIN_0=y +# CONFIG_ESP32S3_REV_MIN_1 is not set +# CONFIG_ESP32S3_REV_MIN_2 is not set +CONFIG_ESP32S3_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 + +# +# Maximum Supported ESP32-S3 Revision (Rev v0.99) +# +CONFIG_ESP32S3_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199 + +# +# Maximum Supported ESP32-S3 eFuse Block Revision (eFuse Block Rev v1.99) +# +# end of Chip revision + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# CONFIG_ESP_SLEEP_DEBUG is not set +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# end of RTC Clock Config + +# +# Peripheral Control +# +CONFIG_ESP_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control + +# +# GDMA Configurations +# +CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y +CONFIG_GDMA_ISR_HANDLER_IN_IRAM=y +CONFIG_GDMA_OBJ_DRAM_SAFE=y +# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configurations + +# +# Main XTAL Config +# +CONFIG_XTAL_FREQ_40=y +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config + +# +# Power Supplier +# + +# +# Brownout Detector +# +CONFIG_ESP_BROWNOUT_DET=y +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP_BROWNOUT_DET_LVL=7 +CONFIG_ESP_BROWNOUT_USE_INTR=y +# end of Brownout Detector +# end of Power Supplier + +CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y +CONFIG_ESP_INTR_IN_IRAM=y +# end of Hardware Settings + +# +# ESP-Driver:LCD Controller Configurations +# +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set +# end of ESP-Driver:LCD Controller Configurations + +# +# ESP-MM: Memory Management Configurations +# +# CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS is not set +# end of ESP-MM: Memory Management Configurations + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y +# CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set +# CONFIG_ESP_NETIF_L2_TAP is not set +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set +# end of ESP NETIF Adapter + +# +# Partition API Configuration +# +# end of Partition API Configuration + +# +# PHY +# +CONFIG_ESP_PHY_ENABLED=y +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +CONFIG_ESP_PHY_ENABLE_USB=y +# CONFIG_ESP_PHY_ENABLE_CERT_TEST is not set +CONFIG_ESP_PHY_RF_CAL_PARTIAL=y +# CONFIG_ESP_PHY_RF_CAL_NONE is not set +# CONFIG_ESP_PHY_RF_CAL_FULL is not set +CONFIG_ESP_PHY_CALIBRATION_MODE=0 +# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set +# CONFIG_ESP_PHY_RECORD_USED_TIME is not set +CONFIG_ESP_PHY_IRAM_OPT=y +# end of PHY + +# +# Power Management +# +CONFIG_PM_SLEEP_FUNC_IN_IRAM=y +# CONFIG_PM_ENABLE is not set +CONFIG_PM_SLP_IRAM_OPT=y +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP PSRAM +# +CONFIG_SPIRAM=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_MODE_QUAD is not set +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM_SPEED=80 +# CONFIG_SPIRAM_ECC_ENABLE is not set +CONFIG_SPIRAM_BOOT_HW_INIT=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y +# CONFIG_SPIRAM_USE_MEMMAP is not set +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=163840 +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y +# end of SPI RAM config +# end of ESP PSRAM + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP-ROM +# +CONFIG_ESP_ROM_PRINT_IN_IRAM=y +# end of ESP-ROM + +# +# ESP Security Specific +# +# end of ESP Security Specific + +# +# ESP System Settings +# +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config + +# +# Memory +# +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory + +# +# Trace memory +# +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# end of Trace memory + +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y +# end of ESP System Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1280 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# ESP Timer (High Resolution Timer) +# +CONFIG_ESP_TIMER_IN_IRAM=y +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of ESP Timer (High Resolution Timer) + +# +# Wi-Fi +# +CONFIG_ESP_WIFI_ENABLED=y +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=32 +CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y +# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 +CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5 +# CONFIG_ESP_WIFI_CSI_ENABLED is not set +CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP_WIFI_TX_BA_WIN=6 +CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP_WIFI_RX_BA_WIN=6 +# CONFIG_ESP_WIFI_AMSDU_TX_ENABLED is not set +CONFIG_ESP_WIFI_NVS_ENABLED=y +CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP_WIFI_IRAM_OPT=y +# CONFIG_ESP_WIFI_EXTRA_IRAM_OPT is not set +CONFIG_ESP_WIFI_RX_IRAM_OPT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP_WIFI_ENABLE_SAE_PK=y +CONFIG_ESP_WIFI_ENABLE_SAE_H2E=y +CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +# CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +CONFIG_ESP_WIFI_GMAC_SUPPORT=y +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y +# CONFIG_ESP_WIFI_WAPI_PSK is not set +# CONFIG_ESP_WIFI_SUITE_B_192 is not set +# CONFIG_ESP_WIFI_11KV_SUPPORT is not set +# CONFIG_ESP_WIFI_MBO_SUPPORT is not set +# CONFIG_ESP_WIFI_DPP_SUPPORT is not set +# CONFIG_ESP_WIFI_11R_SUPPORT is not set +# CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR is not set + +# +# WPS Configuration Options +# +# CONFIG_ESP_WIFI_WPS_STRICT is not set +# CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# end of WPS Configuration Options + +# CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set +# CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT is not set +# end of Wi-Fi + +# +# Core dump +# +CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_NONE is not set +# CONFIG_ESP_COREDUMP_DATA_FORMAT_BIN is not set +CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y +CONFIG_ESP_COREDUMP_CHECKSUM_CRC32=y +# CONFIG_ESP_COREDUMP_CHECKSUM_SHA256 is not set +# CONFIG_ESP_COREDUMP_CAPTURE_DRAM is not set +CONFIG_ESP_COREDUMP_CHECK_BOOT=y +CONFIG_ESP_COREDUMP_ENABLE=y +CONFIG_ESP_COREDUMP_LOGS=y +CONFIG_ESP_COREDUMP_MAX_TASKS_NUM=64 +# CONFIG_ESP_COREDUMP_FLASH_NO_OVERWRITE is not set +CONFIG_ESP_COREDUMP_USE_STACK_SIZE=y +CONFIG_ESP_COREDUMP_STACK_SIZE=1792 +# end of Core dump + +# +# FAT Filesystem support +# +CONFIG_FATFS_VOLUME_COUNT=2 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +# CONFIG_FATFS_SECTOR_512 is not set +CONFIG_FATFS_SECTOR_4096=y +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y +# CONFIG_FATFS_USE_FASTSEEK is not set +CONFIG_FATFS_USE_STRFUNC_NONE=y +# CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV is not set +# CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV is not set +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# CONFIG_FATFS_IMMEDIATE_FSYNC is not set +# CONFIG_FATFS_USE_LABEL is not set +CONFIG_FATFS_LINK_LOCK=y +# CONFIG_FATFS_USE_DYN_BUFFERS is not set + +# +# File system free space calculation behavior +# +CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 +CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 +# end of File system free space calculation behavior +# end of FAT Filesystem support + +# +# FreeRTOS +# + +# +# Kernel +# +# CONFIG_FREERTOS_SMP is not set +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_HZ=100 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_USE_TIMERS=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set +# end of Kernel + +# +# Port +# +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_ISR_STACKSIZE=2096 +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# end of Port + +# +# Extra +# +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y +# end of Extra + +CONFIG_FREERTOS_PORT=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y +CONFIG_FREERTOS_NUMBER_OF_CORES=2 +CONFIG_FREERTOS_IN_IRAM=y +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_WDT_USE_ROM_IMPL=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_TASK_TRACKING is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging + +# +# Log +# +CONFIG_LOG_VERSION_1=y +# CONFIG_LOG_VERSION_2 is not set +CONFIG_LOG_VERSION=1 + +# +# Log Level +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 + +# +# Level Settings +# +# CONFIG_LOG_MASTER_LEVEL is not set +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level + +# +# Format +# +# CONFIG_LOG_COLORS is not set +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Format + +# +# Settings +# +CONFIG_LOG_MODE_TEXT_EN=y +CONFIG_LOG_MODE_TEXT=y +# end of Settings + +CONFIG_LOG_IN_IRAM=y +# end of Log + +# +# LWIP +# +CONFIG_LWIP_ENABLE=y +CONFIG_LWIP_LOCAL_HOSTNAME="PyroVision" +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_ND6=y +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_DEFAULT_TTL=64 +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_ESP_MLDV6_REPORT=y +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +CONFIG_LWIP_DHCPS_ADD_DNS=y +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV4=y +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 +CONFIG_LWIP_TCP_WND_DEFAULT=5760 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 +CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 +CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# CONFIG_LWIP_PPP_SUPPORT is not set +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 +# end of SNTP + +# +# DNS +# +CONFIG_LWIP_DNS_MAX_HOST_IP=1 +CONFIG_LWIP_DNS_MAX_SERVERS=3 +# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set +# CONFIG_LWIP_USE_ESP_GETADDRINFO is not set +# end of DNS + +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set +CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_NONE=y +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_DEFAULT is not set +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v3.x related +# +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +CONFIG_MBEDTLS_PKCS7_C=y +# end of mbedTLS v3.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA1_C=y +CONFIG_MBEDTLS_SHA512_C=y +# CONFIG_MBEDTLS_SHA3_C is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +CONFIG_MBEDTLS_ERROR_STRINGS=y +CONFIG_MBEDTLS_FS_IO=y +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set +# end of mbedTLS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +# CONFIG_MQTT_PROTOCOL_5 is not set +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# LibC +# +CONFIG_LIBC_NEWLIB=y +CONFIG_LIBC_MISC_IN_IRAM=y +CONFIG_LIBC_LOCKS_PLACE_IN_IRAM=y +CONFIG_LIBC_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_LIBC_STDOUT_LINE_ENDING_LF is not set +# CONFIG_LIBC_STDOUT_LINE_ENDING_CR is not set +# CONFIG_LIBC_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_LIBC_STDIN_LINE_ENDING_LF is not set +CONFIG_LIBC_STDIN_LINE_ENDING_CR=y +# CONFIG_LIBC_NEWLIB_NANO_FORMAT is not set +CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y +# CONFIG_LIBC_TIME_SYSCALL_USE_RTC is not set +# CONFIG_LIBC_TIME_SYSCALL_USE_HRT is not set +# CONFIG_LIBC_TIME_SYSCALL_USE_NONE is not set +# end of LibC + +CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y + +# +# NVS +# +# CONFIG_NVS_ENCRYPTION is not set +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set +# CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM is not set +# end of NVS + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set + +# +# OpenThread Spinel +# +# CONFIG_OPENTHREAD_SPINEL_ONLY is not set +# end of OpenThread Spinel +# end of OpenThread + +# +# Protocomm +# +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y +# end of Protocomm + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# MMU Config +# +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# Main Flash configuration +# + +# +# SPI Flash behavior when brownout +# +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Optional and Experimental Features (READ DOCS FIRST) +# + +# +# Features here require specific hardware (READ DOCS FIRST!) +# +# CONFIG_SPI_FLASH_HPM_ENA is not set +CONFIG_SPI_FLASH_HPM_AUTO=y +# CONFIG_SPI_FLASH_HPM_DIS is not set +CONFIG_SPI_FLASH_HPM_ON=y +CONFIG_SPI_FLASH_HPM_DC_AUTO=y +# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 +# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set +CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM=y +# end of Optional and Experimental Features (READ DOCS FIRST) +# end of Main Flash configuration + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED=y +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# CONFIG_WS_DYNAMIC_BUFFER is not set +# end of Websocket +# end of TCP Transport + +# +# Ultra Low Power (ULP) Co-processor +# +CONFIG_ULP_COPROC_ENABLED=y +# CONFIG_ULP_COPROC_TYPE_FSM is not set +CONFIG_ULP_COPROC_TYPE_RISCV=y +CONFIG_ULP_COPROC_RESERVE_MEM=4096 + +# +# ULP RISC-V Settings +# +# CONFIG_ULP_RISCV_INTERRUPT_ENABLE is not set +CONFIG_ULP_RISCV_UART_BAUDRATE=9600 +CONFIG_ULP_RISCV_I2C_RW_TIMEOUT=500 +# end of ULP RISC-V Settings + +# +# ULP Debugging Options +# +# end of ULP Debugging Options +# end of Ultra Low Power (ULP) Co-processor + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# CONFIG_UNITY_TEST_ORDER_BY_FILE_PATH_AND_LINE is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set + +# +# Hub Driver Configuration +# + +# +# Root Port configuration +# +CONFIG_USB_HOST_DEBOUNCE_DELAY_MS=250 +CONFIG_USB_HOST_RESET_HOLD_MS=30 +CONFIG_USB_HOST_RESET_RECOVERY_MS=30 +CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS=10 +# end of Root Port configuration + +# CONFIG_USB_HOST_HUBS_SUPPORTED is not set +# end of Hub Driver Configuration + +# CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK is not set +CONFIG_USB_OTG_SUPPORTED=y +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SELECT_IN_RAM is not set +CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=8 + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) + +CONFIG_VFS_INITIALIZE_DEV_NULL=y +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y +# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set +# end of Wi-Fi Provisioning Manager + +# +# ESP32-Lepton +# + +# +# GPIO +# + +# +# V-Sync +# +# CONFIG_LEPTON_GPIO_USE_VSYNC is not set +# end of V-Sync + +# +# Reset +# +CONFIG_LEPTON_GPIO_RESET_PIN=-1 +# end of Reset + +# +# Power-Down +# +CONFIG_LEPTON_GPIO_PWR_PIN=-1 +# end of Power-Down +# end of GPIO + +# +# VoSPI +# +CONFIG_LEPTON_VOSPI_SPI2_HOST=y +# CONFIG_LEPTON_VOSPI_SPI3_HOST is not set +CONFIG_LEPTON_VOSPI_MISO=12 +CONFIG_LEPTON_VOSPI_SCK=13 +CONFIG_LEPTON_VOSPI_CS=14 +CONFIG_LEPTON_VOSPI_FRAME_BUFFERS=2 +# end of VoSPI + +# +# Capture Task +# +CONFIG_LEPTON_CAPTURE_TASK_CORE_AFFINITY=y +CONFIG_LEPTON_CAPTURE_TASK_CORE=0 +CONFIG_LEPTON_CAPTURE_TASK_STACK=6144 +CONFIG_LEPTON_CAPTURE_TASK_PRIORITY=12 +# end of Capture Task + +# +# Misc +# +CONFIG_LEPTON_MISC_ERROR_BASE=0xB000 +# end of Misc +# end of ESP32-Lepton + +# +# CMake Utilities +# +# CONFIG_CU_RELINKER_ENABLE is not set +# CONFIG_CU_DIAGNOSTICS_COLOR_NEVER is not set +CONFIG_CU_DIAGNOSTICS_COLOR_ALWAYS=y +# CONFIG_CU_DIAGNOSTICS_COLOR_AUTO is not set +# CONFIG_CU_GCC_LTO_ENABLE is not set +# CONFIG_CU_GCC_STRING_1BYTE_ALIGN is not set +# end of CMake Utilities + +# +# Camera configuration +# +# CONFIG_OV7670_SUPPORT is not set +# CONFIG_OV7725_SUPPORT is not set +# CONFIG_NT99141_SUPPORT is not set +# CONFIG_OV2640_SUPPORT is not set +# CONFIG_OV3660_SUPPORT is not set +CONFIG_OV5640_SUPPORT=y +# CONFIG_GC2145_SUPPORT is not set +# CONFIG_GC032A_SUPPORT is not set +# CONFIG_GC0308_SUPPORT is not set +# CONFIG_BF3005_SUPPORT is not set +# CONFIG_BF20A6_SUPPORT is not set +# CONFIG_SC101IOT_SUPPORT is not set +# CONFIG_SC030IOT_SUPPORT is not set +# CONFIG_SC031GS_SUPPORT is not set +# CONFIG_HM1055_SUPPORT is not set +# CONFIG_HM0360_SUPPORT is not set +# CONFIG_MEGA_CCM_SUPPORT is not set +# CONFIG_SCCB_HARDWARE_I2C_DRIVER_LEGACY is not set +CONFIG_SCCB_HARDWARE_I2C_DRIVER_NEW=y +# CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set +CONFIG_SCCB_HARDWARE_I2C_PORT1=y +CONFIG_SCCB_CLK_FREQ=400000 +CONFIG_CAMERA_TASK_STACK_SIZE=4096 +CONFIG_CAMERA_CORE0=y +# CONFIG_CAMERA_CORE1 is not set +# CONFIG_CAMERA_NO_AFFINITY is not set +CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768 +CONFIG_CAMERA_PSRAM_DMA=y +CONFIG_CAMERA_JPEG_MODE_FRAME_SIZE_AUTO=y +# CONFIG_CAMERA_JPEG_MODE_FRAME_SIZE_CUSTOM is not set +# CONFIG_CAMERA_CONVERTER_ENABLED is not set +CONFIG_LCD_CAM_ISR_IRAM_SAFE=y +# end of Camera configuration + +# +# JPEG Decoder +# +CONFIG_JD_USE_ROM=y +# end of JPEG Decoder + +# +# ESP LCD TOUCH +# +CONFIG_ESP_LCD_TOUCH_MAX_POINTS=5 +CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS=1 +# end of ESP LCD TOUCH + +# +# TinyUSB Stack +# +CONFIG_TINYUSB_DEBUG_LEVEL=0 + +# +# TinyUSB DCD +# +# CONFIG_TINYUSB_MODE_SLAVE is not set +CONFIG_TINYUSB_MODE_DMA=y +# end of TinyUSB DCD + +# +# TinyUSB callbacks +# +# CONFIG_TINYUSB_SUSPEND_CALLBACK is not set +# CONFIG_TINYUSB_RESUME_CALLBACK is not set +# end of TinyUSB callbacks + +# +# Descriptor configuration +# + +# +# You can provide your custom descriptors via tinyusb_driver_install() +# +# CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID is not set +CONFIG_TINYUSB_DESC_CUSTOM_VID=0x1234 +# CONFIG_TINYUSB_DESC_USE_DEFAULT_PID is not set +CONFIG_TINYUSB_DESC_CUSTOM_PID=0x5678 +CONFIG_TINYUSB_DESC_BCD_DEVICE=0x0100 +CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="PyroVision" +CONFIG_TINYUSB_DESC_PRODUCT_STRING="ThermalCam Storage" +CONFIG_TINYUSB_DESC_SERIAL_STRING="123456" +CONFIG_TINYUSB_DESC_MSC_STRING="Mass Storage" +# end of Descriptor configuration + +# +# Mass Storage Class (MSC) +# +CONFIG_TINYUSB_MSC_ENABLED=y +CONFIG_TINYUSB_MSC_BUFSIZE=4096 +CONFIG_TINYUSB_MSC_MOUNT_PATH="/data" +# end of Mass Storage Class (MSC) + +# +# Communication Device Class (CDC) +# +# CONFIG_TINYUSB_CDC_ENABLED is not set +# end of Communication Device Class (CDC) + +# +# Musical Instrument Digital Interface (MIDI) +# +CONFIG_TINYUSB_MIDI_COUNT=0 +# end of Musical Instrument Digital Interface (MIDI) + +# +# Human Interface Device Class (HID) +# +CONFIG_TINYUSB_HID_COUNT=0 +# end of Human Interface Device Class (HID) + +# +# Device Firmware Upgrade (DFU) +# +# CONFIG_TINYUSB_DFU_MODE_DFU is not set +# CONFIG_TINYUSB_DFU_MODE_DFU_RUNTIME is not set +CONFIG_TINYUSB_DFU_MODE_NONE=y +# end of Device Firmware Upgrade (DFU) + +# +# Bluetooth Host Class (BTH) +# +# CONFIG_TINYUSB_BTH_ENABLED is not set +# end of Bluetooth Host Class (BTH) + +# +# Network driver (ECM/NCM/RNDIS) +# +# CONFIG_TINYUSB_NET_MODE_ECM_RNDIS is not set +# CONFIG_TINYUSB_NET_MODE_NCM is not set +CONFIG_TINYUSB_NET_MODE_NONE=y +# end of Network driver (ECM/NCM/RNDIS) + +# +# Vendor Specific Interface +# +CONFIG_TINYUSB_VENDOR_COUNT=0 +# end of Vendor Specific Interface +# end of TinyUSB Stack + +# +# LittleFS +# +# CONFIG_LITTLEFS_SDMMC_SUPPORT is not set +CONFIG_LITTLEFS_MAX_PARTITIONS=3 +CONFIG_LITTLEFS_PAGE_SIZE=256 +CONFIG_LITTLEFS_OBJ_NAME_LEN=64 +CONFIG_LITTLEFS_READ_SIZE=128 +CONFIG_LITTLEFS_WRITE_SIZE=128 +CONFIG_LITTLEFS_LOOKAHEAD_SIZE=128 +CONFIG_LITTLEFS_CACHE_SIZE=512 +CONFIG_LITTLEFS_BLOCK_CYCLES=512 +CONFIG_LITTLEFS_USE_MTIME=y +# CONFIG_LITTLEFS_USE_ONLY_HASH is not set +# CONFIG_LITTLEFS_HUMAN_READABLE is not set +CONFIG_LITTLEFS_MTIME_USE_SECONDS=y +# CONFIG_LITTLEFS_MTIME_USE_NONCE is not set +# CONFIG_LITTLEFS_SPIFFS_COMPAT is not set +# CONFIG_LITTLEFS_FLUSH_FILE_EVERY_WRITE is not set +# CONFIG_LITTLEFS_FCNTL_GET_PATH is not set +# CONFIG_LITTLEFS_MULTIVERSION is not set +# CONFIG_LITTLEFS_MALLOC_STRATEGY_DISABLE is not set +CONFIG_LITTLEFS_MALLOC_STRATEGY_DEFAULT=y +# CONFIG_LITTLEFS_MALLOC_STRATEGY_INTERNAL is not set +# CONFIG_LITTLEFS_MALLOC_STRATEGY_SPIRAM is not set +CONFIG_LITTLEFS_ASSERTS=y +# CONFIG_LITTLEFS_MMAP_PARTITION is not set +# CONFIG_LITTLEFS_WDT_RESET is not set +# end of LittleFS + +# +# LVGL configuration +# +CONFIG_LV_CONF_SKIP=y +# CONFIG_LV_CONF_MINIMAL is not set + +# +# Color Settings +# +# CONFIG_LV_COLOR_DEPTH_32 is not set +# CONFIG_LV_COLOR_DEPTH_24 is not set +CONFIG_LV_COLOR_DEPTH_16=y +# CONFIG_LV_COLOR_DEPTH_8 is not set +# CONFIG_LV_COLOR_DEPTH_1 is not set +CONFIG_LV_COLOR_DEPTH=16 +# end of Color Settings + +# +# Memory Settings +# +# CONFIG_LV_USE_BUILTIN_MALLOC is not set +CONFIG_LV_USE_CLIB_MALLOC=y +# CONFIG_LV_USE_MICROPYTHON_MALLOC is not set +# CONFIG_LV_USE_RTTHREAD_MALLOC is not set +# CONFIG_LV_USE_CUSTOM_MALLOC is not set +# CONFIG_LV_USE_BUILTIN_STRING is not set +CONFIG_LV_USE_CLIB_STRING=y +# CONFIG_LV_USE_CUSTOM_STRING is not set +# CONFIG_LV_USE_BUILTIN_SPRINTF is not set +CONFIG_LV_USE_CLIB_SPRINTF=y +# CONFIG_LV_USE_CUSTOM_SPRINTF is not set +# end of Memory Settings + +# +# HAL Settings +# +CONFIG_LV_DEF_REFR_PERIOD=33 +CONFIG_LV_DPI_DEF=130 +# end of HAL Settings + +# +# Operating System (OS) +# +CONFIG_LV_OS_NONE=y +# CONFIG_LV_OS_PTHREAD is not set +# CONFIG_LV_OS_FREERTOS is not set +# CONFIG_LV_OS_CMSIS_RTOS2 is not set +# CONFIG_LV_OS_RTTHREAD is not set +# CONFIG_LV_OS_WINDOWS is not set +# CONFIG_LV_OS_MQX is not set +# CONFIG_LV_OS_SDL2 is not set +# CONFIG_LV_OS_CUSTOM is not set +# end of Operating System (OS) + +# +# Rendering Configuration +# +CONFIG_LV_DRAW_BUF_STRIDE_ALIGN=1 +CONFIG_LV_DRAW_BUF_ALIGN=4 +CONFIG_LV_DRAW_LAYER_SIMPLE_BUF_SIZE=24576 +CONFIG_LV_DRAW_LAYER_MAX_MEMORY=0 +CONFIG_LV_USE_DRAW_SW=y +CONFIG_LV_DRAW_SW_SUPPORT_RGB565=y +CONFIG_LV_DRAW_SW_SUPPORT_RGB565A8=y +CONFIG_LV_DRAW_SW_SUPPORT_RGB888=y +CONFIG_LV_DRAW_SW_SUPPORT_XRGB8888=y +CONFIG_LV_DRAW_SW_SUPPORT_ARGB8888=y +CONFIG_LV_DRAW_SW_SUPPORT_ARGB8888_PREMULTIPLIED=y +CONFIG_LV_DRAW_SW_SUPPORT_L8=y +CONFIG_LV_DRAW_SW_SUPPORT_AL88=y +CONFIG_LV_DRAW_SW_SUPPORT_A8=y +CONFIG_LV_DRAW_SW_SUPPORT_I1=y +CONFIG_LV_DRAW_SW_I1_LUM_THRESHOLD=127 +CONFIG_LV_DRAW_SW_DRAW_UNIT_CNT=1 +# CONFIG_LV_USE_DRAW_ARM2D_SYNC is not set +# CONFIG_LV_USE_NATIVE_HELIUM_ASM is not set +CONFIG_LV_DRAW_SW_COMPLEX=y +# CONFIG_LV_USE_DRAW_SW_COMPLEX_GRADIENTS is not set +CONFIG_LV_DRAW_SW_SHADOW_CACHE_SIZE=0 +CONFIG_LV_DRAW_SW_CIRCLE_CACHE_SIZE=4 +CONFIG_LV_DRAW_SW_ASM_NONE=y +# CONFIG_LV_DRAW_SW_ASM_NEON is not set +# CONFIG_LV_DRAW_SW_ASM_HELIUM is not set +# CONFIG_LV_DRAW_SW_ASM_CUSTOM is not set +CONFIG_LV_USE_DRAW_SW_ASM=0 +# CONFIG_LV_USE_PXP is not set +# CONFIG_LV_USE_G2D is not set +# CONFIG_LV_USE_DRAW_DAVE2D is not set +# CONFIG_LV_USE_DRAW_SDL is not set +# CONFIG_LV_USE_DRAW_VG_LITE is not set +# CONFIG_LV_USE_VECTOR_GRAPHIC is not set +# CONFIG_LV_USE_DRAW_DMA2D is not set +# CONFIG_LV_USE_PPA is not set +# CONFIG_LV_USE_DRAW_EVE is not set +# end of Rendering Configuration + +# +# Feature Configuration +# + +# +# Logging +# +# CONFIG_LV_USE_LOG is not set +# end of Logging + +# +# Asserts +# +CONFIG_LV_USE_ASSERT_NULL=y +CONFIG_LV_USE_ASSERT_MALLOC=y +# CONFIG_LV_USE_ASSERT_STYLE is not set +# CONFIG_LV_USE_ASSERT_MEM_INTEGRITY is not set +# CONFIG_LV_USE_ASSERT_OBJ is not set +CONFIG_LV_ASSERT_HANDLER_INCLUDE="assert.h" +# end of Asserts + +# +# Debug +# +# CONFIG_LV_USE_REFR_DEBUG is not set +# CONFIG_LV_USE_LAYER_DEBUG is not set +# CONFIG_LV_USE_PARALLEL_DRAW_DEBUG is not set +# end of Debug + +# +# Others +# +# CONFIG_LV_ENABLE_GLOBAL_CUSTOM is not set +CONFIG_LV_CACHE_DEF_SIZE=0 +CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT=0 +CONFIG_LV_GRADIENT_MAX_STOPS=2 +CONFIG_LV_COLOR_MIX_ROUND_OFS=128 +# CONFIG_LV_OBJ_STYLE_CACHE is not set +# CONFIG_LV_USE_OBJ_ID is not set +# CONFIG_LV_USE_OBJ_NAME is not set +# CONFIG_LV_USE_OBJ_PROPERTY is not set +# end of Others +# end of Feature Configuration + +# +# Compiler Settings +# +# CONFIG_LV_BIG_ENDIAN_SYSTEM is not set +CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE=1 +CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y +# CONFIG_LV_USE_FLOAT is not set +# CONFIG_LV_USE_MATRIX is not set +# CONFIG_LV_USE_PRIVATE_API is not set +# end of Compiler Settings + +# +# Font Usage +# + +# +# Enable built-in fonts +# +CONFIG_LV_FONT_MONTSERRAT_8=y +CONFIG_LV_FONT_MONTSERRAT_10=y +CONFIG_LV_FONT_MONTSERRAT_12=y +CONFIG_LV_FONT_MONTSERRAT_14=y +# CONFIG_LV_FONT_MONTSERRAT_16 is not set +# CONFIG_LV_FONT_MONTSERRAT_18 is not set +# CONFIG_LV_FONT_MONTSERRAT_20 is not set +# CONFIG_LV_FONT_MONTSERRAT_22 is not set +# CONFIG_LV_FONT_MONTSERRAT_24 is not set +# CONFIG_LV_FONT_MONTSERRAT_26 is not set +# CONFIG_LV_FONT_MONTSERRAT_28 is not set +# CONFIG_LV_FONT_MONTSERRAT_30 is not set +CONFIG_LV_FONT_MONTSERRAT_32=y +# CONFIG_LV_FONT_MONTSERRAT_34 is not set +# CONFIG_LV_FONT_MONTSERRAT_36 is not set +# CONFIG_LV_FONT_MONTSERRAT_38 is not set +# CONFIG_LV_FONT_MONTSERRAT_40 is not set +# CONFIG_LV_FONT_MONTSERRAT_42 is not set +# CONFIG_LV_FONT_MONTSERRAT_44 is not set +# CONFIG_LV_FONT_MONTSERRAT_46 is not set +CONFIG_LV_FONT_MONTSERRAT_48=y +# CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED is not set +# CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW is not set +# CONFIG_LV_FONT_SOURCE_HAN_SANS_SC_14_CJK is not set +# CONFIG_LV_FONT_SOURCE_HAN_SANS_SC_16_CJK is not set +# CONFIG_LV_FONT_UNSCII_8 is not set +# CONFIG_LV_FONT_UNSCII_16 is not set +# end of Enable built-in fonts + +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_10 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12 is not set +CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14=y +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_16 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_18 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_20 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_22 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_24 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_30 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_32 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_34 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_36 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_38 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_40 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_42 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_44 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_46 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_48 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28_COMPRESSED is not set +# CONFIG_LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW is not set +# CONFIG_LV_FONT_DEFAULT_SOURCE_HAN_SANS_SC_14_CJK is not set +# CONFIG_LV_FONT_DEFAULT_SOURCE_HAN_SANS_SC_16_CJK is not set +# CONFIG_LV_FONT_DEFAULT_UNSCII_8 is not set +# CONFIG_LV_FONT_DEFAULT_UNSCII_16 is not set +# CONFIG_LV_FONT_FMT_TXT_LARGE is not set +# CONFIG_LV_USE_FONT_COMPRESSED is not set +CONFIG_LV_USE_FONT_PLACEHOLDER=y + +# +# Enable static fonts +# +# end of Enable static fonts +# end of Font Usage + +# +# Text Settings +# +CONFIG_LV_TXT_ENC_UTF8=y +# CONFIG_LV_TXT_ENC_ASCII is not set +CONFIG_LV_TXT_BREAK_CHARS=" ,.;:-_)}" +CONFIG_LV_TXT_LINE_BREAK_LONG_LEN=0 +CONFIG_LV_TXT_COLOR_CMD="#" +# CONFIG_LV_USE_BIDI is not set +# CONFIG_LV_USE_ARABIC_PERSIAN_CHARS is not set +# end of Text Settings + +# +# Widget Usage +# +CONFIG_LV_WIDGETS_HAS_DEFAULT_VALUE=y +CONFIG_LV_USE_ANIMIMG=y +CONFIG_LV_USE_ARC=y +CONFIG_LV_USE_ARCLABEL=y +CONFIG_LV_USE_BAR=y +CONFIG_LV_USE_BUTTON=y +CONFIG_LV_USE_BUTTONMATRIX=y +# CONFIG_LV_USE_CALENDAR is not set +CONFIG_LV_USE_CANVAS=y +CONFIG_LV_USE_CHART=y +CONFIG_LV_USE_CHECKBOX=y +CONFIG_LV_USE_DROPDOWN=y +CONFIG_LV_USE_IMAGE=y +CONFIG_LV_USE_IMAGEBUTTON=y +CONFIG_LV_USE_KEYBOARD=y +CONFIG_LV_USE_LABEL=y +CONFIG_LV_LABEL_TEXT_SELECTION=y +CONFIG_LV_LABEL_LONG_TXT_HINT=y +CONFIG_LV_LABEL_WAIT_CHAR_COUNT=3 +CONFIG_LV_USE_LED=y +CONFIG_LV_USE_LINE=y +CONFIG_LV_USE_LIST=y +CONFIG_LV_USE_MENU=y +CONFIG_LV_USE_MSGBOX=y +CONFIG_LV_USE_ROLLER=y +CONFIG_LV_USE_SCALE=y +CONFIG_LV_USE_SLIDER=y +CONFIG_LV_USE_SPAN=y +CONFIG_LV_SPAN_SNIPPET_STACK_SIZE=64 +CONFIG_LV_USE_SPINBOX=y +CONFIG_LV_USE_SPINNER=y +CONFIG_LV_USE_SWITCH=y +CONFIG_LV_USE_TEXTAREA=y +CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME=1500 +CONFIG_LV_USE_TABLE=y +CONFIG_LV_USE_TABVIEW=y +CONFIG_LV_USE_TILEVIEW=y +CONFIG_LV_USE_WIN=y +# end of Widget Usage + +# +# Themes +# +CONFIG_LV_USE_THEME_DEFAULT=y +# CONFIG_LV_THEME_DEFAULT_DARK is not set +CONFIG_LV_THEME_DEFAULT_GROW=y +CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME=80 +CONFIG_LV_USE_THEME_SIMPLE=y +# CONFIG_LV_USE_THEME_MONO is not set +# end of Themes + +# +# Layouts +# +CONFIG_LV_USE_FLEX=y +CONFIG_LV_USE_GRID=y +# end of Layouts + +# +# 3rd Party Libraries +# +CONFIG_LV_FS_DEFAULT_DRIVER_LETTER=0 +# CONFIG_LV_USE_FS_STDIO is not set +# CONFIG_LV_USE_FS_POSIX is not set +# CONFIG_LV_USE_FS_WIN32 is not set +# CONFIG_LV_USE_FS_FATFS is not set +# CONFIG_LV_USE_FS_MEMFS is not set +# CONFIG_LV_USE_FS_LITTLEFS is not set +# CONFIG_LV_USE_FS_ARDUINO_ESP_LITTLEFS is not set +# CONFIG_LV_USE_FS_ARDUINO_SD is not set +# CONFIG_LV_USE_FS_UEFI is not set +# CONFIG_LV_USE_FS_FROGFS is not set +# CONFIG_LV_USE_LODEPNG is not set +# CONFIG_LV_USE_LIBPNG is not set +# CONFIG_LV_USE_BMP is not set +# CONFIG_LV_USE_TJPGD is not set +# CONFIG_LV_USE_LIBJPEG_TURBO is not set +# CONFIG_LV_USE_GIF is not set +# CONFIG_LV_BIN_DECODER_RAM_LOAD is not set +# CONFIG_LV_USE_RLE is not set +# CONFIG_LV_USE_QRCODE is not set +# CONFIG_LV_USE_BARCODE is not set +# CONFIG_LV_USE_FREETYPE is not set +# CONFIG_LV_USE_TINY_TTF is not set +# CONFIG_LV_USE_RLOTTIE is not set +# CONFIG_LV_USE_THORVG is not set +# CONFIG_LV_USE_LZ4 is not set +# CONFIG_LV_USE_FFMPEG is not set +# end of 3rd Party Libraries + +# +# Others +# +# CONFIG_LV_USE_SNAPSHOT is not set +# CONFIG_LV_USE_SYSMON is not set +# CONFIG_LV_USE_PROFILER is not set +# CONFIG_LV_USE_MONKEY is not set +# CONFIG_LV_USE_GRIDNAV is not set +# CONFIG_LV_USE_FRAGMENT is not set +# CONFIG_LV_USE_IMGFONT is not set +CONFIG_LV_USE_OBSERVER=y +# CONFIG_LV_USE_IME_PINYIN is not set +# CONFIG_LV_USE_FILE_EXPLORER is not set +# CONFIG_LV_USE_FONT_MANAGER is not set +# CONFIG_LV_USE_TEST is not set +# CONFIG_LV_USE_TRANSLATION is not set +# CONFIG_LV_USE_XML is not set +# CONFIG_LV_USE_COLOR_FILTER is not set +CONFIG_LVGL_VERSION_MAJOR=9 +CONFIG_LVGL_VERSION_MINOR=4 +CONFIG_LVGL_VERSION_PATCH=0 +# end of Others + +# +# Devices +# +# CONFIG_LV_USE_SDL is not set +# CONFIG_LV_USE_X11 is not set +# CONFIG_LV_USE_WAYLAND is not set +# CONFIG_LV_USE_LINUX_FBDEV is not set +# CONFIG_LV_USE_NUTTX is not set +# CONFIG_LV_USE_LINUX_DRM is not set +# CONFIG_LV_USE_TFT_ESPI is not set +# CONFIG_LV_USE_LOVYAN_GFX is not set +# CONFIG_LV_USE_EVDEV is not set +# CONFIG_LV_USE_LIBINPUT is not set +# CONFIG_LV_USE_ST7735 is not set +# CONFIG_LV_USE_ST7789 is not set +# CONFIG_LV_USE_ST7796 is not set +# CONFIG_LV_USE_ILI9341 is not set +# CONFIG_LV_USE_GENERIC_MIPI is not set +# CONFIG_LV_USE_NXP_ELCDIF is not set +# CONFIG_LV_USE_RENESAS_GLCDC is not set +# CONFIG_LV_USE_ST_LTDC is not set +# CONFIG_LV_USE_FT81X is not set +# CONFIG_LV_USE_UEFI is not set +# CONFIG_LV_USE_OPENGLES is not set +# CONFIG_LV_USE_QNX is not set +# end of Devices + +# +# Examples +# +# CONFIG_LV_BUILD_EXAMPLES is not set +# end of Examples + +# +# Demos +# +# CONFIG_LV_BUILD_DEMOS is not set +# end of Demos +# end of LVGL configuration +# end of Component config + +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set + +# Deprecated options for backward compatibility +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_EXTERNAL_COEX_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_GDBSTUB_SUPPORT_TASKS=y +CONFIG_GDBSTUB_MAX_TASKS=32 +# CONFIG_OTA_ALLOW_HTTP is not set +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_7=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_REDUCE_PHY_TX_POWER is not set +# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=8192 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_IPC_TASK_STACK_SIZE=1280 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=y +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE is not set +# CONFIG_ESP32_COREDUMP_DATA_FORMAT_BIN is not set +CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF=y +CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32=y +# CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 is not set +CONFIG_ESP32_ENABLE_COREDUMP=y +CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM=64 +CONFIG_ESP32_CORE_DUMP_STACK_SIZE=1792 +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5760 +CONFIG_TCP_WND_DEFAULT=5760 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/ui/PyroVision.sll b/ui/PyroVision.sll index 107daa2..ad3b9d9 100644 --- a/ui/PyroVision.sll +++ b/ui/PyroVision.sll @@ -25,7 +25,7 @@ "custom_variable_prefix": "uic", "separate_screen_save": false, "hierarchy_state_save": false, - "backup_cnt": 92, + "backup_cnt": 96, "autosave_cnt": 0, "group_color_cnt": 0, "imagebytearrayprefix": "", @@ -36,5 +36,5 @@ "naming": "Screen_Name", "naming_force_lowercase": false, "naming_add_subcomponent": false, - "nidcnt": 1001743 + "nidcnt": 1001753 } \ No newline at end of file diff --git a/ui/PyroVision.spj b/ui/PyroVision.spj index c5e75c4..83c8c66 100644 --- a/ui/PyroVision.spj +++ b/ui/PyroVision.spj @@ -1355,59 +1355,59 @@ }, { "disabled": false, - "nid": 1001723, + "nid": 1001743, "strtype": "_event/EventHandler", "strval": "SCREEN_LOADED", "childs": [ { - "nid": 1001724, + "nid": 1001744, "strtype": "_event/name", "strval": "ScreenSplashLoaded", "InheritedType": 10 }, { - "nid": 1001725, + "nid": 1001745, "strtype": "_event/condition_C", "strval": "", "InheritedType": 10 }, { - "nid": 1001726, + "nid": 1001746, "strtype": "_event/condition_P", "strval": "", "InheritedType": 10 }, { - "nid": 1001727, + "nid": 1001747, "strtype": "_event/action", "strval": "CALL FUNCTION", "childs": [ { - "nid": 1001728, + "nid": 1001748, "strtype": "CALL FUNCTION/Name", "strval": "CALL FUNCTION", "InheritedType": 10 }, { - "nid": 1001729, + "nid": 1001749, "strtype": "CALL FUNCTION/Call", "strval": "<{Function_name}>( event_struct )", "InheritedType": 10 }, { - "nid": 1001730, + "nid": 1001750, "strtype": "CALL FUNCTION/CallC", "strval": "<{Function_name}>( e );", "InheritedType": 10 }, { - "nid": 1001731, + "nid": 1001751, "strtype": "CALL FUNCTION/Function_name", - "strval": "ScreenSplahLoaded", + "strval": "ScreenSplashLoaded", "InheritedType": 10 }, { - "nid": 1001732, + "nid": 1001752, "strtype": "CALL FUNCTION/Dont_export_function", "strval": "False", "InheritedType": 2 @@ -5240,7 +5240,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Label Main Button WiFi", + "strval": "Label Main Button Save", "InheritedType": 10 }, { @@ -5365,7 +5365,7 @@ { "nid": 1030, "strtype": "LABEL/Text", - "strval": "W", + "strval": "S", "InheritedType": 10 }, { @@ -5410,7 +5410,7 @@ { "nid": 10, "strtype": "OBJECT/Name", - "strval": "Button Main WiFi", + "strval": "Button Main Save", "InheritedType": 10 }, { @@ -5441,7 +5441,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - -20, + 100, 0 ], "InheritedType": 7 @@ -5591,7 +5591,7 @@ { "nid": 1000442, "strtype": "_event/name", - "strval": "ButtonMainWiFiClicked", + "strval": "ButtonMainSaveClicked", "InheritedType": 10 }, { @@ -5632,7 +5632,7 @@ { "nid": 1000449, "strtype": "CALL FUNCTION/Function_name", - "strval": "ButtonMainWiFiClicked", + "strval": "ButtonMainSaveClicked", "InheritedType": 10 }, { @@ -5860,7 +5860,7 @@ "flags": 17, "strtype": "OBJECT/Position", "intarray": [ - 100, + -20, 0 ], "InheritedType": 7 @@ -18765,7 +18765,7 @@ "custom_variable_prefix": "uic", "separate_screen_save": false, "hierarchy_state_save": false, - "backup_cnt": 92, + "backup_cnt": 96, "autosave_cnt": 0, "group_color_cnt": 0, "imagebytearrayprefix": null, @@ -18776,7 +18776,7 @@ "naming": "Screen_Name", "naming_force_lowercase": false, "naming_add_subcomponent": false, - "nidcnt": 1001743, + "nidcnt": 1001753, "BitDepth": 16, "Name": "SquareLine_Project" } diff --git a/ui/PyroVision_events.py b/ui/PyroVision_events.py index 1563400..2adcf99 100644 --- a/ui/PyroVision_events.py +++ b/ui/PyroVision_events.py @@ -58,3 +58,11 @@ def ScreenSplashLoaded(event_struct): def ButtonMenuSaveClicked(event_struct): return + +def ScreenSplahLoaded(event_struct): + return + + +def ButtonMainSaveClicked(event_struct): + return + diff --git a/ui/project.info b/ui/project.info index b30e35d..ef7f898 100644 --- a/ui/project.info +++ b/ui/project.info @@ -1,7 +1,7 @@ { "project_name": "SquareLine_Project.spj", - "datetime": "2026-02-07T12:27:13.6536638+01:00", + "datetime": "2026-02-07T23:00:07.4624365+01:00", "editor_version": "1.6.0", - "project_version": 106, + "project_version": 109, "user": "Kampert Daniel" } \ No newline at end of file From ccc89f2c2168c89bb38755430061b2866b757f71 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Wed, 11 Feb 2026 13:02:13 +0100 Subject: [PATCH 13/26] Add documentation for the remote control --- README.md | 5 +++++ Remote-Control.md | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 Remote-Control.md diff --git a/README.md b/README.md index c0f09ef..d3ee333 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - [Table of Contents](#table-of-contents) - [License](#license) - [Color palette](#color-palette) + - [VISA and HTTP / WebSocket interface](#visa-and-http--websocket-interface) - [Maintainer](#maintainer) ## License @@ -31,6 +32,10 @@ See [LICENSE](LICENSE) for full text. | Light Red/Orange | #FF6F3C | Accent color | | Dark Gray/Black | #1E1E1E | Background color | +## VISA and HTTP / WebSocket interface + +The camera can use a VISA and / or HTTP / Websocket interface for communication. Please read the [documentation](Remote-Control.md) for additional informations about it. + ## Maintainer **Daniel Kampert** diff --git a/Remote-Control.md b/Remote-Control.md new file mode 100644 index 0000000..3f79445 --- /dev/null +++ b/Remote-Control.md @@ -0,0 +1,36 @@ +# Lepton - Remote-Control + +## Table of Contents + +- [Lepton - Remote-Control](#lepton---remote-control) + - [Table of Contents](#table-of-contents) + - [Available parameters](#available-parameters) + - [Maintainer](#maintainer) + +## Available parameters + +| Parameter | Description | Methods | +|-------------------------|------------------------------------------|----------| +| Temperature Sensor Value| Temperature from the TMP117 sensor | GET | +| Time | Current system time | GET, SET | +| Battery Voltage | Voltage of the battery | GET | +| State-Of-Charge | Battery state of charge | GET | +| OV5640 Image | Image from OV5640 camera | GET | +| Lepton Image | Image from Lepton camera | GET | +| Lepton Emissivity | Emissivity of Lepton camera | GET, SET | +| Lepton Scene Statistics | Scene statistics from Lepton | GET | +| Lepton ROI | Region of Interest for Lepton | GET, SET | +| Lepton Spotmeter | Spotmeter data from Lepton | GET | +| Flash Power | Power of the flash | GET, SET | +| Flash On / Off | Flash state | GET, SET | +| Image Format | File format of the output images | GET, SET | +| Status LED | Set the Status LED | SET | +| State SD card | Checks if an SD card is available | GET | +| Format | Format the active memory (internal flash or SD card) | SET | +| Messagebox Display | Display a message box with a given text | SET | + +## Maintainer + +**Daniel Kampert** +📧 [DanielKampert@kampis-elektroecke.de](mailto:DanielKampert@kampis-elektroecke.de) +🌐 [www.kampis-elektroecke.de](https://www.kampis-elektroecke.de) \ No newline at end of file From a729e334c3bfdacd63b3de49c79b96d42a28e778 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Wed, 11 Feb 2026 14:26:17 +0100 Subject: [PATCH 14/26] Add common interface for VISA and WebSockets --- Remote-Control.md | 142 ++++- data/settings_default.json | 3 +- docs/SettingsManager.adoc | 2 +- .../Server/RemoteControl/remoteControl.cpp | 469 ++++++++++++++++ .../Server/RemoteControl/remoteControl.h | 247 +++++++++ .../Server/VISA/Private/visaCommands.cpp | 83 ++- .../VISA/Private/visaRemoteCommands.cpp | 495 +++++++++++++++++ .../Server/VISA/Private/visaRemoteCommands.h | 208 +++++++ .../Private/websocketRemoteHandlers.cpp | 512 ++++++++++++++++++ .../Private/websocketRemoteHandlers.h | 163 ++++++ .../Network/Server/WebSocket/websocket.cpp | 47 +- .../Network/Server/WebSocket/websocket.h | 1 + .../Private/settingsDefaultLoader.cpp | 3 +- .../Settings/Private/settingsJSONLoader.cpp | 21 +- .../Manager/Settings/settingsManager.cpp | 24 +- .../Manager/Settings/settingsManager.h | 72 ++- .../Manager/Settings/settingsTypes.h | 14 +- main/Application/Tasks/GUI/UI/ui_Settings.cpp | 2 +- .../Application/Tasks/Network/networkTask.cpp | 10 +- main/Application/application.h | 2 +- 20 files changed, 2461 insertions(+), 59 deletions(-) create mode 100644 main/Application/Manager/Network/Server/RemoteControl/remoteControl.cpp create mode 100644 main/Application/Manager/Network/Server/RemoteControl/remoteControl.h create mode 100644 main/Application/Manager/Network/Server/VISA/Private/visaRemoteCommands.cpp create mode 100644 main/Application/Manager/Network/Server/VISA/Private/visaRemoteCommands.h create mode 100644 main/Application/Manager/Network/Server/WebSocket/Private/websocketRemoteHandlers.cpp create mode 100644 main/Application/Manager/Network/Server/WebSocket/Private/websocketRemoteHandlers.h diff --git a/Remote-Control.md b/Remote-Control.md index 3f79445..99b5d03 100644 --- a/Remote-Control.md +++ b/Remote-Control.md @@ -5,6 +5,16 @@ - [Lepton - Remote-Control](#lepton---remote-control) - [Table of Contents](#table-of-contents) - [Available parameters](#available-parameters) + - [VISA SCPI Commands](#visa-scpi-commands) + - [System Commands](#system-commands) + - [Sensor Commands](#sensor-commands) + - [Display Commands](#display-commands) + - [Memory Commands](#memory-commands) + - [WebSocket Commands](#websocket-commands) + - [Request Format](#request-format) + - [Response Format](#response-format) + - [Available Commands](#available-commands) + - [Example WebSocket Session](#example-websocket-session) - [Maintainer](#maintainer) ## Available parameters @@ -23,11 +33,139 @@ | Lepton Spotmeter | Spotmeter data from Lepton | GET | | Flash Power | Power of the flash | GET, SET | | Flash On / Off | Flash state | GET, SET | -| Image Format | File format of the output images | GET, SET | -| Status LED | Set the Status LED | SET | +| Image Format | File format of the output images (PNG, Raw, JPEG) | GET, SET | +| Status LED | Set the Status LED (Red, Green, Blue) | SET | | State SD card | Checks if an SD card is available | GET | | Format | Format the active memory (internal flash or SD card) | SET | | Messagebox Display | Display a message box with a given text | SET | +| Lock | Lock the input buttons and the joystick | GET, SET | + +### VISA SCPI Commands + +The VISA server (port 5025) supports the following SCPI commands: + +#### System Commands + +| Command | Description | Example | +|-------------------|----------------------------------|----------------------------------| +| `*IDN?` | Get device identification | `*IDN?` | +| `*RST` | Reset device | `*RST` | +| `SYST:TIME?` | Get current system time | `SYST:TIME?` | +| `SYST:TIME` | Set system time (ISO 8601) | `SYST:TIME 2026-01-15T12:30:00` | +| `SYST:LOCK?` | Get input lock state | `SYST:LOCK?` | +| `SYST:LOCK` | Set input lock state | `SYST:LOCK LOCKED` | + +#### Sensor Commands + +| Command | Description | Example | +|--------------------------|----------------------------------|----------------------------------| +| `SENS:TEMP?` | Get temperature sensor value | `SENS:TEMP?` | +| `SENS:BATT:VOLT?` | Get battery voltage | `SENS:BATT:VOLT?` | +| `SENS:BATT:SOC?` | Get battery state of charge | `SENS:BATT:SOC?` | +| `SENS:IMG:FORM?` | Get image format | `SENS:IMG:FORM?` | +| `SENS:IMG:FORM` | Set image format | `SENS:IMG:FORM JPEG` | +| `SENS:IMG:LEP:EMIS?` | Get Lepton emissivity | `SENS:IMG:LEP:EMIS?` | +| `SENS:IMG:LEP:EMIS` | Set Lepton emissivity (0-100) | `SENS:IMG:LEP:EMIS 98` | +| `SENS:IMG:LEP:STAT?` | Get Lepton scene statistics | `SENS:IMG:LEP:STAT?` | +| `SENS:IMG:LEP:ROI?` | Get Lepton ROI | `SENS:IMG:LEP:ROI?` | +| `SENS:IMG:LEP:ROI` | Set Lepton ROI (JSON) | `SENS:IMG:LEP:ROI {"x":40,...}` | +| `SENS:IMG:LEP:SPOT?` | Get Lepton spotmeter data | `SENS:IMG:LEP:SPOT?` | + +#### Display Commands + +| Command | Description | Example | +|--------------------------|----------------------------------|----------------------------------| +| `DISP:LED:STAT` | Set status LED | `DISP:LED:STAT RED 255` | +| `DISP:FLASH:POW?` | Get flash power | `DISP:FLASH:POW?` | +| `DISP:FLASH:POW` | Set flash power (0-100) | `DISP:FLASH:POW 50` | +| `DISP:FLASH:STAT?` | Get flash state | `DISP:FLASH:STAT?` | +| `DISP:FLASH:STAT` | Set flash state | `DISP:FLASH:STAT ON` | +| `DISP:MBOX` | Display message box | `DISP:MBOX "Hello World"` | + +#### Memory Commands + +| Command | Description | Example | +|-------------------|----------------------------------|----------------------------------| +| `MEM:SD:STAT?` | Check SD card availability | `MEM:SD:STAT?` | +| `MEM:FORM` | Format active memory | `MEM:FORM` | + +### WebSocket Commands + +The WebSocket endpoint (`ws://device-ip/ws`) supports JSON-formatted commands: + +#### Request Format + +```json +{ + "cmd": "command_name", + "data": { + // command-specific data + } +} +``` + +#### Response Format + +```json +{ + "cmd": "command_name", + "status": "ok|error", + "data": { + // response data + }, + "error": "error message (if status=error)" +} +``` + +#### Available Commands + +| Command | Description | Request Data | +|----------------------------|----------------------------------|----------------------------------| +| `get_temperature` | Get temperature sensor value | - | +| `get_time` | Get current system time | - | +| `set_time` | Set system time | `{"time": "ISO8601"}` | +| `get_battery` | Get battery voltage and SOC | - | +| `get_lepton_emissivity` | Get Lepton emissivity | - | +| `set_lepton_emissivity` | Set Lepton emissivity | `{"emissivity": 98}` | +| `get_lepton_stats` | Get Lepton scene statistics | - | +| `get_lepton_roi` | Get Lepton ROI | - | +| `set_lepton_roi` | Set Lepton ROI | `{"x":40,"y":30,"width":80,...}` | +| `get_lepton_spotmeter` | Get Lepton spotmeter data | - | +| `get_flash` | Get flash state and power | - | +| `set_flash` | Set flash state/power | `{"enabled":true,"power":50}` | +| `get_image_format` | Get current image format | - | +| `set_image_format` | Set image format | `{"format":"JPEG"}` | +| `set_status_led` | Set status LED | `{"color":"RED","brightness":255}`| +| `get_sd_state` | Check SD card availability | - | +| `format_memory` | Format active memory | - | +| `display_message` | Display message box | `{"message":"Hello World"}` | +| `get_lock` | Get input lock state | - | +| `set_lock` | Set input lock state | `{"locked":true}` | + +#### Example WebSocket Session + +```javascript +// Connect to WebSocket +const ws = new WebSocket('ws://192.168.1.100/ws'); + +// Get temperature +ws.send(JSON.stringify({ + cmd: "get_temperature", + data: {} +})); + +// Response: +// {"cmd":"temperature","status":"ok","data":{"temperature":25.3}} + +// Set Lepton emissivity +ws.send(JSON.stringify({ + cmd: "set_lepton_emissivity", + data: {"emissivity": 98} +})); + +// Response: +// {"cmd":"set_lepton_emissivity","status":"ok"} +``` ## Maintainer diff --git a/data/settings_default.json b/data/settings_default.json index 52b20db..045ecb0 100644 --- a/data/settings_default.json +++ b/data/settings_default.json @@ -67,7 +67,8 @@ }, "system" : { "timezone" : "CET-1CEST,M3.5.0,M10.5.0/3", - "ntp-server" : "pool.ntp.org" + "ntp-server" : "pool.ntp.org", + "imageFormat" : "JPEG" }, "http-server" : { "port" : 80, diff --git a/docs/SettingsManager.adoc b/docs/SettingsManager.adoc index 93be84f..88b42a3 100644 --- a/docs/SettingsManager.adoc +++ b/docs/SettingsManager.adoc @@ -70,7 +70,7 @@ The settings are divided into the following categories: typedef struct { App_Settings_ROI_t ROI[4]; // Camera ROIs App_Settings_Emissivity_t EmissivityPresets[128]; // Emissivity presets - size_t EmissivityCount; // Number of presets + size_t EmissivityPresetsCount; // Number of presets } App_Settings_Lepton_t; ---- diff --git a/main/Application/Manager/Network/Server/RemoteControl/remoteControl.cpp b/main/Application/Manager/Network/Server/RemoteControl/remoteControl.cpp new file mode 100644 index 0000000..589a7b6 --- /dev/null +++ b/main/Application/Manager/Network/Server/RemoteControl/remoteControl.cpp @@ -0,0 +1,469 @@ +/* + * remoteControl.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Common remote control interface implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include +#include +#include + +#include "remoteControl.h" +#include "../../../Time/timeManager.h" +#include "../../../Devices/devicesManager.h" +#include "../../../Settings/settingsManager.h" +#include "../../../Memory/memoryManager.h" +#include "../../../../Tasks/tasks.h" + +static const char *TAG = "RemoteControl"; + +typedef struct { + App_Lepton_ROI_Result_t Spotmeter; + SemaphoreHandle_t Mutex; + bool isValid; +} RemoteControl_State_t; + +static RemoteControl_State_t _RemoteControl_State; + +esp_err_t RemoteControl_GetTemperature(float *p_Temperature) +{ + if (p_Temperature == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get temperature from TMP117 via DevicesManager */ + *p_Temperature = 25.0f; /* Placeholder */ + + return ESP_OK; +} + +esp_err_t RemoteControl_GetTime(char *p_TimeStr, size_t MaxLen) +{ + time_t Now; + struct tm TimeInfo; + + if (p_TimeStr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + time(&Now); + localtime_r(&Now, &TimeInfo); + + /* ISO 8601 format: YYYY-MM-DDTHH:MM:SS */ + strftime(p_TimeStr, MaxLen, "%Y-%m-%dT%H:%M:%S", &TimeInfo); + + return ESP_OK; +} + +esp_err_t RemoteControl_SetTime(const char *p_TimeStr) +{ + struct tm TimeInfo; + time_t NewTime; + + if (p_TimeStr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Parse ISO 8601 format: YYYY-MM-DDTHH:MM:SS */ + if (strptime(p_TimeStr, "%Y-%m-%dT%H:%M:%S", &TimeInfo) == NULL) { + ESP_LOGE(TAG, "Invalid time format. Expected: YYYY-MM-DDTHH:MM:SS"); + return ESP_ERR_INVALID_ARG; + } + + NewTime = mktime(&TimeInfo); + if (NewTime == -1) { + ESP_LOGE(TAG, "Failed to convert time!"); + + return ESP_ERR_INVALID_ARG; + } + + /* Set system time */ + struct timeval tv = { + .tv_sec = NewTime, + .tv_usec = 0, + }; + + settimeofday(&tv, NULL); + + ESP_LOGD(TAG, "System time set to: %s", p_TimeStr); + + return ESP_OK; +} + +esp_err_t RemoteControl_GetBatteryVoltage(float *p_Voltage) +{ + if (p_Voltage == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get battery voltage from ADC via DevicesManager */ + *p_Voltage = 3.7f; /* Placeholder */ + + return ESP_OK; +} + +esp_err_t RemoteControl_GetStateOfCharge(uint8_t *p_SOC) +{ + if (p_SOC == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Calculate SOC from battery voltage */ + *p_SOC = 75; /* Placeholder */ + + return ESP_OK; +} + +esp_err_t RemoteControl_GetOV5640Image(uint8_t **pp_Buffer, size_t *p_Size, Remote_Image_Format_t Format) +{ + if ((pp_Buffer == NULL) || (p_Size == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get image from OV5640 camera */ + ESP_LOGW(TAG, "OV5640 image capture not implemented"); + + return ESP_ERR_NOT_FOUND; +} + +esp_err_t RemoteControl_GetLeptonImage(uint8_t **pp_Buffer, size_t *p_Size, Remote_Image_Format_t Format) +{ + if ((pp_Buffer == NULL) || (p_Size == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get image from Lepton camera via LeptonTask */ + ESP_LOGW(TAG, "Lepton image capture not implemented"); + + return ESP_ERR_NOT_FOUND; +} + +esp_err_t RemoteControl_GetLeptonEmissivity(uint8_t *p_Emissivity) +{ + esp_err_t Error; + App_Settings_Lepton_t Lepton; + + if (p_Emissivity == NULL) { + return ESP_ERR_INVALID_ARG; + } + + Error = SettingsManager_GetLepton(&Lepton); + if(Error != ESP_OK) { + return Error; + } + + *p_Emissivity = Lepton.CurrentEmissivity; + + return ESP_OK; +} + +esp_err_t RemoteControl_SetLeptonEmissivity(uint8_t Emissivity) +{ + esp_err_t Error; + App_Settings_Lepton_t Lepton; + SettingsManager_Setting_t Changed; + + if (Emissivity > 100) { + return ESP_ERR_INVALID_ARG; + } + + Error = SettingsManager_GetLepton(&Lepton); + if(Error != ESP_OK) { + return Error; + } + + Lepton.CurrentEmissivity = Emissivity; + Changed.ID = SETTINGS_ID_LEPTON_EMISSIVITY; + Changed.Value = Emissivity; + + ESP_LOGD(TAG, "Set Lepton emissivity to: %u%%", Emissivity); + + return SettingsManager_UpdateLepton(&Lepton, &Changed); +} + +esp_err_t RemoteControl_GetLeptonSceneStats(cJSON *p_JSON) +{ + if (p_JSON == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get scene statistics from Lepton camera */ + cJSON_AddNumberToObject(p_JSON, "min_temp", 15.5); + cJSON_AddNumberToObject(p_JSON, "max_temp", 35.2); + cJSON_AddNumberToObject(p_JSON, "avg_temp", 22.8); + + return ESP_OK; +} + +esp_err_t RemoteControl_GetLeptonROI(cJSON *p_JSON) +{ + if (p_JSON == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get ROI from Lepton camera */ + cJSON_AddNumberToObject(p_JSON, "x", 40); + cJSON_AddNumberToObject(p_JSON, "y", 30); + cJSON_AddNumberToObject(p_JSON, "width", 80); + cJSON_AddNumberToObject(p_JSON, "height", 60); + + return ESP_OK; +} + +esp_err_t RemoteControl_SetLeptonROI(const cJSON *p_JSON) +{ + if (p_JSON == NULL) { + return ESP_ERR_INVALID_ARG; + } + + cJSON *x = cJSON_GetObjectItem(p_JSON, "x"); + cJSON *y = cJSON_GetObjectItem(p_JSON, "y"); + cJSON *width = cJSON_GetObjectItem(p_JSON, "width"); + cJSON *height = cJSON_GetObjectItem(p_JSON, "height"); + + if ((cJSON_IsNumber(x) == false) || (cJSON_IsNumber(y) == false) || + (cJSON_IsNumber(width) == false) || (cJSON_IsNumber(height) == false)) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Set ROI in Lepton camera */ + ESP_LOGI(TAG, "Set Lepton ROI: x=%d, y=%d, w=%d, h=%d", + x->valueint, y->valueint, width->valueint, height->valueint); + + return ESP_OK; +} + +esp_err_t RemoteControl_UpdateSpotmeter(float Min, float Max, float Mean) +{ + /* Initialize mutex on first call */ + if (_RemoteControl_State.Mutex == NULL) { + _RemoteControl_State.Mutex = xSemaphoreCreateMutex(); + if (_RemoteControl_State.Mutex == NULL) { + ESP_LOGE(TAG, "Failed to create mutex for spotmeter data"); + return ESP_ERR_NO_MEM; + } + } + + /* Thread-safe update of spotmeter data */ + if (xSemaphoreTake(_RemoteControl_State.Mutex, 100 / portTICK_PERIOD_MS) == pdTRUE) { + _RemoteControl_State.Spotmeter.Min = Min; + _RemoteControl_State.Spotmeter.Max = Max; + _RemoteControl_State.Spotmeter.Mean = Mean; + _RemoteControl_State.isValid = true; + xSemaphoreGive(_RemoteControl_State.Mutex); + + ESP_LOGD(TAG, "Spotmeter data updated: Min=%.2f°C, Max=%.2f°C, Avg=%.2f°C", + _RemoteControl_State.Spotmeter.Min, _RemoteControl_State.Spotmeter.Max, _RemoteControl_State.Spotmeter.Mean); + + return ESP_OK; + } else { + ESP_LOGE(TAG, "Failed to acquire mutex for spotmeter update!"); + + return ESP_ERR_TIMEOUT; + } +} + +esp_err_t RemoteControl_GetLeptonSpotmeter(cJSON *p_JSON) +{ + if (p_JSON == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* Check if data is available */ + if (_RemoteControl_State.isValid == false) { + ESP_LOGW(TAG, "No spotmeter data available yet"); + return ESP_ERR_NOT_FOUND; + } + + /* Thread-safe read of spotmeter data */ + if (xSemaphoreTake(_RemoteControl_State.Mutex, pdMS_TO_TICKS(100)) == pdTRUE) { + cJSON_AddNumberToObject(p_JSON, "min", _RemoteControl_State.Spotmeter.Min); + cJSON_AddNumberToObject(p_JSON, "max", _RemoteControl_State.Spotmeter.Max); + cJSON_AddNumberToObject(p_JSON, "average", _RemoteControl_State.Spotmeter.Average); + cJSON_AddNumberToObject(p_JSON, "mean", _RemoteControl_State.Spotmeter.Mean); + xSemaphoreGive(_RemoteControl_State.Mutex); + + return ESP_OK; + } else { + ESP_LOGE(TAG, "Failed to acquire mutex for spotmeter read"); + return ESP_ERR_TIMEOUT; + } +} + +esp_err_t RemoteControl_GetFlashPower(uint8_t *p_Power) +{ + if (p_Power == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get flash power from settings or hardware */ + *p_Power = 50; /* Placeholder */ + + return ESP_OK; +} + +esp_err_t RemoteControl_SetFlashPower(uint8_t Power) +{ + if (Power > 100) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Set flash power */ + ESP_LOGI(TAG, "Set flash power to: %u%%", Power); + + return ESP_OK; +} + +esp_err_t RemoteControl_GetFlashState(bool *p_Enabled) +{ + if (p_Enabled == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get flash state */ + *p_Enabled = false; /* Placeholder */ + + return ESP_OK; +} + +esp_err_t RemoteControl_SetFlashState(bool Enabled) +{ + /* TODO: Set flash state */ + ESP_LOGI(TAG, "Set flash state: %s", Enabled ? "ON" : "OFF"); + + return ESP_OK; +} + +esp_err_t RemoteControl_GetImageFormat(Remote_Image_Format_t *p_Format) +{ + App_Settings_System_t System; + esp_err_t Error; + + if (p_Format == NULL) { + return ESP_ERR_INVALID_ARG; + } + + Error = SettingsManager_GetSystem(&System); + if (Error != ESP_OK) { + return Error; + } + + /* Convert from Settings format to Remote format (enum values match) */ + *p_Format = static_cast(System.ImageFormat); + + return ESP_OK; +} + +esp_err_t RemoteControl_SetImageFormat(Remote_Image_Format_t Format) +{ + esp_err_t Error; + App_Settings_System_t System; + SettingsManager_Setting_t Changed; + + if ((Format != REMOTE_IMAGE_FORMAT_PNG) && + (Format != REMOTE_IMAGE_FORMAT_RAW) && + (Format != REMOTE_IMAGE_FORMAT_JPEG)) { + return ESP_ERR_INVALID_ARG; + } + + Error = SettingsManager_GetSystem(&System); + if (Error != ESP_OK) { + return Error; + } + + Changed.ID = SETTINGS_ID_IMAGE_FORMAT; + Changed.Value = Format; + System.ImageFormat = static_cast(Format); + + ESP_LOGI(TAG, "Set image format to: %d", System.ImageFormat); + + return SettingsManager_UpdateSystem(&System, &Changed); +} + +esp_err_t RemoteControl_SetStatusLED(Remote_LED_Color_t Color, uint8_t Brightness) +{ + if ((Color != REMOTE_LED_RED) && + (Color != REMOTE_LED_GREEN) && + (Color != REMOTE_LED_BLUE)) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Set LED via PCA9633 driver */ + const char *color_str = (Color == REMOTE_LED_RED) ? "RED" : + (Color == REMOTE_LED_GREEN) ? "GREEN" : "BLUE"; + + ESP_LOGI(TAG, "Set status LED: %s at brightness %u", color_str, Brightness); + + return ESP_OK; +} + +esp_err_t RemoteControl_GetSDCardState(bool *p_Available) +{ + if (p_Available == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Check SD card state via MemoryManager */ + *p_Available = false; /* Placeholder */ + + return ESP_OK; +} + +esp_err_t RemoteControl_FormatMemory(void) +{ + /* TODO: Format active memory via MemoryManager */ + ESP_LOGW(TAG, "Memory format not implemented"); + + return ESP_FAIL; +} + +esp_err_t RemoteControl_DisplayMessageBox(const char *p_Message) +{ + if (p_Message == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Display message box via GUITask */ + ESP_LOGI(TAG, "Display message: %s", p_Message); + + return ESP_OK; +} + +esp_err_t RemoteControl_GetLockState(bool *p_Locked) +{ + if (p_Locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + + /* TODO: Get lock state from settings or GUI */ + *p_Locked = false; /* Placeholder */ + + return ESP_OK; +} + +esp_err_t RemoteControl_SetLockState(bool Locked) +{ + /* TODO: Set lock state in settings or GUI */ + ESP_LOGI(TAG, "Set lock state: %s", Locked ? "LOCKED" : "UNLOCKED"); + + return ESP_OK; +} diff --git a/main/Application/Manager/Network/Server/RemoteControl/remoteControl.h b/main/Application/Manager/Network/Server/RemoteControl/remoteControl.h new file mode 100644 index 0000000..f1533d3 --- /dev/null +++ b/main/Application/Manager/Network/Server/RemoteControl/remoteControl.h @@ -0,0 +1,247 @@ +/* + * remoteControl.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Common remote control interface for VISA and HTTP/WebSocket servers. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef REMOTE_CONTROL_H_ +#define REMOTE_CONTROL_H_ + +#include +#include +#include +#include + +/** @brief LED color enumeration. + */ +typedef enum { + REMOTE_LED_RED = 0, /**< Red LED. */ + REMOTE_LED_GREEN = 1, /**< Green LED. */ + REMOTE_LED_BLUE = 2, /**< Blue LED. */ +} Remote_LED_Color_t; + +/** @brief Image format enumeration. + */ +typedef enum { + REMOTE_IMAGE_FORMAT_PNG = 0, /**< PNG format. */ + REMOTE_IMAGE_FORMAT_RAW = 1, /**< Raw format. */ + REMOTE_IMAGE_FORMAT_JPEG = 2, /**< JPEG format. */ +} Remote_Image_Format_t; + +/** @brief Get temperature from TMP117 sensor. + * @param p_Temperature Pointer to store temperature value in Celsius + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Temperature is NULL + * ESP_ERR_INVALID_STATE if sensor not initialized + */ +esp_err_t RemoteControl_GetTemperature(float *p_Temperature); + +/** @brief Get current system time. + * @param p_TimeStr Pointer to buffer for time string (ISO 8601 format) + * @param MaxLen Maximum length of buffer + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_TimeStr is NULL + * ESP_ERR_INVALID_STATE if time not synchronized + */ +esp_err_t RemoteControl_GetTime(char *p_TimeStr, size_t MaxLen); + +/** @brief Set current system time. + * @param p_TimeStr Time string in ISO 8601 format + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_TimeStr is NULL or invalid format + */ +esp_err_t RemoteControl_SetTime(const char *p_TimeStr); + +/** @brief Get battery voltage. + * @param p_Voltage Pointer to store voltage value in volts + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Voltage is NULL + * ESP_ERR_NOT_SUPPORTED if battery monitoring not available + */ +esp_err_t RemoteControl_GetBatteryVoltage(float *p_Voltage); + +/** @brief Get battery state of charge. + * @param p_SOC Pointer to store SOC value in percent (0-100) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_SOC is NULL + * ESP_ERR_NOT_SUPPORTED if battery monitoring not available + */ +esp_err_t RemoteControl_GetStateOfCharge(uint8_t *p_SOC); + +/** @brief Get OV5640 camera image. + * @param pp_Buffer Pointer to store image buffer pointer (caller must free) + * @param p_Size Pointer to store image size in bytes + * @param Format Desired image format + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_ERR_NO_MEM if allocation fails + * ESP_ERR_NOT_FOUND if camera not available + */ +esp_err_t RemoteControl_GetOV5640Image(uint8_t **pp_Buffer, size_t *p_Size, Remote_Image_Format_t Format); + +/** @brief Get Lepton thermal camera image. + * @param pp_Buffer Pointer to store image buffer pointer (caller must free) + * @param p_Size Pointer to store image size in bytes + * @param Format Desired image format + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if pointers are NULL + * ESP_ERR_NO_MEM if allocation fails + * ESP_ERR_NOT_FOUND if camera not available + */ +esp_err_t RemoteControl_GetLeptonImage(uint8_t **pp_Buffer, size_t *p_Size, Remote_Image_Format_t Format); + +/** @brief Get Lepton camera emissivity. + * @param p_Emissivity Pointer to store emissivity value (0-100) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Emissivity is NULL + */ +esp_err_t RemoteControl_GetLeptonEmissivity(uint8_t *p_Emissivity); + +/** @brief Set Lepton camera emissivity. + * @param Emissivity Emissivity value (0-100) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if value out of range + */ +esp_err_t RemoteControl_SetLeptonEmissivity(uint8_t Emissivity); + +/** @brief Get Lepton scene statistics. + * @param p_JSON Pointer to cJSON object to populate (must be created) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_JSON is NULL + * ESP_ERR_NOT_FOUND if no data available + */ +esp_err_t RemoteControl_GetLeptonSceneStats(cJSON *p_JSON); + +/** @brief Get Lepton ROI (Region of Interest). + * @param p_JSON Pointer to cJSON object to populate with ROI data + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_JSON is NULL + */ +esp_err_t RemoteControl_GetLeptonROI(cJSON *p_JSON); + +/** @brief Set Lepton ROI (Region of Interest). + * @param p_JSON Pointer to cJSON object containing ROI data + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_JSON is NULL or invalid + */ +esp_err_t RemoteControl_SetLeptonROI(const cJSON *p_JSON); + +/** @brief Get Lepton spotmeter data. + * @param p_JSON Pointer to cJSON object to populate + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_JSON is NULL + */ +esp_err_t RemoteControl_GetLeptonSpotmeter(cJSON *p_JSON); + +/** @brief Update Lepton spotmeter data in server cache. + * This function stores the latest spotmeter ROI results for use by + * VISA and WebSocket/HTTP interfaces. + * @note This function is thread-safe and can be called from any task. + * @param Min Minimum temperature in Celsius + * @param Max Maximum temperature in Celsius + * @param Mean Mean temperature in Celsius + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_ROIResult is NULL + */ +esp_err_t RemoteControl_UpdateSpotmeter(float Min, float Max, float Mean); + +/** @brief Get flash power level. + * @param p_Power Pointer to store power level (0-100) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Power is NULL + */ +esp_err_t RemoteControl_GetFlashPower(uint8_t *p_Power); + +/** @brief Set flash power level. + * @param Power Power level (0-100) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if value out of range + */ +esp_err_t RemoteControl_SetFlashPower(uint8_t Power); + +/** @brief Get flash state. + * @param p_Enabled Pointer to store flash state + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Enabled is NULL + */ +esp_err_t RemoteControl_GetFlashState(bool *p_Enabled); + +/** @brief Set flash state. + * @param Enabled Flash enabled state + * @return ESP_OK on success + */ +esp_err_t RemoteControl_SetFlashState(bool Enabled); + +/** @brief Get current image format. + * @param p_Format Pointer to store image format + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Format is NULL + */ +esp_err_t RemoteControl_GetImageFormat(Remote_Image_Format_t *p_Format); + +/** @brief Set image format. + * @param Format Image format + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if format invalid + */ +esp_err_t RemoteControl_SetImageFormat(Remote_Image_Format_t Format); + +/** @brief Set status LED color and brightness. + * @param Color LED color + * @param Brightness Brightness level (0-255) + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if color invalid + */ +esp_err_t RemoteControl_SetStatusLED(Remote_LED_Color_t Color, uint8_t Brightness); + +/** @brief Check if SD card is available. + * @param p_Available Pointer to store availability state + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Available is NULL + */ +esp_err_t RemoteControl_GetSDCardState(bool *p_Available); + +/** @brief Format active memory (internal flash or SD card). + * @return ESP_OK on success + * ESP_FAIL if format operation failed + */ +esp_err_t RemoteControl_FormatMemory(void); + +/** @brief Display message box on screen. + * @param p_Message Message text to display + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Message is NULL + */ +esp_err_t RemoteControl_DisplayMessageBox(const char *p_Message); + +/** @brief Get lock state of input buttons and joystick. + * @param p_Locked Pointer to store lock state + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG if p_Locked is NULL + */ +esp_err_t RemoteControl_GetLockState(bool *p_Locked); + +/** @brief Set lock state of input buttons and joystick. + * @param Locked Lock state + * @return ESP_OK on success + */ +esp_err_t RemoteControl_SetLockState(bool Locked); + +#endif /* REMOTE_CONTROL_H_ */ diff --git a/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp b/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp index 3adf8ba..97730cc 100644 --- a/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp +++ b/main/Application/Manager/Network/Server/VISA/Private/visaCommands.cpp @@ -31,6 +31,7 @@ #include #include "visaCommands.h" +#include "visaRemoteCommands.h" #include "sdkconfig.h" @@ -453,13 +454,35 @@ int VISACommands_Execute(const char *Command, char *Response, size_t MaxLen) if (is_query) { return VISA_CMD_SYST_VERS(Response, MaxLen); } + } else if ((token_count >= 2) && (strcasecmp(tokens[1], "TIME") == 0)) { + if (is_query) { + return VISA_Cmd_GetTime(Response, MaxLen); + } else { + return VISA_Cmd_SetTime(tokens, token_count, Response, MaxLen); + } + } else if ((token_count >= 2) && (strcasecmp(tokens[1], "LOCK") == 0)) { + if (is_query) { + return VISA_Cmd_GetLockState(Response, MaxLen); + } else { + return VISA_Cmd_SetLockState(tokens, token_count, Response, MaxLen); + } } } /* Device-Specific Commands - SENSe */ else if ((strcasecmp(tokens[0], "SENS") == 0) || (strcasecmp(tokens[0], "SENSe") == 0)) { if ((token_count >= 2) && (strcasecmp(tokens[1], "TEMP") == 0 || strcasecmp(tokens[1], "TEMPerature") == 0)) { if (is_query) { - return VISA_CMD_SENS_TEMP(Response, MaxLen); + return VISA_Cmd_GetTemperature(Response, MaxLen); + } + } else if ((token_count >= 2) && (strcasecmp(tokens[1], "BATT") == 0 || strcasecmp(tokens[1], "BATTery") == 0)) { + if ((token_count >= 3) && (strcasecmp(tokens[2], "VOLT") == 0 || strcasecmp(tokens[2], "VOLTage") == 0)) { + if (is_query) { + return VISA_Cmd_GetBatteryVoltage(Response, MaxLen); + } + } else if ((token_count >= 3) && (strcasecmp(tokens[2], "SOC") == 0)) { + if (is_query) { + return VISA_Cmd_GetStateOfCharge(Response, MaxLen); + } } } else if ((token_count >= 2) && (strcasecmp(tokens[1], "IMG") == 0 || strcasecmp(tokens[1], "IMAGE") == 0)) { if ((token_count >= 3) && (strcasecmp(tokens[2], "CAPT") == 0 || strcasecmp(tokens[2], "CAPTure") == 0)) { @@ -469,9 +492,35 @@ int VISACommands_Execute(const char *Command, char *Response, size_t MaxLen) return VISA_CMD_SENS_IMG_DATA(Response, MaxLen); } } else if ((token_count >= 3) && (strcasecmp(tokens[2], "FORM") == 0 || strcasecmp(tokens[2], "FORMat") == 0)) { - return VISA_CMD_SENS_IMG_FORM(tokens, token_count, Response, MaxLen); + if (is_query) { + return VISA_Cmd_GetImageFormat(Response, MaxLen); + } else { + return VISA_Cmd_SetImageFormat(tokens, token_count, Response, MaxLen); + } } else if ((token_count >= 3) && (strcasecmp(tokens[2], "PAL") == 0 || strcasecmp(tokens[2], "PALette") == 0)) { return VISA_CMD_SENS_IMG_PAL(tokens, token_count, Response, MaxLen); + } else if ((token_count >= 3) && (strcasecmp(tokens[2], "LEP") == 0 || strcasecmp(tokens[2], "LEPton") == 0)) { + if ((token_count >= 4) && (strcasecmp(tokens[3], "EMIS") == 0 || strcasecmp(tokens[3], "EMISsivity") == 0)) { + if (is_query) { + return VISA_Cmd_GetLeptonEmissivity(Response, MaxLen); + } else { + return VISA_Cmd_SetLeptonEmissivity(tokens, token_count, Response, MaxLen); + } + } else if ((token_count >= 4) && (strcasecmp(tokens[3], "STAT") == 0 || strcasecmp(tokens[3], "STATistics") == 0)) { + if (is_query) { + return VISA_Cmd_GetLeptonStats(Response, MaxLen); + } + } else if ((token_count >= 4) && (strcasecmp(tokens[3], "ROI") == 0)) { + if (is_query) { + return VISA_Cmd_GetLeptonROI(Response, MaxLen); + } else { + return VISA_Cmd_SetLeptonROI(tokens, token_count, Response, MaxLen); + } + } else if ((token_count >= 4) && (strcasecmp(tokens[3], "SPOT") == 0 || strcasecmp(tokens[3], "SPOTmeter") == 0)) { + if (is_query) { + return VISA_Cmd_GetLeptonSpotmeter(Response, MaxLen); + } + } } } } @@ -479,10 +528,38 @@ int VISACommands_Execute(const char *Command, char *Response, size_t MaxLen) else if ((strcasecmp(tokens[0], "DISP") == 0) || (strcasecmp(tokens[0], "DISPlay") == 0)) { if ((token_count >= 2) && (strcasecmp(tokens[1], "LED") == 0)) { if ((token_count >= 3) && (strcasecmp(tokens[2], "STAT") == 0 || strcasecmp(tokens[2], "STATe") == 0)) { - return VISA_CMD_DISP_LED_STAT(tokens, token_count, Response, MaxLen); + return VISA_Cmd_SetStatusLED(tokens, token_count, Response, MaxLen); } else if ((token_count >= 3) && (strcasecmp(tokens[2], "BRIG") == 0 || strcasecmp(tokens[2], "BRIGhtness") == 0)) { return VISA_CMD_DISP_LED_BRIG(tokens, token_count, Response, MaxLen); } + } else if ((token_count >= 2) && (strcasecmp(tokens[1], "FLASH") == 0)) { + if ((token_count >= 3) && (strcasecmp(tokens[2], "POW") == 0 || strcasecmp(tokens[2], "POWer") == 0)) { + if (is_query) { + return VISA_Cmd_GetFlashPower(Response, MaxLen); + } else { + return VISA_Cmd_SetFlashPower(tokens, token_count, Response, MaxLen); + } + } else if ((token_count >= 3) && (strcasecmp(tokens[2], "STAT") == 0 || strcasecmp(tokens[2], "STATe") == 0)) { + if (is_query) { + return VISA_Cmd_GetFlashState(Response, MaxLen); + } else { + return VISA_Cmd_SetFlashState(tokens, token_count, Response, MaxLen); + } + } + } else if ((token_count >= 2) && (strcasecmp(tokens[1], "MBOX") == 0 || strcasecmp(tokens[1], "MessageBOX") == 0)) { + return VISA_Cmd_DisplayMessageBox(tokens, token_count, Response, MaxLen); + } + } + /* Device-Specific Commands - MEMory */ + else if ((strcasecmp(tokens[0], "MEM") == 0) || (strcasecmp(tokens[0], "MEMory") == 0)) { + if ((token_count >= 2) && (strcasecmp(tokens[1], "SD") == 0)) { + if ((token_count >= 3) && (strcasecmp(tokens[2], "STAT") == 0 || strcasecmp(tokens[2], "STATe") == 0)) { + if (is_query) { + return VISA_Cmd_GetSDCardState(Response, MaxLen); + } + } + } else if ((token_count >= 2) && (strcasecmp(tokens[1], "FORM") == 0 || strcasecmp(tokens[1], "FORMat") == 0)) { + return VISA_Cmd_FormatMemory(Response, MaxLen); } } diff --git a/main/Application/Manager/Network/Server/VISA/Private/visaRemoteCommands.cpp b/main/Application/Manager/Network/Server/VISA/Private/visaRemoteCommands.cpp new file mode 100644 index 0000000..e313643 --- /dev/null +++ b/main/Application/Manager/Network/Server/VISA/Private/visaRemoteCommands.cpp @@ -0,0 +1,495 @@ +/* + * visaRemoteCommands.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: VISA commands for remote control interface. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include +#include +#include + +#include "visaRemoteCommands.h" +#include "visaCommands.h" +#include "../../RemoteControl/remoteControl.h" + +static const char *TAG = "VISA-Remote"; + +int VISA_Cmd_GetTemperature(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + float Temperature; + + Error = RemoteControl_GetTemperature(&Temperature); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%.2f\n", Temperature); +} + +int VISA_Cmd_GetTime(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + char TimeStr[32]; + + Error = RemoteControl_GetTime(TimeStr, sizeof(TimeStr)); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return snprintf(p_Response, MaxLen, "%s\n", TimeStr); +} + +int VISA_Cmd_SetTime(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + + if (Count < 4) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + Error = RemoteControl_SetTime(pp_Tokens[3]); + if (Error != ESP_OK) { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + return 0; +} + +int VISA_Cmd_GetBatteryVoltage(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + float Voltage; + + Error = RemoteControl_GetBatteryVoltage(&Voltage); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%.3f\n", Voltage); +} + +int VISA_Cmd_GetStateOfCharge(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + uint8_t SOC; + + Error = RemoteControl_GetStateOfCharge(&SOC); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%u\n", SOC); +} + +int VISA_Cmd_GetLeptonEmissivity(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + uint8_t Emissivity; + + Error = RemoteControl_GetLeptonEmissivity(&Emissivity); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%u\n", Emissivity); +} + +int VISA_Cmd_SetLeptonEmissivity(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + int Emissivity; + + if (Count < 5) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + Emissivity = atoi(pp_Tokens[4]); + if ((Emissivity < 0) || (Emissivity > 100)) { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + Error = RemoteControl_SetLeptonEmissivity((uint8_t)Emissivity); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} + +int VISA_Cmd_GetLeptonStats(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + cJSON *JSON; + char *JSONStr; + int len; + + JSON = cJSON_CreateObject(); + if (JSON == NULL) { + return SCPI_ERROR_OUT_OF_MEMORY; + } + + Error = RemoteControl_GetLeptonSceneStats(JSON); + if (Error != ESP_OK) { + cJSON_Delete(JSON); + return SCPI_ERROR_HARDWARE_ERROR; + } + + JSONStr = cJSON_PrintUnformatted(JSON); + cJSON_Delete(JSON); + + if (JSONStr == NULL) { + return SCPI_ERROR_OUT_OF_MEMORY; + } + + len = snprintf(p_Response, MaxLen, "%s\n", JSONStr); + cJSON_free(JSONStr); + + return len; +} + +int VISA_Cmd_GetLeptonROI(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + cJSON *JSON; + char *JSONStr; + int len; + + JSON = cJSON_CreateObject(); + if (JSON == NULL) { + return SCPI_ERROR_OUT_OF_MEMORY; + } + + Error = RemoteControl_GetLeptonROI(JSON); + if (Error != ESP_OK) { + cJSON_Delete(JSON); + return SCPI_ERROR_HARDWARE_ERROR; + } + + JSONStr = cJSON_PrintUnformatted(JSON); + cJSON_Delete(JSON); + + if (JSONStr == NULL) { + return SCPI_ERROR_OUT_OF_MEMORY; + } + + len = snprintf(p_Response, MaxLen, "%s\n", JSONStr); + cJSON_free(JSONStr); + + return len; +} + +int VISA_Cmd_SetLeptonROI(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + cJSON *JSON; + + if (Count < 5) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + /* Expected format: SENS:IMG:LEP:ROI x,y,width,height */ + /* Parse as JSON: {"x":40,"y":30,"width":80,"height":60} */ + JSON = cJSON_Parse(pp_Tokens[4]); + if (JSON == NULL) { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + Error = RemoteControl_SetLeptonROI(JSON); + cJSON_Delete(JSON); + + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} + +int VISA_Cmd_GetLeptonSpotmeter(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + cJSON *JSON; + char *JSONStr; + int len; + + JSON = cJSON_CreateObject(); + if (JSON == NULL) { + return SCPI_ERROR_OUT_OF_MEMORY; + } + + Error = RemoteControl_GetLeptonSpotmeter(JSON); + if (Error != ESP_OK) { + cJSON_Delete(JSON); + return SCPI_ERROR_HARDWARE_ERROR; + } + + JSONStr = cJSON_PrintUnformatted(JSON); + cJSON_Delete(JSON); + + if (JSONStr == NULL) { + return SCPI_ERROR_OUT_OF_MEMORY; + } + + len = snprintf(p_Response, MaxLen, "%s\n", JSONStr); + cJSON_free(JSONStr); + + return len; +} + +int VISA_Cmd_GetFlashPower(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + uint8_t Power; + + Error = RemoteControl_GetFlashPower(&Power); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%u\n", Power); +} + +int VISA_Cmd_SetFlashPower(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + int Power; + + if (Count < 4) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + Power = atoi(pp_Tokens[3]); + if ((Power < 0) || (Power > 100)) { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + Error = RemoteControl_SetFlashPower((uint8_t)Power); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} + +int VISA_Cmd_GetFlashState(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + bool Enabled; + + Error = RemoteControl_GetFlashState(&Enabled); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%s\n", Enabled ? "ON" : "OFF"); +} + +int VISA_Cmd_SetFlashState(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + bool Enabled; + + if (Count < 4) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + if ((strcasecmp(pp_Tokens[3], "ON") == 0) || (strcasecmp(pp_Tokens[3], "1") == 0)) { + Enabled = true; + } else if ((strcasecmp(pp_Tokens[3], "OFF") == 0) || (strcasecmp(pp_Tokens[3], "0") == 0)) { + Enabled = false; + } else { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + Error = RemoteControl_SetFlashState(Enabled); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} + +int VISA_Cmd_GetImageFormat(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + Remote_Image_Format_t Format; + const char *FormatStr; + + Error = RemoteControl_GetImageFormat(&Format); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + switch (Format) { + case REMOTE_IMAGE_FORMAT_PNG: + FormatStr = "PNG"; + break; + case REMOTE_IMAGE_FORMAT_RAW: + FormatStr = "RAW"; + break; + case REMOTE_IMAGE_FORMAT_JPEG: + FormatStr = "JPEG"; + break; + default: + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%s\n", FormatStr); +} + +int VISA_Cmd_SetImageFormat(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + Remote_Image_Format_t Format; + + if (Count < 4) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + if (strcasecmp(pp_Tokens[3], "PNG") == 0) { + Format = REMOTE_IMAGE_FORMAT_PNG; + } else if (strcasecmp(pp_Tokens[3], "RAW") == 0) { + Format = REMOTE_IMAGE_FORMAT_RAW; + } else if (strcasecmp(pp_Tokens[3], "JPEG") == 0) { + Format = REMOTE_IMAGE_FORMAT_JPEG; + } else { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + Error = RemoteControl_SetImageFormat(Format); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} + +int VISA_Cmd_SetStatusLED(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + Remote_LED_Color_t Color; + int Brightness; + + if (Count < 5) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + if (strcasecmp(pp_Tokens[3], "RED") == 0) { + Color = REMOTE_LED_RED; + } else if (strcasecmp(pp_Tokens[3], "GREEN") == 0) { + Color = REMOTE_LED_GREEN; + } else if (strcasecmp(pp_Tokens[3], "BLUE") == 0) { + Color = REMOTE_LED_BLUE; + } else { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + Brightness = atoi(pp_Tokens[4]); + if ((Brightness < 0) || (Brightness > 255)) { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + Error = RemoteControl_SetStatusLED(Color, (uint8_t)Brightness); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} + +int VISA_Cmd_GetSDCardState(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + bool Available; + + Error = RemoteControl_GetSDCardState(&Available); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%s\n", Available ? "AVAILABLE" : "NOT_AVAILABLE"); +} + +int VISA_Cmd_FormatMemory(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + + Error = RemoteControl_FormatMemory(); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} + +int VISA_Cmd_DisplayMessageBox(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + + if (Count < 4) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + Error = RemoteControl_DisplayMessageBox(pp_Tokens[3]); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} + +int VISA_Cmd_GetLockState(char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + bool Locked; + + Error = RemoteControl_GetLockState(&Locked); + if (Error != ESP_OK) { + return SCPI_ERROR_HARDWARE_ERROR; + } + + return snprintf(p_Response, MaxLen, "%s\n", Locked ? "LOCKED" : "UNLOCKED"); +} + +int VISA_Cmd_SetLockState(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen) +{ + esp_err_t Error; + bool Locked; + + if (Count < 3) { + return SCPI_ERROR_MISSING_PARAMETER; + } + + if ((strcasecmp(pp_Tokens[2], "LOCKED") == 0) || (strcasecmp(pp_Tokens[2], "1") == 0)) { + Locked = true; + } else if ((strcasecmp(pp_Tokens[2], "UNLOCKED") == 0) || (strcasecmp(pp_Tokens[2], "0") == 0)) { + Locked = false; + } else { + return SCPI_ERROR_DATA_OUT_OF_RANGE; + } + + Error = RemoteControl_SetLockState(Locked); + if (Error != ESP_OK) { + return SCPI_ERROR_EXECUTION_ERROR; + } + + return 0; +} diff --git a/main/Application/Manager/Network/Server/VISA/Private/visaRemoteCommands.h b/main/Application/Manager/Network/Server/VISA/Private/visaRemoteCommands.h new file mode 100644 index 0000000..f954b33 --- /dev/null +++ b/main/Application/Manager/Network/Server/VISA/Private/visaRemoteCommands.h @@ -0,0 +1,208 @@ +/* + * visaRemoteCommands.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: VISA commands for remote control interface. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef VISA_REMOTE_COMMANDS_H_ +#define VISA_REMOTE_COMMANDS_H_ + +#include + +/** @brief Handle SENS:TEMP? - Get temperature sensor value. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetTemperature(char *p_Response, size_t MaxLen); + +/** @brief Handle SYST:TIME? - Get system time. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetTime(char *p_Response, size_t MaxLen); + +/** @brief Handle SYST:TIME - Set system time. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_SetTime(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:BATT:VOLT? - Get battery voltage. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetBatteryVoltage(char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:BATT:SOC? - Get state of charge. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetStateOfCharge(char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:IMG:LEP:EMIS? - Get Lepton emissivity. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetLeptonEmissivity(char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:IMG:LEP:EMIS - Set Lepton emissivity. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_SetLeptonEmissivity(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:IMG:LEP:STAT? - Get Lepton scene statistics. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetLeptonStats(char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:IMG:LEP:ROI? - Get Lepton ROI. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetLeptonROI(char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:IMG:LEP:ROI - Set Lepton ROI. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_SetLeptonROI(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:IMG:LEP:SPOT? - Get Lepton spotmeter. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetLeptonSpotmeter(char *p_Response, size_t MaxLen); + +/** @brief Handle DISP:FLASH:POW? - Get flash power. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetFlashPower(char *p_Response, size_t MaxLen); + +/** @brief Handle DISP:FLASH:POW - Set flash power. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_SetFlashPower(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +/** @brief Handle DISP:FLASH:STAT? - Get flash state. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetFlashState(char *p_Response, size_t MaxLen); + +/** @brief Handle DISP:FLASH:STAT - Set flash state. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_SetFlashState(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:IMG:FORM? - Get image format. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetImageFormat(char *p_Response, size_t MaxLen); + +/** @brief Handle SENS:IMG:FORM - Set image format. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_SetImageFormat(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +/** @brief Handle DISP:LED:STAT - Set status LED. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_SetStatusLED(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +/** @brief Handle MEM:SD:STAT? - Get SD card state. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetSDCardState(char *p_Response, size_t MaxLen); + +/** @brief Handle MEM:FORM - Format memory. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_FormatMemory(char *p_Response, size_t MaxLen); + +/** @brief Handle DISP:MBOX - Display message box. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_DisplayMessageBox(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +/** @brief Handle SYST:LOCK? - Get lock state. + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_GetLockState(char *p_Response, size_t MaxLen); + +/** @brief Handle SYST:LOCK - Set lock state. + * @param pp_Tokens Command tokens + * @param Count Token count + * @param p_Response Response buffer + * @param MaxLen Maximum response length + * @return Response length or negative error code + */ +int VISA_Cmd_SetLockState(char **pp_Tokens, int Count, char *p_Response, size_t MaxLen); + +#endif /* VISA_REMOTE_COMMANDS_H_ */ diff --git a/main/Application/Manager/Network/Server/WebSocket/Private/websocketRemoteHandlers.cpp b/main/Application/Manager/Network/Server/WebSocket/Private/websocketRemoteHandlers.cpp new file mode 100644 index 0000000..c792eb7 --- /dev/null +++ b/main/Application/Manager/Network/Server/WebSocket/Private/websocketRemoteHandlers.cpp @@ -0,0 +1,512 @@ +/* + * websocketRemoteHandlers.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: WebSocket handlers for remote control interface. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include + +#include + +#include "Settings/settingsManager.h" +#include "websocketRemoteHandlers.h" +#include "../../RemoteControl/remoteControl.h" + +static const char *TAG = "WebSocket-Remote"; + +static void WebSocket_SendResponse(int FD, const char *p_Cmd, const char *p_Status, cJSON *p_Data, const char *p_Error) +{ + cJSON *Response; + + Response = cJSON_CreateObject(); + cJSON_AddStringToObject(Response, "status", p_Status); + + if (p_Data != NULL) { + cJSON_AddItemReferenceToObject(Response, "data", p_Data); + } else if (p_Error != NULL) { + cJSON_AddStringToObject(Response, "error", p_Error); + } + + WebSocket_SendJSON(FD, p_Cmd, Response); + cJSON_Delete(Response); +} + +void WebSocket_Handle_GetTemperature(int FD, cJSON *p_Data) +{ + esp_err_t Error; + float Temperature; + cJSON *Data; + + Error = RemoteControl_GetTemperature(&Temperature); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "temperature", "error", NULL, "Failed to get temperature"); + + return; + } + + Data = cJSON_CreateObject(); + cJSON_AddNumberToObject(Data, "temperature", Temperature); + + WebSocket_SendResponse(FD, "temperature", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_GetTime(int FD, cJSON *p_Data) +{ + esp_err_t Error; + char TimeStr[32]; + cJSON *Data; + + Error = RemoteControl_GetTime(TimeStr, sizeof(TimeStr)); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "time", "error", NULL, "Failed to get time"); + + return; + } + + Data = cJSON_CreateObject(); + cJSON_AddStringToObject(Data, "time", TimeStr); + + WebSocket_SendResponse(FD, "time", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_SetTime(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *TimeField; + + TimeField = cJSON_GetObjectItem(p_Data, "time"); + if (cJSON_IsString(TimeField) == false) { + WebSocket_SendResponse(FD, "set_time", "error", NULL, "Missing or invalid 'time' field"); + + return; + } + + Error = RemoteControl_SetTime(TimeField->valuestring); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "set_time", "error", NULL, "Invalid time format"); + + return; + } + + WebSocket_SendResponse(FD, "set_time", "ok", NULL, NULL); +} + +void WebSocket_Handle_GetBattery(int FD, cJSON *p_Data) +{ + esp_err_t Error; + float Voltage; + uint8_t SOC; + cJSON *Data; + + Error = RemoteControl_GetBatteryVoltage(&Voltage); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "battery", "error", NULL, "Failed to get battery voltage"); + + return; + } + + Error = RemoteControl_GetStateOfCharge(&SOC); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "battery", "error", NULL, "Failed to get SOC"); + + return; + } + + Data = cJSON_CreateObject(); + cJSON_AddNumberToObject(Data, "voltage", Voltage); + cJSON_AddNumberToObject(Data, "soc", SOC); + + WebSocket_SendResponse(FD, "battery", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_GetLeptonEmissivity(int FD, cJSON *p_Data) +{ + esp_err_t Error; + uint8_t Emissivity; + cJSON *Data; + + Error = RemoteControl_GetLeptonEmissivity(&Emissivity); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "lepton_emissivity", "error", NULL, "Failed to get emissivity"); + + return; + } + + Data = cJSON_CreateObject(); + cJSON_AddNumberToObject(Data, "emissivity", Emissivity); + + WebSocket_SendResponse(FD, "lepton_emissivity", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_SetLeptonEmissivity(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *EmisField; + + EmisField = cJSON_GetObjectItem(p_Data, "emissivity"); + if (cJSON_IsNumber(EmisField) == false) { + WebSocket_SendResponse(FD, "set_lepton_emissivity", "error", NULL, "Missing or invalid 'emissivity' field"); + + return; + } + + Error = RemoteControl_SetLeptonEmissivity((uint8_t)EmisField->valueint); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "set_lepton_emissivity", "error", NULL, "Invalid emissivity value"); + + return; + } + + WebSocket_SendResponse(FD, "set_lepton_emissivity", "ok", NULL, NULL); +} + +void WebSocket_Handle_GetLeptonStats(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *Data; + + Data = cJSON_CreateObject(); + Error = RemoteControl_GetLeptonSceneStats(Data); + if (Error != ESP_OK) { + cJSON_Delete(Data); + WebSocket_SendResponse(FD, "lepton_stats", "error", NULL, "Failed to get scene stats"); + + return; + } + + WebSocket_SendResponse(FD, "lepton_stats", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_GetLeptonROI(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *Data; + + Data = cJSON_CreateObject(); + Error = RemoteControl_GetLeptonROI(Data); + if (Error != ESP_OK) { + cJSON_Delete(Data); + WebSocket_SendResponse(FD, "lepton_roi", "error", NULL, "Failed to get ROI"); + return; + } + + WebSocket_SendResponse(FD, "lepton_roi", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_SetLeptonROI(int FD, cJSON *p_Data) +{ + esp_err_t Error; + + Error = RemoteControl_SetLeptonROI(p_Data); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "set_lepton_roi", "error", NULL, "Invalid ROI data"); + + return; + } + + WebSocket_SendResponse(FD, "set_lepton_roi", "ok", NULL, NULL); +} + +void WebSocket_Handle_GetLeptonSpotmeter(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *Data; + + Data = cJSON_CreateObject(); + Error = RemoteControl_GetLeptonSpotmeter(Data); + if (Error != ESP_OK) { + cJSON_Delete(Data); + WebSocket_SendResponse(FD, "lepton_spotmeter", "error", NULL, "Failed to get spotmeter"); + + return; + } + + WebSocket_SendResponse(FD, "lepton_spotmeter", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_GetFlash(int FD, cJSON *p_Data) +{ + esp_err_t Error; + bool Enabled; + uint8_t Power; + cJSON *Data; + + Error = RemoteControl_GetFlashState(&Enabled); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "flash", "error", NULL, "Failed to get flash state"); + + return; + } + + Error = RemoteControl_GetFlashPower(&Power); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "flash", "error", NULL, "Failed to get flash power"); + + return; + } + + Data = cJSON_CreateObject(); + cJSON_AddBoolToObject(Data, "enabled", Enabled); + cJSON_AddNumberToObject(Data, "power", Power); + + WebSocket_SendResponse(FD, "flash", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_SetFlash(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *EnabledField; + cJSON *PowerField; + + EnabledField = cJSON_GetObjectItem(p_Data, "enabled"); + if (cJSON_IsBool(EnabledField)) { + Error = RemoteControl_SetFlashState(cJSON_IsTrue(EnabledField)); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "set_flash", "error", NULL, "Failed to set flash state"); + + return; + } + } + + PowerField = cJSON_GetObjectItem(p_Data, "power"); + if (cJSON_IsNumber(PowerField)) { + Error = RemoteControl_SetFlashPower((uint8_t)PowerField->valueint); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "set_flash", "error", NULL, "Invalid flash power value"); + + return; + } + } + + WebSocket_SendResponse(FD, "set_flash", "ok", NULL, NULL); +} + +void WebSocket_Handle_GetImageFormat(int FD, cJSON *p_Data) +{ + esp_err_t Error; + Remote_Image_Format_t Format; + const char *FormatStr; + cJSON *Data; + + Error = RemoteControl_GetImageFormat(&Format); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "image_format", "error", NULL, "Failed to get image format"); + + return; + } + + switch (Format) { + case REMOTE_IMAGE_FORMAT_PNG: + FormatStr = "PNG"; + break; + case REMOTE_IMAGE_FORMAT_RAW: + FormatStr = "RAW"; + break; + case REMOTE_IMAGE_FORMAT_JPEG: + FormatStr = "JPEG"; + break; + default: + WebSocket_SendResponse(FD, "image_format", "error", NULL, "Unknown format"); + return; + } + + Data = cJSON_CreateObject(); + cJSON_AddStringToObject(Data, "format", FormatStr); + + WebSocket_SendResponse(FD, "image_format", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_SetImageFormat(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *FormatField; + Remote_Image_Format_t Format; + + FormatField = cJSON_GetObjectItem(p_Data, "format"); + if (cJSON_IsString(FormatField) == false) { + WebSocket_SendResponse(FD, "set_image_format", "error", NULL, "Missing or invalid 'format' field"); + return; + } + + if (strcasecmp(FormatField->valuestring, "PNG") == 0) { + Format = REMOTE_IMAGE_FORMAT_PNG; + } else if (strcasecmp(FormatField->valuestring, "RAW") == 0) { + Format = REMOTE_IMAGE_FORMAT_RAW; + } else if (strcasecmp(FormatField->valuestring, "JPEG") == 0) { + Format = REMOTE_IMAGE_FORMAT_JPEG; + } else { + WebSocket_SendResponse(FD, "set_image_format", "error", NULL, "Invalid format"); + return; + } + + Error = RemoteControl_SetImageFormat(Format); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "set_image_format", "error", NULL, "Failed to set image format"); + return; + } + + WebSocket_SendResponse(FD, "set_image_format", "ok", NULL, NULL); +} + +void WebSocket_Handle_SetStatusLED(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *ColorField; + cJSON *BrightnessField; + Remote_LED_Color_t Color; + uint8_t Brightness; + + ColorField = cJSON_GetObjectItem(p_Data, "color"); + BrightnessField = cJSON_GetObjectItem(p_Data, "brightness"); + + if ((cJSON_IsString(ColorField) == false) || (cJSON_IsNumber(BrightnessField) == false)) { + WebSocket_SendResponse(FD, "set_status_led", "error", NULL, "Missing or invalid fields"); + + return; + } + + if (strcasecmp(ColorField->valuestring, "RED") == 0) { + Color = REMOTE_LED_RED; + } else if (strcasecmp(ColorField->valuestring, "GREEN") == 0) { + Color = REMOTE_LED_GREEN; + } else if (strcasecmp(ColorField->valuestring, "BLUE") == 0) { + Color = REMOTE_LED_BLUE; + } else { + WebSocket_SendResponse(FD, "set_status_led", "error", NULL, "Invalid color"); + return; + } + + Brightness = (uint8_t)BrightnessField->valueint; + + Error = RemoteControl_SetStatusLED(Color, Brightness); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "set_status_led", "error", NULL, "Failed to set LED"); + return; + } + + WebSocket_SendResponse(FD, "set_status_led", "ok", NULL, NULL); +} + +void WebSocket_Handle_GetSDState(int FD, cJSON *p_Data) +{ + esp_err_t Error; + bool Available; + cJSON *Data; + + Error = RemoteControl_GetSDCardState(&Available); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "sd_state", "error", NULL, "Failed to get SD state"); + + return; + } + + Data = cJSON_CreateObject(); + cJSON_AddBoolToObject(Data, "available", Available); + + WebSocket_SendResponse(FD, "sd_state", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_FormatMemory(int FD, cJSON *p_Data) +{ + esp_err_t Error; + + Error = RemoteControl_FormatMemory(); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "format_memory", "error", NULL, "Format operation failed"); + + return; + } + + WebSocket_SendResponse(FD, "format_memory", "ok", NULL, NULL); +} + +void WebSocket_Handle_DisplayMessage(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *MessageField; + + MessageField = cJSON_GetObjectItem(p_Data, "message"); + if (cJSON_IsString(MessageField) == false) { + WebSocket_SendResponse(FD, "display_message", "error", NULL, "Missing or invalid 'message' field"); + + return; + } + + Error = RemoteControl_DisplayMessageBox(MessageField->valuestring); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "display_message", "error", NULL, "Failed to display message"); + + return; + } + + WebSocket_SendResponse(FD, "display_message", "ok", NULL, NULL); +} + +void WebSocket_Handle_GetLock(int FD, cJSON *p_Data) +{ + esp_err_t Error; + bool Locked; + cJSON *Data; + + Error = RemoteControl_GetLockState(&Locked); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "lock", "error", NULL, "Failed to get lock state"); + + return; + } + + Data = cJSON_CreateObject(); + cJSON_AddBoolToObject(Data, "locked", Locked); + + WebSocket_SendResponse(FD, "lock", "ok", Data, NULL); + cJSON_Delete(Data); +} + +void WebSocket_Handle_SetLock(int FD, cJSON *p_Data) +{ + esp_err_t Error; + cJSON *LockedField; + + LockedField = cJSON_GetObjectItem(p_Data, "locked"); + if (cJSON_IsBool(LockedField) == false) { + WebSocket_SendResponse(FD, "set_lock", "error", NULL, "Missing or invalid 'locked' field"); + + return; + } + + Error = RemoteControl_SetLockState(cJSON_IsTrue(LockedField)); + if (Error != ESP_OK) { + WebSocket_SendResponse(FD, "set_lock", "error", NULL, "Failed to set lock state"); + + return; + } + + WebSocket_SendResponse(FD, "set_lock", "ok", NULL, NULL); +} diff --git a/main/Application/Manager/Network/Server/WebSocket/Private/websocketRemoteHandlers.h b/main/Application/Manager/Network/Server/WebSocket/Private/websocketRemoteHandlers.h new file mode 100644 index 0000000..7e42678 --- /dev/null +++ b/main/Application/Manager/Network/Server/WebSocket/Private/websocketRemoteHandlers.h @@ -0,0 +1,163 @@ +/* + * websocketRemoteHandlers.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: WebSocket handlers for remote control interface. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef WEBSOCKET_REMOTE_HANDLERS_H_ +#define WEBSOCKET_REMOTE_HANDLERS_H_ + +#include + +#include + +#include + +/** @brief Send JSON message to WebSocket client. + * @param FD File descriptor of client socket + * @param p_Cmd Command string + * @param p_Data Optional JSON data object (can be NULL) + * @return ESP_OK on success + * ESP_ERR_NO_MEM if JSON creation failed + * ESP_ERR_INVALID_STATE if send failed + */ +esp_err_t WebSocket_SendJSON(int FD, const char *p_Cmd, cJSON *p_Data); + +/** @brief Handle "get_temperature" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetTemperature(int FD, cJSON *p_Data); + +/** @brief Handle "get_time" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetTime(int FD, cJSON *p_Data); + +/** @brief Handle "set_time" command. + * @param FD Client file descriptor + * @param p_Data Command data (must contain "time" field) + */ +void WebSocket_Handle_SetTime(int FD, cJSON *p_Data); + +/** @brief Handle "get_battery" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetBattery(int FD, cJSON *p_Data); + +/** @brief Handle "get_lepton_emissivity" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetLeptonEmissivity(int FD, cJSON *p_Data); + +/** @brief Handle "set_lepton_emissivity" command. + * @param FD Client file descriptor + * @param p_Data Command data (must contain "emissivity" field) + */ +void WebSocket_Handle_SetLeptonEmissivity(int FD, cJSON *p_Data); + +/** @brief Handle "get_lepton_stats" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetLeptonStats(int FD, cJSON *p_Data); + +/** @brief Handle "get_lepton_roi" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetLeptonROI(int FD, cJSON *p_Data); + +/** @brief Handle "set_lepton_roi" command. + * @param FD Client file descriptor + * @param p_Data Command data (must contain ROI fields) + */ +void WebSocket_Handle_SetLeptonROI(int FD, cJSON *p_Data); + +/** @brief Handle "get_lepton_spotmeter" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetLeptonSpotmeter(int FD, cJSON *p_Data); + +/** @brief Handle "get_flash" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetFlash(int FD, cJSON *p_Data); + +/** @brief Handle "set_flash" command. + * @param FD Client file descriptor + * @param p_Data Command data (must contain "enabled" and/or "power" fields) + */ +void WebSocket_Handle_SetFlash(int FD, cJSON *p_Data); + +/** @brief Handle "get_image_format" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetImageFormat(int FD, cJSON *p_Data); + +/** @brief Handle "set_image_format" command. + * @param FD Client file descriptor + * @param p_Data Command data (must contain "format" field) + */ +void WebSocket_Handle_SetImageFormat(int FD, cJSON *p_Data); + +/** @brief Handle "set_status_led" command. + * @param FD Client file descriptor + * @param p_Data Command data (must contain "color" and "brightness" fields) + */ +void WebSocket_Handle_SetStatusLED(int FD, cJSON *p_Data); + +/** @brief Handle "get_sd_state" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetSDState(int FD, cJSON *p_Data); + +/** @brief Handle "format_memory" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_FormatMemory(int FD, cJSON *p_Data); + +/** @brief Handle "display_message" command. + * @param FD Client file descriptor + * @param p_Data Command data (must contain "message" field) + */ +void WebSocket_Handle_DisplayMessage(int FD, cJSON *p_Data); + +/** @brief Handle "get_lock" command. + * @param FD Client file descriptor + * @param p_Data Command data (unused) + */ +void WebSocket_Handle_GetLock(int FD, cJSON *p_Data); + +/** @brief Handle "set_lock" command. + * @param FD Client file descriptor + * @param p_Data Command data (must contain "locked" field) + */ +void WebSocket_Handle_SetLock(int FD, cJSON *p_Data); + +#endif /* WEBSOCKET_REMOTE_HANDLERS_H_ */ diff --git a/main/Application/Manager/Network/Server/WebSocket/websocket.cpp b/main/Application/Manager/Network/Server/WebSocket/websocket.cpp index 6fad777..b8f0303 100644 --- a/main/Application/Manager/Network/Server/WebSocket/websocket.cpp +++ b/main/Application/Manager/Network/Server/WebSocket/websocket.cpp @@ -29,6 +29,7 @@ #include "websocket.h" #include "../ImageEncoder/imageEncoder.h" +#include "Private/websocketRemoteHandlers.h" /** @brief WebSocket client state. */ @@ -143,7 +144,7 @@ static void WebSocket_RemoveClient(int FD) * @param p_Data Data JSON object (will not be freed, can be NULL) * @return ESP_OK on success */ -static esp_err_t WebSocket_SendJSON(int FD, const char *p_Cmd, cJSON *p_Data) +esp_err_t WebSocket_SendJSON(int FD, const char *p_Cmd, cJSON *p_Data) { esp_err_t Error; char *JSON; @@ -330,7 +331,9 @@ static void WebSocket_ProcessMessage(WS_Client_t *p_Client, const char *p_Data, if (cJSON_IsString(cmd) == false) { ESP_LOGW(TAG, "Invalid message format from fd=%d", p_Client->fd); + cJSON_Delete(json); + return; } @@ -344,6 +347,48 @@ static void WebSocket_ProcessMessage(WS_Client_t *p_Client, const char *p_Data, WebSocket_HandleTelemetrySubscribe(p_Client, data); } else if (strcmp(cmd_str, "unsubscribe") == 0) { WebSocket_HandleTelemetryUnsubscribe(p_Client); + } + /* Remote Control Commands */ + else if (strcmp(cmd_str, "get_temperature") == 0) { + WebSocket_Handle_GetTemperature(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_time") == 0) { + WebSocket_Handle_GetTime(p_Client->fd, data); + } else if (strcmp(cmd_str, "set_time") == 0) { + WebSocket_Handle_SetTime(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_battery") == 0) { + WebSocket_Handle_GetBattery(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_lepton_emissivity") == 0) { + WebSocket_Handle_GetLeptonEmissivity(p_Client->fd, data); + } else if (strcmp(cmd_str, "set_lepton_emissivity") == 0) { + WebSocket_Handle_SetLeptonEmissivity(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_lepton_stats") == 0) { + WebSocket_Handle_GetLeptonStats(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_lepton_roi") == 0) { + WebSocket_Handle_GetLeptonROI(p_Client->fd, data); + } else if (strcmp(cmd_str, "set_lepton_roi") == 0) { + WebSocket_Handle_SetLeptonROI(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_lepton_spotmeter") == 0) { + WebSocket_Handle_GetLeptonSpotmeter(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_flash") == 0) { + WebSocket_Handle_GetFlash(p_Client->fd, data); + } else if (strcmp(cmd_str, "set_flash") == 0) { + WebSocket_Handle_SetFlash(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_image_format") == 0) { + WebSocket_Handle_GetImageFormat(p_Client->fd, data); + } else if (strcmp(cmd_str, "set_image_format") == 0) { + WebSocket_Handle_SetImageFormat(p_Client->fd, data); + } else if (strcmp(cmd_str, "set_status_led") == 0) { + WebSocket_Handle_SetStatusLED(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_sd_state") == 0) { + WebSocket_Handle_GetSDState(p_Client->fd, data); + } else if (strcmp(cmd_str, "format_memory") == 0) { + WebSocket_Handle_FormatMemory(p_Client->fd, data); + } else if (strcmp(cmd_str, "display_message") == 0) { + WebSocket_Handle_DisplayMessage(p_Client->fd, data); + } else if (strcmp(cmd_str, "get_lock") == 0) { + WebSocket_Handle_GetLock(p_Client->fd, data); + } else if (strcmp(cmd_str, "set_lock") == 0) { + WebSocket_Handle_SetLock(p_Client->fd, data); } else { ESP_LOGW(TAG, "Unknown command from fd=%d: %s", p_Client->fd, cmd_str); } diff --git a/main/Application/Manager/Network/Server/WebSocket/websocket.h b/main/Application/Manager/Network/Server/WebSocket/websocket.h index ba6c526..f5342d4 100644 --- a/main/Application/Manager/Network/Server/WebSocket/websocket.h +++ b/main/Application/Manager/Network/Server/WebSocket/websocket.h @@ -26,6 +26,7 @@ #include #include +#include #include "../../networkTypes.h" diff --git a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp index 9829e6e..efa608d 100644 --- a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp @@ -69,7 +69,7 @@ void SettingsManager_InitDefaultLeptonROIs(App_Settings_t *p_Settings) void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settings) { /* No emissiviy values available */ - p_Settings->Lepton.EmissivityCount = 1; + p_Settings->Lepton.EmissivityPresetsCount = 1; p_Settings->Lepton.EmissivityPresets[0].Value = 1.0f; strncpy(p_Settings->Lepton.EmissivityPresets[0].Description, "Unknown", sizeof(p_Settings->Lepton.EmissivityPresets[0].Description)); @@ -135,6 +135,7 @@ void SettingsManager_InitDefaultSystem(App_Settings_t *p_Settings) } p_Settings->System.SDCard_AutoMount = true; + p_Settings->System.ImageFormat = IMAGE_FORMAT_JPEG; strncpy(p_Settings->System.Timezone, SETTINGS_SYSTEM_DEFAULT_TIMEZONE, sizeof(p_Settings->System.Timezone)); strncpy(p_Settings->System.NTPServer, SETTINGS_SYSTEM_DEFAULT_NTP_SERVER, sizeof(p_Settings->System.NTPServer)); } diff --git a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp index 2990b68..b584443 100644 --- a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp @@ -52,11 +52,11 @@ static void SettingsManager_LoadLepton(Settings_Manager_State_t *p_State, const if (lepton != NULL) { emissivity_array = cJSON_GetObjectItem(lepton, "emissivity"); if (cJSON_IsArray(emissivity_array)) { - p_State->Settings.Lepton.EmissivityCount = cJSON_GetArraySize(emissivity_array); + p_State->Settings.Lepton.EmissivityPresetsCount = cJSON_GetArraySize(emissivity_array); - ESP_LOGD(TAG, "Found %d emissivity presets in JSON", p_State->Settings.Lepton.EmissivityCount); + ESP_LOGD(TAG, "Found %d emissivity presets in JSON", p_State->Settings.Lepton.EmissivityPresetsCount); - for (uint32_t i = 0; i < p_State->Settings.Lepton.EmissivityCount; i++) { + for (uint32_t i = 0; i < p_State->Settings.Lepton.EmissivityPresetsCount; i++) { cJSON *preset = cJSON_GetArrayItem(emissivity_array, i); cJSON *name = cJSON_GetObjectItem(preset, "name"); cJSON *value = cJSON_GetObjectItem(preset, "value"); @@ -225,6 +225,21 @@ static void SettingsManager_LoadSystem(Settings_Manager_State_t *p_State, const strncpy(p_State->Settings.System.DeviceName, SETTINGS_SYSTEM_DEFAULT_DEVICENAME, sizeof(p_State->Settings.System.DeviceName)); } + + cJSON *imageFormat = cJSON_GetObjectItem(system, "imageFormat"); + if (cJSON_IsString(imageFormat)) { + if (strcmp(imageFormat->valuestring, "PNG") == 0) { + p_State->Settings.System.ImageFormat = IMAGE_FORMAT_PNG; + } else if (strcmp(imageFormat->valuestring, "RAW") == 0) { + p_State->Settings.System.ImageFormat = IMAGE_FORMAT_RAW; + } else if (strcmp(imageFormat->valuestring, "JPEG") == 0) { + p_State->Settings.System.ImageFormat = IMAGE_FORMAT_JPEG; + } else { + p_State->Settings.System.ImageFormat = IMAGE_FORMAT_JPEG; /* Default to JPEG */ + } + } else { + p_State->Settings.System.ImageFormat = IMAGE_FORMAT_JPEG; /* Default to JPEG */ + } } else { SettingsManager_InitDefaultSystem(&p_State->Settings); } diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index a707c72..fdbe876 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -364,10 +364,10 @@ esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t *p_Settings) return ESP_OK; } -esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t *p_Settings) +esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t *p_Settings, SettingsManager_Setting_t *p_ChangedSetting) { return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.WiFi, sizeof(App_Settings_WiFi_t), - SETTINGS_EVENT_WIFI_CHANGED); + SETTINGS_EVENT_WIFI_CHANGED, p_ChangedSetting); } esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t *p_Settings) @@ -385,11 +385,11 @@ esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t *p_Setting return ESP_OK; } -esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t *p_Settings) +esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t *p_Settings, SettingsManager_Setting_t *p_ChangedSetting) { return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.Provisioning, sizeof(App_Settings_Provisioning_t), - SETTINGS_EVENT_PROVISIONING_CHANGED); + SETTINGS_EVENT_PROVISIONING_CHANGED, p_ChangedSetting); } esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t *p_Settings) @@ -407,10 +407,10 @@ esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t *p_Settings) return ESP_OK; } -esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t *p_Settings) +esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t *p_Settings, SettingsManager_Setting_t *p_ChangedSetting) { return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.Display, sizeof(App_Settings_Display_t), - SETTINGS_EVENT_DISPLAY_CHANGED); + SETTINGS_EVENT_DISPLAY_CHANGED, p_ChangedSetting); } esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t *p_Settings) @@ -428,11 +428,11 @@ esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t *p_Settings) return ESP_OK; } -esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t *p_Settings) +esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t *p_Settings, SettingsManager_Setting_t *p_ChangedSetting) { return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.HTTPServer, sizeof(App_Settings_HTTP_Server_t), - SETTINGS_EVENT_HTTP_SERVER_CHANGED); + SETTINGS_EVENT_HTTP_SERVER_CHANGED, p_ChangedSetting); } esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t *p_Settings) @@ -450,11 +450,11 @@ esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t *p_Settings) return ESP_OK; } -esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t *p_Settings) +esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t *p_Settings, SettingsManager_Setting_t *p_ChangedSetting) { return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.VISAServer, sizeof(App_Settings_VISA_Server_t), - SETTINGS_EVENT_VISA_SERVER_CHANGED); + SETTINGS_EVENT_VISA_SERVER_CHANGED, p_ChangedSetting); } esp_err_t SettingsManager_GetSystem(App_Settings_System_t *p_Settings) @@ -472,10 +472,10 @@ esp_err_t SettingsManager_GetSystem(App_Settings_System_t *p_Settings) return ESP_OK; } -esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t *p_Settings) +esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t *p_Settings, SettingsManager_Setting_t *p_ChangedSetting) { return SettingsManager_Update(p_Settings, &_Settings_Manager_State.Settings.System, sizeof(App_Settings_System_t), - SETTINGS_EVENT_SYSTEM_CHANGED); + SETTINGS_EVENT_SYSTEM_CHANGED, p_ChangedSetting); } esp_err_t SettingsManager_ResetToDefaults(void) diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h index a10792a..84bab75 100644 --- a/main/Application/Manager/Settings/settingsManager.h +++ b/main/Application/Manager/Settings/settingsManager.h @@ -110,12 +110,14 @@ esp_err_t SettingsManager_UpdateLepton(App_Settings_Lepton_t *p_Settings, */ esp_err_t SettingsManager_GetWiFi(App_Settings_WiFi_t *p_Settings); -/** @brief Update WiFi settings in the Settings Manager RAM. - * This function triggers the SETTINGS_EVENT_WIFI_CHANGED event. - * @param p_Settings Pointer to WiFi settings structure - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Update WiFi settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_WIFI_CHANGED event. + * @param p_Settings Pointer to WiFi settings structure + * @param p_ChangedSetting Optional pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t *p_Settings); +esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t *p_Settings, + SettingsManager_Setting_t *p_ChangedSetting = NULL); /** @brief Get the Provisioning settings from the Settings Manager RAM. * @param p_Settings Pointer to Provisioning settings structure to populate @@ -123,12 +125,14 @@ esp_err_t SettingsManager_UpdateWiFi(App_Settings_WiFi_t *p_Settings); */ esp_err_t SettingsManager_GetProvisioning(App_Settings_Provisioning_t *p_Settings); -/** @brief Update Provisioning settings in the Settings Manager RAM. - * This function triggers the SETTINGS_EVENT_PROVISIONING_CHANGED event. - * @param p_Settings Pointer to Provisioning settings structure - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Update Provisioning settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_PROVISIONING_CHANGED event. + * @param p_Settings Pointer to Provisioning settings structure + * @param p_ChangedSetting Optional pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t *p_Settings); +esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t *p_Settings, + SettingsManager_Setting_t *p_ChangedSetting = NULL); /** @brief Get the Display settings from the Settings Manager RAM. * @param p_Settings Pointer to Display settings structure to populate @@ -136,12 +140,14 @@ esp_err_t SettingsManager_UpdateProvisioning(App_Settings_Provisioning_t *p_Sett */ esp_err_t SettingsManager_GetDisplay(App_Settings_Display_t *p_Settings); -/** @brief Update Display settings in the Settings Manager RAM. - * This function triggers the SETTINGS_EVENT_DISPLAY_CHANGED event. - * @param p_Settings Pointer to Display settings structure - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Update Display settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_DISPLAY_CHANGED event. + * @param p_Settings Pointer to Display settings structure + * @param p_ChangedSetting Optional pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t *p_Settings); +esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t *p_Settings, + SettingsManager_Setting_t *p_ChangedSetting = NULL); /** @brief Get the HTTP Server settings from the Settings Manager RAM. * @param p_Settings Pointer to HTTP Server settings structure to populate @@ -149,12 +155,14 @@ esp_err_t SettingsManager_UpdateDisplay(App_Settings_Display_t *p_Settings); */ esp_err_t SettingsManager_GetHTTPServer(App_Settings_HTTP_Server_t *p_Settings); -/** @brief Update HTTP Server settings in the Settings Manager RAM. - * This function triggers the SETTINGS_EVENT_HTTP_SERVER_CHANGED event. - * @param p_Settings Pointer to HTTP Server settings structure - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Update HTTP Server settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_HTTP_SERVER_CHANGED event. + * @param p_Settings Pointer to HTTP Server settings structure + * @param p_ChangedSetting Optional pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t *p_Settings); +esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t *p_Settings, + SettingsManager_Setting_t *p_ChangedSetting = NULL); /** @brief Get the VISA Server settings from the Settings Manager RAM. * @param p_Settings Pointer to VISA Server settings structure to populate @@ -162,12 +170,14 @@ esp_err_t SettingsManager_UpdateHTTPServer(App_Settings_HTTP_Server_t *p_Setting */ esp_err_t SettingsManager_GetVISAServer(App_Settings_VISA_Server_t *p_Settings); -/** @brief Update VISA Server settings in the Settings Manager RAM. - * This function triggers the SETTINGS_EVENT_VISA_SERVER_CHANGED event. - * @param p_Settings Pointer to VISA Server settings structure - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Update VISA Server settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_VISA_SERVER_CHANGED event. + * @param p_Settings Pointer to VISA Server settings structure + * @param p_ChangedSetting Optional pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t *p_Settings); +esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t *p_Settings, + SettingsManager_Setting_t *p_ChangedSetting = NULL); /** @brief Get the system settings from the Settings Manager RAM. * @param p_Settings Pointer to System settings structure to populate @@ -175,12 +185,14 @@ esp_err_t SettingsManager_UpdateVISAServer(App_Settings_VISA_Server_t *p_Setting */ esp_err_t SettingsManager_GetSystem(App_Settings_System_t *p_Settings); -/** @brief Update System settings in the Settings Manager RAM. - * This function triggers the SETTINGS_EVENT_SYSTEM_CHANGED event. - * @param p_Settings Pointer to System settings structure - * @return ESP_OK on success, ESP_ERR_* on failure +/** @brief Update System settings in the Settings Manager RAM. + * This function triggers the SETTINGS_EVENT_SYSTEM_CHANGED event. + * @param p_Settings Pointer to System settings structure + * @param p_ChangedSetting Optional pointer to structure to receive changed setting ID and value for event data (can be NULL if not needed) + * @return ESP_OK on success, ESP_ERR_* on failure */ -esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t *p_Settings); +esp_err_t SettingsManager_UpdateSystem(App_Settings_System_t *p_Settings, + SettingsManager_Setting_t *p_ChangedSetting = NULL); /** @brief Reset all settings to factory defaults. * Erases NVS partition and reloads defaults. diff --git a/main/Application/Manager/Settings/settingsTypes.h b/main/Application/Manager/Settings/settingsTypes.h index f88dfbe..89db6f7 100644 --- a/main/Application/Manager/Settings/settingsTypes.h +++ b/main/Application/Manager/Settings/settingsTypes.h @@ -70,6 +70,7 @@ enum { */ enum { SETTINGS_ID_LEPTON_EMISSIVITY, /**< Emissivity setting changed. Data contains uint8_t with new emissivity value. */ + SETTINGS_ID_IMAGE_FORMAT, /**< Image format setting changed. Data contains App_Settings_Image_Format_t. */ }; /** @brief GUI ROI types. @@ -81,6 +82,14 @@ typedef enum { ROI_TYPE_VIDEO_FOCUS, /**< Video focus ROI. */ } App_Settings_ROI_Type_t; +/** @brief Image format types. + */ +typedef enum { + IMAGE_FORMAT_PNG = 0, /**< PNG format. */ + IMAGE_FORMAT_RAW = 1, /**< Raw format. */ + IMAGE_FORMAT_JPEG = 2, /**< JPEG format. */ +} App_Settings_Image_Format_t; + /** @brief Structure to hold the modified settings value. */ typedef struct { @@ -124,7 +133,7 @@ typedef struct { typedef struct { App_Settings_ROI_t ROI[4]; /**< Camera ROIs. */ App_Settings_Emissivity_t EmissivityPresets[128]; /**< Array of emissivity presets. */ - size_t EmissivityCount; /**< Number of emissivity presets. */ + size_t EmissivityPresetsCount; /**< Number of emissivity presets. */ uint8_t CurrentEmissivity; /**< Currently selected emissivity value in the range from 0 to 100. */ } __attribute__((packed)) App_Settings_Lepton_t; @@ -179,7 +188,8 @@ typedef struct { char Timezone[32]; /**< Timezone string (e.g., "CET-1CEST,M3.5.0,M10.5.0/3"). */ char NTPServer[32]; /**< NTP server address. */ char DeviceName[32]; /**< Device name. */ - uint8_t Reserved[100]; /**< Reserved for future use. */ + App_Settings_Image_Format_t ImageFormat; /**< Image format for captures (PNG, RAW, JPEG). */ + uint8_t Reserved[99]; /**< Reserved for future use. */ } __attribute__((packed)) App_Settings_System_t; /** @brief Complete application settings structure. diff --git a/main/Application/Tasks/GUI/UI/ui_Settings.cpp b/main/Application/Tasks/GUI/UI/ui_Settings.cpp index 99b6858..75c4712 100644 --- a/main/Application/Tasks/GUI/UI/ui_Settings.cpp +++ b/main/Application/Tasks/GUI/UI/ui_Settings.cpp @@ -391,7 +391,7 @@ static lv_obj_t *ui_Settings_Create_Lepton_Page(lv_obj_t *p_Menu) SettingsManager_GetLepton(&LeptonSettings); - for (size_t i = 0; i < LeptonSettings.EmissivityCount; i++) { + for (size_t i = 0; i < LeptonSettings.EmissivityPresetsCount; i++) { Buffer += LeptonSettings.EmissivityPresets[i].Description + std::string("\n"); } diff --git a/main/Application/Tasks/Network/networkTask.cpp b/main/Application/Tasks/Network/networkTask.cpp index bd16582..43df1df 100644 --- a/main/Application/Tasks/Network/networkTask.cpp +++ b/main/Application/Tasks/Network/networkTask.cpp @@ -35,6 +35,7 @@ #include "managers.h" #include "networkTask.h" #include "Application/Tasks/GUI/guiTask.h" +#include "Application/Manager/Network/Server/RemoteControl/remoteControl.h" #define NETWORK_TASK_STOP_REQUEST BIT0 #define NETWORK_TASK_BROADCAST_FRAME BIT1 @@ -388,7 +389,14 @@ static void Task_Network(void *p_Parameters) xEventGroupClearBits(_Network_Task_State.EventGroup, NETWORK_TASK_WIFI_CREDENTIALS_UPDATED); } else if (EventBits & LEPTON_SPOTMETER_READY) { if (Server_IsRunning()) { - // TODO Update Spotmeter in the Server + esp_err_t Error; + + Error = RemoteControl_UpdateSpotmeter(_Network_Task_State.ROIResult.Min, + _Network_Task_State.ROIResult.Max, + _Network_Task_State.ROIResult.Average); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to update spotmeter in server: 0x%x", Error); + } } xEventGroupClearBits(_Network_Task_State.EventGroup, LEPTON_SPOTMETER_READY); diff --git a/main/Application/application.h b/main/Application/application.h index 65a94a1..ac59c68 100644 --- a/main/Application/application.h +++ b/main/Application/application.h @@ -43,7 +43,7 @@ enum { LEPTON_EVENT_RESPONSE_FPA_AUX_TEMP, /**< FPA and AUX temperatures are ready. Data is transmitted in a App_Lepton_Temperatures_t structure. */ LEPTON_EVENT_RESPONSE_SPOTMETER, /**< Spotmeter data is ready. - Data is transmitted in a App_Lepton_Spotmeter_t structure. */ + Data is transmitted in a App_Lepton_Spotmeter_t structure with temperature value Celsius. */ LEPTON_EVENT_RESPONSE_UPTIME, /**< Uptime data is ready. Data is transmitted as a uint32_t representing uptime in milliseconds. */ LEPTON_EVENT_RESPONSE_PIXEL_TEMPERATURE, /**< Pixel temperature data is ready. From d805b2698e87c3a450b6cded8b42da4b5e30e83c Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Wed, 11 Feb 2026 21:56:34 +0100 Subject: [PATCH 15/26] Fix broken USB and Settings Manager --- .github/copilot-instructions.md | 4 +- docs/SettingsManager.adoc | 12 +-- .../Manager/Devices/devicesManager.cpp | 2 +- .../Private/settingsDefaultLoader.cpp | 28 +++--- .../Settings/Private/settingsJSONLoader.cpp | 57 +----------- .../Manager/Settings/Private/settingsLoader.h | 23 ++--- .../Manager/Settings/settingsManager.cpp | 92 +++++++++++++++---- .../Manager/Settings/settingsManager.h | 12 ++- main/Application/Manager/USB/usbManager.cpp | 45 ++++----- .../GUI/UI/Private/ui_Settings_Events.cpp | 4 +- 10 files changed, 144 insertions(+), 135 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 6bdb81e..e26f91c 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -280,8 +280,8 @@ esp_err_t SettingsManager_SetWiFi(const char *p_SSID, const char *p_Pass); **Example:** ```cpp -/* Reset config_loaded flag to allow reloading default config */ -Error = nvs_set_u8(_State.NVS_Handle, "config_loaded", false); +/* Reset config_valid flag to allow reloading default config */ +Error = nvs_set_u8(_State.NVS_Handle, "config_valid", false); ``` ### Structure Documentation diff --git a/docs/SettingsManager.adoc b/docs/SettingsManager.adoc index 88b42a3..013ec10 100644 --- a/docs/SettingsManager.adoc +++ b/docs/SettingsManager.adoc @@ -55,7 +55,7 @@ typedef struct { * *Namespace*: `"pyrovision"` * *Blob Key*: `"settings"` - Contains the complete `App_Settings_t` structure * *Version Key*: Reserved for future migrations -* *Config Loaded Flag*: `"config_loaded"` - Indicates whether JSON defaults have been loaded +* *Config valid Flag*: `"config_valid"` - Indicates a valid configuration in the NVS == Data Structures @@ -402,7 +402,7 @@ esp_err_t SettingsManager_ResetToDefaults(void); *Process*: 1. Deletes the `"settings"` key from NVS -2. Resets `"config_loaded"` flag (allows reloading JSON defaults) +2. Resets `"config_valid"` flag (allows reloading JSON defaults) 3. Executes `esp_restart()` *Return Value*: @@ -582,7 +582,7 @@ void configure_device_initial(void) 1. *JSON Config* (`data/default_settings.json`) * Loaded on first boot - * Flag `"config_loaded"` prevents reloading + * Flag `"config_valid"` prevents reloading of the configuration into the Flash memory * Flexible and easy to customize without recompilation 2. *Hardcoded Defaults* (in `settingsDefaultLoader.cpp`) @@ -635,7 +635,7 @@ void configure_device_initial(void) 1. Edit `data/default_settings.json` 2. Flash firmware -3. Perform factory reset or manually reset `config_loaded` flag +3. Perform factory reset or manually reset `config_valid` flag ==== Option 2: Change Hardcoded Defaults @@ -699,7 +699,7 @@ SettingsManager_Save(); // <-- Don't forget! *Symptom*: JSON defaults are ignored -*Cause*: `config_loaded` flag is set +*Cause*: `config_valid` flag is set *Solution*: [source,cpp] @@ -707,7 +707,7 @@ SettingsManager_Save(); // <-- Don't forget! // Manually reset flag nvs_handle_t handle; nvs_open("pyrovision", NVS_READWRITE, &handle); -nvs_set_u8(handle, "config_loaded", 0); +nvs_set_u8(handle, "config_valid", 0); nvs_commit(handle); nvs_close(handle); esp_restart(); diff --git a/main/Application/Manager/Devices/devicesManager.cpp b/main/Application/Manager/Devices/devicesManager.cpp index 2900ec4..540b996 100644 --- a/main/Application/Manager/Devices/devicesManager.cpp +++ b/main/Application/Manager/Devices/devicesManager.cpp @@ -140,7 +140,7 @@ esp_err_t DevicesManager_Init(void) memset(&_Devices_Manager_State, 0, sizeof(Devices_Manager_State_t)); - if (I2CM_Init(&_Devices_Manager_Touch_I2CM_Config, &_Devices_Manager_State.I2C_Bus_Handle) != ESP_OK) { + if (I2CM_Init(&_Devices_Manager_Touch_I2CM_Config, &_Devices_Manager_State.Touch_I2C_Bus_Handle) != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize Touch I2C!"); return ESP_FAIL; diff --git a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp index efa608d..d199d6e 100644 --- a/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsDefaultLoader.cpp @@ -77,20 +77,6 @@ void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settin p_Settings->Lepton.CurrentEmissivity = SETTINGS_DEFAULT_LEPTON_EMISSIVITY; } -void SettingsManager_InitDefaults(Settings_Manager_State_t *p_State) -{ - memset(&p_State->Settings, 0, sizeof(App_Settings_t)); - - p_State->Settings.Version = SETTINGS_VERSION; - SettingsManager_InitDefaultDisplay(&p_State->Settings); - SettingsManager_InitDefaultProvisioning(&p_State->Settings); - SettingsManager_InitDefaultWiFi(&p_State->Settings); - SettingsManager_InitDefaultSystem(&p_State->Settings); - SettingsManager_InitDefaultLepton(&p_State->Settings); - SettingsManager_InitDefaultHTTPServer(&p_State->Settings); - SettingsManager_InitDefaultVISAServer(&p_State->Settings); -} - void SettingsManager_InitDefaultDisplay(App_Settings_t *p_Settings) { ESP_LOGW(TAG, "Loading default Display settings"); @@ -162,4 +148,18 @@ void SettingsManager_InitDefaultVISAServer(App_Settings_t *p_Settings) ESP_LOGW(TAG, "Loading default VISA Server settings"); p_Settings->VISAServer.Port = SETTINGS_DEFAULT_VISA_PORT; +} + +void SettingsManager_LoadFromDefaults(Settings_Manager_State_t *p_State) +{ + memset(&p_State->Settings, 0, sizeof(App_Settings_t)); + + p_State->Settings.Version = SETTINGS_VERSION; + SettingsManager_InitDefaultDisplay(&p_State->Settings); + SettingsManager_InitDefaultProvisioning(&p_State->Settings); + SettingsManager_InitDefaultWiFi(&p_State->Settings); + SettingsManager_InitDefaultSystem(&p_State->Settings); + SettingsManager_InitDefaultLepton(&p_State->Settings); + SettingsManager_InitDefaultHTTPServer(&p_State->Settings); + SettingsManager_InitDefaultVISAServer(&p_State->Settings); } \ No newline at end of file diff --git a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp index b584443..2185232 100644 --- a/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp +++ b/main/Application/Manager/Settings/Private/settingsJSONLoader.cpp @@ -301,12 +301,7 @@ static void SettingsManager_LoadVISAServer(Settings_Manager_State_t *p_State, co } } -/** @brief Load and parse JSON settings from file. - * @param p_State Settings state structure - * @param filepath Full path to JSON file - * @return ESP_OK on success - */ -static esp_err_t SettingsManager_Load_JSON(Settings_Manager_State_t *p_State, const char *p_FilePath) +esp_err_t SettingsManager_LoadFromJSON(Settings_Manager_State_t *p_State, const char *p_FilePath) { FILE *File = NULL; char *Buffer = NULL; @@ -315,7 +310,7 @@ static esp_err_t SettingsManager_Load_JSON(Settings_Manager_State_t *p_State, co cJSON *JSON = NULL; esp_err_t Error; - ESP_LOGD(TAG, "Loading settings from: %s", p_FilePath); + ESP_LOGD(TAG, "Loading JSON settings from: %s", p_FilePath); /* Check if file exists */ struct stat st; @@ -386,7 +381,7 @@ static esp_err_t SettingsManager_Load_JSON(Settings_Manager_State_t *p_State, co return ESP_FAIL; } - ESP_LOGD(TAG, "JSON parsed successfully from %s", p_FilePath); + ESP_LOGI(TAG, "JSON parsed successfully from %s", p_FilePath); /* Check the version number of the JSON and the version from the firmware. Skip the loading if the version in the JSON is older or invalid. */ cJSON *version = cJSON_GetObjectItem(JSON, "version"); @@ -435,49 +430,3 @@ static esp_err_t SettingsManager_Load_JSON(Settings_Manager_State_t *p_State, co return Error; } - -esp_err_t SettingsManager_LoadDefaultsFromJSON(Settings_Manager_State_t *p_State) -{ - uint8_t ConfigLoaded = 0; - esp_err_t Error; - - Error = nvs_get_u8(p_State->NVS_Handle, "config_loaded", &ConfigLoaded); - if ((Error == ESP_OK) && (ConfigLoaded == true)) { - ESP_LOGD(TAG, "Default config already loaded, skipping"); - return ESP_OK; - } - - ESP_LOGI(TAG, "Loading settings from /storage (managed by MemoryManager)"); - - /* Try to load from /storage - MemoryManager decides if this is SD card or internal flash */ - Error = SettingsManager_Load_JSON(p_State, "/storage/settings.json"); - if (Error == ESP_OK) { - ESP_LOGI(TAG, "Settings loaded from /storage/settings.json"); - - /* Do NOT delete the file - user should be able to edit it via USB or by placing it on SD card */ - return ESP_OK; - } - - ESP_LOGW(TAG, "No settings.json found on /storage, falling back to built-in defaults"); - - /* Fallback to built-in defaults */ - ESP_LOGW(TAG, "Using built-in default settings"); - SettingsManager_InitDefaults(p_State); - - /* Mark config as loaded */ - Error = nvs_set_u8(p_State->NVS_Handle, "config_loaded", true); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to set config_loaded flag: %d!", Error); - return Error; - } - - Error = nvs_commit(p_State->NVS_Handle); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to commit config_loaded flag: %d!", Error); - return Error; - } - - ESP_LOGD(TAG, "Default config loaded and marked as valid"); - - return ESP_OK; -} \ No newline at end of file diff --git a/main/Application/Manager/Settings/Private/settingsLoader.h b/main/Application/Manager/Settings/Private/settingsLoader.h index 2bceada..ba22ec5 100644 --- a/main/Application/Manager/Settings/Private/settingsLoader.h +++ b/main/Application/Manager/Settings/Private/settingsLoader.h @@ -70,13 +70,19 @@ typedef struct { SemaphoreHandle_t Mutex; } Settings_Manager_State_t; -/** @brief Initialize the settings presets from the NVS by using a config JSON file. - * @param p_State Pointer to the Settings Manager state structure - * @return ESP_OK on succes - * ESP_ERR_INVALID_VERSION if the version in the JSON is older or invalid - * ESP_ERR_* on failure + +/** @brief Load and parse JSON settings from file into RAM settings structure. + * If the file is missing or invalid, returns an error and leaves settings unchanged. + * @param p_State Settings state structure + * @param filepath Full path to JSON file + * @return ESP_OK on success + */ +esp_err_t SettingsManager_LoadFromJSON(Settings_Manager_State_t *p_State, const char *p_FilePath); + +/** @brief Load factory default settings into RAM settings structure. This is used when no valid settings are found in NVS or JSON config. + * @param p_State Pointer to Settings Manager state structure */ -esp_err_t SettingsManager_LoadDefaultsFromJSON(Settings_Manager_State_t *p_State); +void SettingsManager_LoadFromDefaults(Settings_Manager_State_t *p_State); /** @brief Initialize Lepton ROIs with factory defaults. * @param p_Settings Pointer to settings structure @@ -88,11 +94,6 @@ void SettingsManager_InitDefaultLeptonROIs(App_Settings_t *p_Settings); */ void SettingsManager_InitDefaultLeptonEmissivityPresets(App_Settings_t *p_Settings); -/** @brief Initialize settings with factory defaults. - * @param p_State Pointer to Settings Manager state structure - */ -void SettingsManager_InitDefaults(Settings_Manager_State_t *p_State); - /** @brief Initialize Display settings with factory defaults. * @param p_Settings Pointer to settings structure */ diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index fdbe876..96591cf 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -165,23 +165,23 @@ esp_err_t SettingsManager_Init(void) } /* Load the settings from the NVS */ - Error = SettingsManager_Load(&_Settings_Manager_State.Settings); + Error = SettingsManager_LoadFromNVS(&_Settings_Manager_State.Settings); if (Error != ESP_OK) { - ESP_LOGI(TAG, "No settings found, using factory defaults"); + ESP_LOGI(TAG, "No settings found, using JSON config defaults"); /* Try to load default settings from JSON first (on first boot) */ - if (SettingsManager_LoadDefaultsFromJSON(&_Settings_Manager_State) != ESP_OK) { + if (SettingsManager_LoadFromJSON(&_Settings_Manager_State, "/storage/settings.json") != ESP_OK) { ESP_LOGW(TAG, "Failed to load default settings from JSON, using built-in defaults"); /* Use built-in defaults */ - SettingsManager_InitDefaults(&_Settings_Manager_State); + SettingsManager_LoadFromDefaults(&_Settings_Manager_State); } /* Save the default settings to NVS */ SettingsManager_Save(); /* Load the JSON presets into the settings structure */ - SettingsManager_Load(&_Settings_Manager_State.Settings); + SettingsManager_LoadFromNVS(&_Settings_Manager_State.Settings); } ESP_LOGI(TAG, "Settings Manager initialized"); @@ -208,10 +208,11 @@ esp_err_t SettingsManager_Deinit(void) return ESP_OK; } -esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) +esp_err_t SettingsManager_LoadFromNVS(App_Settings_t *p_Settings) { esp_err_t Error; size_t RequiredSize; + uint8_t ConfigValid; if (_Settings_Manager_State.isInitialized == false) { return ESP_ERR_INVALID_STATE; @@ -221,22 +222,32 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + /* Check if the config is valid */ + Error = nvs_get_u8(_Settings_Manager_State.NVS_Handle, "config_valid", &ConfigValid); + if ((Error != ESP_OK) || (ConfigValid != 1)) { + ESP_LOGE(TAG, "Failed to read config_valid flag: %d!", Error); + + Error = ESP_ERR_NVS_INVALID_STATE; + + goto SettingsManager_LoadFromNVS_Exit; + } + /* Get the settings version from NVS. Continue loading if the version numbers match. */ Error = nvs_get_u32(_Settings_Manager_State.NVS_Handle, "version", &p_Settings->Version); - if ((Error == ESP_OK) && (p_Settings->Version == SETTINGS_VERSION)) { + if ((Error != ESP_OK) && (p_Settings->Version == SETTINGS_VERSION)) { Error = nvs_get_blob(_Settings_Manager_State.NVS_Handle, "settings", NULL, &RequiredSize); if (Error == ESP_ERR_NVS_NOT_FOUND) { ESP_LOGW(TAG, "Settings not found in NVS!"); Error = ESP_ERR_NVS_NOT_FOUND; - goto SettingsManager_Load_Exit; + goto SettingsManager_LoadFromNVS_Exit; } else if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to get settings size: %d!", Error); xSemaphoreGive(_Settings_Manager_State.Mutex); - goto SettingsManager_Load_Exit; + goto SettingsManager_LoadFromNVS_Exit; } if (RequiredSize != sizeof(App_Settings_t)) { @@ -249,14 +260,14 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) Error = ESP_ERR_INVALID_SIZE; - goto SettingsManager_Load_Exit; + goto SettingsManager_LoadFromNVS_Exit; } Error = nvs_get_blob(_Settings_Manager_State.NVS_Handle, "settings", &_Settings_Manager_State.Settings, &RequiredSize); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to read settings: %d!", Error); - goto SettingsManager_Load_Exit; + goto SettingsManager_LoadFromNVS_Exit; } memcpy(p_Settings, &_Settings_Manager_State.Settings, sizeof(App_Settings_t)); @@ -267,13 +278,13 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings) } /* We reach this case when we can no read a settings version because it does not exist or does not match */ else { - ESP_LOGI(TAG, "Settings version mismatch or not found in NVS (expected %u, got %u), erasing and using defaults", + ESP_LOGI(TAG, "Settings version mismatch or not found in NVS (expected %u, got %u)", SETTINGS_VERSION, p_Settings->Version); Error = ESP_ERR_INVALID_VERSION; } -SettingsManager_Load_Exit: +SettingsManager_LoadFromNVS_Exit: xSemaphoreGive(_Settings_Manager_State.Mutex); return Error; @@ -293,15 +304,23 @@ esp_err_t SettingsManager_Save(void) sizeof(App_Settings_t)); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to write settings: %d!", Error); - xSemaphoreGive(_Settings_Manager_State.Mutex); - return Error; + + goto SettingsManager_Save_Error; + } + + /* Mark config as valid */ + Error = nvs_set_u8(_Settings_Manager_State.NVS_Handle, "config_valid", true); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set config_valid flag: %d!", Error); + + goto SettingsManager_Save_Error; } Error = nvs_commit(_Settings_Manager_State.NVS_Handle); if (Error != ESP_OK) { ESP_LOGE(TAG, "Failed to commit settings: %d!", Error); - xSemaphoreGive(_Settings_Manager_State.Mutex); - return Error; + + goto SettingsManager_Save_Error; } xSemaphoreGive(_Settings_Manager_State.Mutex); @@ -311,6 +330,39 @@ esp_err_t SettingsManager_Save(void) esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_SAVED, NULL, 0, portMAX_DELAY); return ESP_OK; + +SettingsManager_Save_Error: + xSemaphoreGive(_Settings_Manager_State.Mutex); + + ESP_LOGE(TAG, "Failed to save settings to NVS: %d!", Error); + + return Error; +} + +esp_err_t SettingsManager_Reset(void) +{ + esp_err_t Error; + + if (_Settings_Manager_State.isInitialized == false) { + return ESP_ERR_INVALID_STATE; + } + + /* Mark the config as invalid */ + Error = nvs_set_u8(_Settings_Manager_State.NVS_Handle, "config_valid", true); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to set config_valid flag: %d!", Error); + + return Error; + } + + Error = nvs_commit(_Settings_Manager_State.NVS_Handle); + if(Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit settings reset: %d!", Error); + + return Error; + } + + esp_restart(); } esp_err_t SettingsManager_GetInfo(App_Settings_Info_t *p_Settings) @@ -508,10 +560,10 @@ esp_err_t SettingsManager_ResetToDefaults(void) return Error; } - /* Reset config_loaded flag to allow reloading default config */ - Error = nvs_set_u8(_Settings_Manager_State.NVS_Handle, "config_loaded", false); + /* Reset config_valid flag to allow reloading default config */ + Error = nvs_set_u8(_Settings_Manager_State.NVS_Handle, "config_valid", false); if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to set config_loaded flag: %d!", Error); + ESP_LOGE(TAG, "Failed to set config_valid flag: %d!", Error); xSemaphoreGive(_Settings_Manager_State.Mutex); diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h index 84bab75..8cbc09e 100644 --- a/main/Application/Manager/Settings/settingsManager.h +++ b/main/Application/Manager/Settings/settingsManager.h @@ -63,12 +63,13 @@ esp_err_t SettingsManager_Deinit(void); * @param p_Settings Pointer to settings structure to populate * @return ESP_OK on success * ESP_ERR_INVALID_ARG if p_Settings is NULL + * ESP_ERR_NVS_INVALID_STATE if config_valid flag is missing or false * ESP_ERR_NVS_NOT_FOUND if no settings exist in NVS * ESP_ERR_INVALID_VERSION if version mismatch * ESP_ERR_INVALID_SIZE if size mismatch (corrupted) * ESP_FAIL on other NVS errors */ -esp_err_t SettingsManager_Load(App_Settings_t *p_Settings); +esp_err_t SettingsManager_LoadFromNVS(App_Settings_t *p_Settings); /** @brief Save all RAM settings to NVS. * Writes current settings from RAM to non-volatile storage. Changes @@ -83,6 +84,15 @@ esp_err_t SettingsManager_Load(App_Settings_t *p_Settings); */ esp_err_t SettingsManager_Save(void); +/** @brief Reset settings in NVS to factory defaults. + * Marks the config as invalid in NVS and triggers a reboot, causing defaults to be loaded on next init. + * @return ESP_OK on success + * ESP_ERR_INVALID_STATE if not initialized + * ESP_ERR_NVS_NOT_ENOUGH_SPACE if NVS is full + * ESP_FAIL if NVS write fails + */ +esp_err_t SettingsManager_Reset(void); + /** @brief Get the device information from the Settings Manager RAM. * @param p_Settings Pointer to Info structure to populate * @return ESP_OK on success, ESP_ERR_* on failure diff --git a/main/Application/Manager/USB/usbManager.cpp b/main/Application/Manager/USB/usbManager.cpp index e2c7b1e..316e5ce 100644 --- a/main/Application/Manager/USB/usbManager.cpp +++ b/main/Application/Manager/USB/usbManager.cpp @@ -39,15 +39,12 @@ ESP_EVENT_DEFINE_BASE(USB_EVENTS); -static const char *TAG = "USB-Manager"; - /** @brief USB Manager internal state. */ typedef struct { bool isInitialized; /**< Initialization state. */ bool isDeinitializing; /**< Deinitialization in progress. */ bool isUSBMounted; /**< USB host has mounted device. */ - USB_Manager_Config_t Config; /**< Current configuration. */ tinyusb_msc_storage_handle_t Storage; /**< Storage handle. */ TaskHandle_t DeinitTask; /**< Deinit task handle. */ tusb_desc_device_t DeviceDescriptor; /**< Custom device descriptor. */ @@ -56,9 +53,13 @@ typedef struct { static USB_Manager_State_t _USB_Manager_State; +static const char *TAG = "USB-Manager"; + esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) { esp_err_t Error; + MemoryManager_Location_t StorageLocation; + tinyusb_config_t USB_Config = TINYUSB_DEFAULT_CONFIG(); if (p_Config == NULL) { ESP_LOGE(TAG, "Invalid configuration pointer!"); @@ -76,9 +77,11 @@ esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) /* Wait for any pending deinitialization to complete */ if (_USB_Manager_State.isDeinitializing) { + uint8_t WaitCount; + ESP_LOGD(TAG, "Waiting for previous deinit to complete..."); - uint8_t WaitCount = 0; + WaitCount = 0; while ((_USB_Manager_State.isDeinitializing) && (WaitCount < 100)) { vTaskDelay(100 / portTICK_PERIOD_MS); WaitCount++; @@ -97,14 +100,13 @@ esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) } /* Detect active storage type from MemoryManager */ - MemoryManager_Location_t StorageLocation = MemoryManager_GetStorageLocation(); + StorageLocation = MemoryManager_GetStorageLocation(); const char *p_StorageTypeName = (StorageLocation == MEMORY_LOCATION_SD_CARD) ? "SD Card (FAT32)" : "Internal Flash (FAT32)"; - ESP_LOGD(TAG, "Initializing USB Manager..."); - memset(&_USB_Manager_State, 0, sizeof(USB_Manager_State_t)); + ESP_LOGD(TAG, "Initializing USB Manager..."); ESP_LOGD(TAG, " Storage type: %s (auto-detected)", p_StorageTypeName); ESP_LOGD(TAG, " Mount point: %s", p_Config->MountPoint); @@ -114,33 +116,27 @@ esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) ESP_LOGW(TAG, "Failed to lock filesystem: %d!", Error); } - memcpy(&_USB_Manager_State.Config, p_Config, sizeof(USB_Manager_Config_t)); - /* Configure the Device Descriptor */ memcpy(&_USB_Manager_State.DeviceDescriptor, get_Desc_Device(), sizeof(tusb_desc_device_t)); - /* Configure the String Descriptors */ - _USB_Manager_State.StringDescriptors[0] = NULL; // 0: Language (set by TinyUSB) - _USB_Manager_State.StringDescriptors[1] = p_Config->Manufacturer; // 1: Manufacturer - _USB_Manager_State.StringDescriptors[2] = p_Config->Product; // 2: Product - _USB_Manager_State.StringDescriptors[3] = p_Config->SerialNumber; // 3: Serial Number + _USB_Manager_State.StringDescriptors[0] = ""; // 0: Empty string (Language handled by TinyUSB) + _USB_Manager_State.StringDescriptors[1] = p_Config->Manufacturer; // 1: Manufacturer + _USB_Manager_State.StringDescriptors[2] = p_Config->Product; // 2: Product + _USB_Manager_State.StringDescriptors[3] = p_Config->SerialNumber; // 3: Serial Number ESP_LOGD(TAG, "USB Descriptors:"); ESP_LOGD(TAG, " VID:PID = 0x%04X:0x%04X", _USB_Manager_State.DeviceDescriptor.idVendor, _USB_Manager_State.DeviceDescriptor.idProduct); - ESP_LOGD(TAG, " Manufacturer: %s", p_Config->Manufacturer ? p_Config->Manufacturer : "(null)"); - ESP_LOGD(TAG, " Product: %s", p_Config->Product ? p_Config->Product : "(null)"); - ESP_LOGD(TAG, " Serial: %s", p_Config->SerialNumber ? p_Config->SerialNumber : "(null)"); - - ESP_LOGD(TAG, "Initializing TinyUSB..."); - - tinyusb_config_t USB_Config = TINYUSB_DEFAULT_CONFIG(); + ESP_LOGD(TAG, " Manufacturer: %s", _USB_Manager_State.StringDescriptors[1]); + ESP_LOGD(TAG, " Product: %s", _USB_Manager_State.StringDescriptors[2]); + ESP_LOGD(TAG, " Serial: %s", _USB_Manager_State.StringDescriptors[3]); /* Override with custom descriptors */ USB_Config.descriptor.device = &_USB_Manager_State.DeviceDescriptor; USB_Config.descriptor.string = _USB_Manager_State.StringDescriptors; - USB_Config.descriptor.string_count = 4; + USB_Config.descriptor.string_count = sizeof(_USB_Manager_State.StringDescriptors) / sizeof(_USB_Manager_State.StringDescriptors[0]); + ESP_LOGD(TAG, "Initializing TinyUSB..."); Error = tinyusb_driver_install(&USB_Config); if (Error != ESP_OK) { if (Error == ESP_ERR_INVALID_STATE) { @@ -169,8 +165,8 @@ esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) /* Initialize MSC storage based on detected storage location */ if (StorageLocation == MEMORY_LOCATION_SD_CARD) { sdmmc_card_t *p_Card = NULL; + tinyusb_msc_storage_config_t Storage_Config; - /* Configure SD card MSC */ ESP_LOGD(TAG, "Configuring SD Card MSC..."); /* Get SD card handle from MemoryManager */ @@ -183,7 +179,6 @@ esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) ESP_LOGD(TAG, "Using SD card from MemoryManager"); - tinyusb_msc_storage_config_t Storage_Config; memset(&Storage_Config, 0, sizeof(tinyusb_msc_storage_config_t)); Storage_Config.medium.card = p_Card; @@ -195,6 +190,7 @@ esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) } } else if (StorageLocation == MEMORY_LOCATION_INTERNAL) { wl_handle_t WL_Handle; + tinyusb_msc_storage_config_t Storage_Config; /* Configure SPI flash (FAT32 with Wear Leveling) MSC */ ESP_LOGD(TAG, "Configuring internal flash MSC..."); @@ -209,7 +205,6 @@ esp_err_t USBManager_Init(const USB_Manager_Config_t *p_Config) ESP_LOGD(TAG, "Using existing wear leveling handle: %d", WL_Handle); - tinyusb_msc_storage_config_t Storage_Config; memset(&Storage_Config, 0, sizeof(tinyusb_msc_storage_config_t)); Storage_Config.medium.wl_handle = WL_Handle; diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp index 9f6dd8f..17aac78 100644 --- a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp +++ b/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp @@ -27,6 +27,8 @@ #include "ui_Settings_Events.h" +static USB_Manager_Config_t USB_Config; + static const char *TAG = "ui_Settings_Events"; void on_Lepton_Emissivity_Slider_Callback(lv_event_t *e) @@ -248,7 +250,7 @@ void on_USB_Mode_Switch_Callback(lv_event_t *e) SettingsManager_GetInfo(&InfoSettings); /* Configure USB Mass Storage with auto-detected mount point */ - USB_Manager_Config_t USB_Config = { + USB_Config = { .MountPoint = MemoryManager_GetStoragePath(), .Manufacturer = InfoSettings.Manufacturer, .Product = InfoSettings.Name, From 968eeb9cc162d034ae5a6b8f396fd5bd86a02bc0 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Thu, 12 Feb 2026 11:23:24 +0100 Subject: [PATCH 16/26] Improve WiFi provisioning, optimize WiFi UI elements --- .../Provisioning/provisionHandlers.cpp | 19 +- .../Manager/Settings/settingsManager.cpp | 38 +--- .../Manager/Settings/settingsManager.h | 9 - .../Tasks/GUI/Export/ui_events.cpp | 53 +----- main/Application/Tasks/GUI/Export/ui_events.h | 5 + .../Tasks/GUI/Private/guiImageSave.cpp | 10 + main/Application/Tasks/GUI/UI/ui_Settings.cpp | 175 +++++++++--------- main/Application/Tasks/GUI/UI/ui_Settings.h | 9 +- .../Tasks/GUI/UI/ui_messagebox.cpp | 78 ++++++++ main/Application/Tasks/GUI/UI/ui_messagebox.h | 42 +++++ ...ings_Events.cpp => ui_settings_events.cpp} | 4 +- ...Settings_Events.h => ui_settings_events.h} | 0 main/Application/Tasks/GUI/guiTask.cpp | 98 ++++++---- main/Application/application.h | 1 + webserver/provision.html | 57 ++++-- 15 files changed, 363 insertions(+), 235 deletions(-) create mode 100644 main/Application/Tasks/GUI/UI/ui_messagebox.cpp create mode 100644 main/Application/Tasks/GUI/UI/ui_messagebox.h rename main/Application/Tasks/GUI/UI/{Private/ui_Settings_Events.cpp => ui_settings_events.cpp} (99%) rename main/Application/Tasks/GUI/UI/{Private/ui_Settings_Events.h => ui_settings_events.h} (100%) diff --git a/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp b/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp index 2e085ec..d37e308 100644 --- a/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp +++ b/main/Application/Manager/Network/Provisioning/provisionHandlers.cpp @@ -123,9 +123,14 @@ esp_err_t Provision_Handler_Scan(httpd_req_t *p_Request) { wifi_scan_config_t ScanConfig; uint16_t APCount = 0; + uint16_t MaxAPCount = 50; /* Increased from default 20 to support more networks */ esp_err_t Error; memset(&ScanConfig, 0, sizeof(ScanConfig)); + ScanConfig.show_hidden = true; /* Also scan for hidden networks */ + ScanConfig.scan_type = WIFI_SCAN_TYPE_ACTIVE; /* Active scan for better detection */ + ScanConfig.scan_time.active.min = 120; /* Minimum scan time per channel (ms) */ + ScanConfig.scan_time.active.max = 150; /* Maximum scan time per channel (ms) */ /* Start async scan */ Error = esp_wifi_scan_start(&ScanConfig, false); @@ -140,8 +145,8 @@ esp_err_t Provision_Handler_Scan(httpd_req_t *p_Request) return Provision_Handler_Send_JSON_Response(p_Request, Response, 200); } - /* Wait for scan to complete (max 10 seconds) */ - for (uint8_t i = 0; i < 100; i++) { + /* Wait for scan to complete (max 15 seconds for thorough scan) */ + for (uint8_t i = 0; i < 150; i++) { vTaskDelay(100 / portTICK_PERIOD_MS); if (esp_wifi_scan_get_ap_num(&APCount) == ESP_OK) { break; @@ -151,11 +156,21 @@ esp_err_t Provision_Handler_Scan(httpd_req_t *p_Request) if (APCount == 0) { cJSON *Response; + ESP_LOGI(TAG, "No networks found in scan"); + Response = cJSON_CreateObject(); cJSON_AddArrayToObject(Response, "networks"); return Provision_Handler_Send_JSON_Response(p_Request, Response, 200); } + ESP_LOGI(TAG, "Found %d networks", APCount); + + /* Limit to maximum to prevent memory issues */ + if (APCount > MaxAPCount) { + ESP_LOGW(TAG, "Found %d networks, limiting to %d", APCount, MaxAPCount); + APCount = MaxAPCount; + } + wifi_ap_record_t *APList = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * APCount); if (APList == NULL) { httpd_resp_send_500(p_Request); diff --git a/main/Application/Manager/Settings/settingsManager.cpp b/main/Application/Manager/Settings/settingsManager.cpp index 96591cf..d0d5e23 100644 --- a/main/Application/Manager/Settings/settingsManager.cpp +++ b/main/Application/Manager/Settings/settingsManager.cpp @@ -234,7 +234,7 @@ esp_err_t SettingsManager_LoadFromNVS(App_Settings_t *p_Settings) /* Get the settings version from NVS. Continue loading if the version numbers match. */ Error = nvs_get_u32(_Settings_Manager_State.NVS_Handle, "version", &p_Settings->Version); - if ((Error != ESP_OK) && (p_Settings->Version == SETTINGS_VERSION)) { + if ((Error == ESP_OK) && (p_Settings->Version == SETTINGS_VERSION)) { Error = nvs_get_blob(_Settings_Manager_State.NVS_Handle, "settings", NULL, &RequiredSize); if (Error == ESP_ERR_NVS_NOT_FOUND) { ESP_LOGW(TAG, "Settings not found in NVS!"); @@ -300,6 +300,14 @@ esp_err_t SettingsManager_Save(void) xSemaphoreTake(_Settings_Manager_State.Mutex, portMAX_DELAY); + /* Save the version number first */ + Error = nvs_set_u32(_Settings_Manager_State.NVS_Handle, "version", _Settings_Manager_State.Settings.Version); + if (Error != ESP_OK) { + ESP_LOGE(TAG, "Failed to write version: %d!", Error); + + goto SettingsManager_Save_Error; + } + Error = nvs_set_blob(_Settings_Manager_State.NVS_Handle, "settings", &_Settings_Manager_State.Settings, sizeof(App_Settings_t)); if (Error != ESP_OK) { @@ -325,7 +333,7 @@ esp_err_t SettingsManager_Save(void) xSemaphoreGive(_Settings_Manager_State.Mutex); - ESP_LOGI(TAG, "Settings saved to NVS"); + ESP_LOGI(TAG, "Settings saved to NVS (version %u)", _Settings_Manager_State.Settings.Version); esp_event_post(SETTINGS_EVENTS, SETTINGS_EVENT_SAVED, NULL, 0, portMAX_DELAY); @@ -339,32 +347,6 @@ esp_err_t SettingsManager_Save(void) return Error; } -esp_err_t SettingsManager_Reset(void) -{ - esp_err_t Error; - - if (_Settings_Manager_State.isInitialized == false) { - return ESP_ERR_INVALID_STATE; - } - - /* Mark the config as invalid */ - Error = nvs_set_u8(_Settings_Manager_State.NVS_Handle, "config_valid", true); - if (Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to set config_valid flag: %d!", Error); - - return Error; - } - - Error = nvs_commit(_Settings_Manager_State.NVS_Handle); - if(Error != ESP_OK) { - ESP_LOGE(TAG, "Failed to commit settings reset: %d!", Error); - - return Error; - } - - esp_restart(); -} - esp_err_t SettingsManager_GetInfo(App_Settings_Info_t *p_Settings) { if ( p_Settings == NULL ) { diff --git a/main/Application/Manager/Settings/settingsManager.h b/main/Application/Manager/Settings/settingsManager.h index 8cbc09e..3406f23 100644 --- a/main/Application/Manager/Settings/settingsManager.h +++ b/main/Application/Manager/Settings/settingsManager.h @@ -84,15 +84,6 @@ esp_err_t SettingsManager_LoadFromNVS(App_Settings_t *p_Settings); */ esp_err_t SettingsManager_Save(void); -/** @brief Reset settings in NVS to factory defaults. - * Marks the config as invalid in NVS and triggers a reboot, causing defaults to be loaded on next init. - * @return ESP_OK on success - * ESP_ERR_INVALID_STATE if not initialized - * ESP_ERR_NVS_NOT_ENOUGH_SPACE if NVS is full - * ESP_FAIL if NVS write fails - */ -esp_err_t SettingsManager_Reset(void); - /** @brief Get the device information from the Settings Manager RAM. * @param p_Settings Pointer to Info structure to populate * @return ESP_OK on success, ESP_ERR_* on failure diff --git a/main/Application/Tasks/GUI/Export/ui_events.cpp b/main/Application/Tasks/GUI/Export/ui_events.cpp index c7a7491..296891a 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.cpp +++ b/main/Application/Tasks/GUI/Export/ui_events.cpp @@ -11,18 +11,10 @@ #include "../UI/ui_Settings.h" #include "../../../application.h" #include "../guiTask.h" +#include "../UI/ui_messagebox.h" static const char *TAG = "ui_events"; -/** @brief Callback for the message box timer to close the box after a delay. - * @param p_Timer Timer handle (user data is the message box to close) - */ -static void MessageBox_on_Close(lv_timer_t *p_Timer) -{ - lv_obj_t *Box = (lv_obj_t *)lv_timer_get_user_data(p_Timer); - lv_msgbox_close(Box); -} - void ScreenMainLoaded(lv_event_t *e) { char Buf[128]; @@ -59,45 +51,16 @@ void ButtonMainWiFiClicked(lv_event_t *e) void ScreenSplashLoaded(lv_event_t *e) { - ui_settings_build(ui_Container_Menu); + ui_settings_init(ui_Container_Menu); } -void ButtonMenuSaveClicked(lv_event_t *e) +void ButtonMainSaveClicked(lv_event_t *e) { - lv_obj_t *Box = lv_msgbox_create(NULL); - - SettingsManager_Save(); - - lv_msgbox_add_title(Box, "Settings Saved"); - - lv_timer_t *Timer = lv_timer_create(MessageBox_on_Close, 1000, Box); - lv_timer_set_repeat_count(Timer, 1); + MessageBox_ImageSaveError(GUI_SaveThermalImage()); } -void ButtonMainSaveClicked(lv_event_t *e) +void ButtonMenuSaveClicked(lv_event_t *e) { - lv_obj_t *Box = lv_msgbox_create(NULL); - esp_err_t Error = GUI_SaveThermalImage(); - - if (Error == ESP_OK) { - lv_msgbox_add_title(Box, "Image Saved"); - lv_msgbox_add_text(Box, "Thermal image saved to storage"); - ESP_LOGI(TAG, "Thermal image saved successfully"); - } else if (Error == ESP_ERR_INVALID_STATE) { - lv_msgbox_add_title(Box, "USB Active"); - lv_msgbox_add_text(Box, "Cannot save - USB mode is active!\\nDisable USB first."); - ESP_LOGW(TAG, "Cannot save image - USB mode active"); - } else if (Error == ESP_ERR_NO_MEM) { - lv_msgbox_add_title(Box, "No Frame"); - lv_msgbox_add_text(Box, "No thermal frame available"); - ESP_LOGW(TAG, "No thermal frame available"); - } else { - lv_msgbox_add_title(Box, "Save Failed"); - lv_msgbox_add_text(Box, "Failed to save image"); - ESP_LOGE(TAG, "Failed to save thermal image: %d!", Error); - } - - /* Auto-close message box after 2 seconds */ - lv_timer_t *Timer = lv_timer_create(MessageBox_on_Close, 2000, Box); - lv_timer_set_repeat_count(Timer, 1); -} + SettingsManager_Save(); + MessageBox_Show("Settings Saved"); +} \ No newline at end of file diff --git a/main/Application/Tasks/GUI/Export/ui_events.h b/main/Application/Tasks/GUI/Export/ui_events.h index 3a687e9..386b7ff 100644 --- a/main/Application/Tasks/GUI/Export/ui_events.h +++ b/main/Application/Tasks/GUI/Export/ui_events.h @@ -10,6 +10,11 @@ extern "C" { #endif +/** @brief Callback for the message box timer to close the box after a delay. + * @param p_Timer Timer handle (user data is the message box to close) + */ +void MessageBox_on_Close(lv_timer_t *p_Timer); + void ScreenSplashLoaded(lv_event_t *e); void ScreenMainLoaded(lv_event_t *e); void ButtonMainSaveClicked(lv_event_t *e); diff --git a/main/Application/Tasks/GUI/Private/guiImageSave.cpp b/main/Application/Tasks/GUI/Private/guiImageSave.cpp index 3673d08..c725d75 100644 --- a/main/Application/Tasks/GUI/Private/guiImageSave.cpp +++ b/main/Application/Tasks/GUI/Private/guiImageSave.cpp @@ -78,7 +78,9 @@ void Task_ImageSave(void *p_Param) FILE *PNGFile = fopen(FilePath, "wb"); if (PNGFile == NULL) { ESP_LOGE(TAG, "Failed to open file for writing: %s", FilePath); + esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; } @@ -86,17 +88,21 @@ void Task_ImageSave(void *p_Param) png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { ESP_LOGE(TAG, "Failed to create PNG write struct!"); + fclose(PNGFile); esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; } png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { ESP_LOGE(TAG, "Failed to create PNG info struct!"); + png_destroy_write_struct(&png_ptr, NULL); fclose(PNGFile); esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; } @@ -104,19 +110,23 @@ void Task_ImageSave(void *p_Param) uint8_t *LineBuffer = static_cast(heap_caps_malloc(Frame.Width * 3, MALLOC_CAP_SPIRAM)); if (LineBuffer == NULL) { ESP_LOGE(TAG, "Failed to allocate line buffer!"); + png_destroy_write_struct(&png_ptr, &info_ptr); fclose(PNGFile); esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; } /* Set error handling */ if (setjmp(png_jmpbuf(png_ptr))) { ESP_LOGE(TAG, "PNG encoding error!"); + heap_caps_free(LineBuffer); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(PNGFile); esp_event_post(GUI_EVENTS, GUI_EVENT_THERMAL_IMAGE_SAVE_FAILED, NULL, 0, portMAX_DELAY); + continue; } diff --git a/main/Application/Tasks/GUI/UI/ui_Settings.cpp b/main/Application/Tasks/GUI/UI/ui_Settings.cpp index 75c4712..c2e1499 100644 --- a/main/Application/Tasks/GUI/UI/ui_Settings.cpp +++ b/main/Application/Tasks/GUI/UI/ui_Settings.cpp @@ -1,5 +1,5 @@ /* - * ui_Settings.cpp + * ui_settings.cpp * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de @@ -29,12 +29,9 @@ #include "../Export/ui.h" #include "../Export/screens/ui_Menu.h" -#include "ui_Settings.h" -#include "Private/ui_Settings_Events.h" -#include "../../../Manager/Settings/settingsManager.h" -#include "../../../Manager/Memory/memoryManager.h" -#include "../../../Manager/Network/Server/server.h" -#include "../../../Manager/USB/usbManager.h" +#include "ui_settings.h" +#include "ui_settings_events.h" +#include "managers.h" Slider_Widgets_t brightness_widgets; Slider_Widgets_t emissivity_widgets; @@ -43,8 +40,8 @@ static lv_obj_t *flash_storage_used_label = NULL; static lv_obj_t *flash_storage_free_label = NULL; static lv_obj_t *flash_coredump_used_label = NULL; static lv_obj_t *flash_coredump_total_label = NULL; +static lv_obj_t *root_page; -lv_obj_t *root_page; lv_obj_t *cont; lv_obj_t *section; lv_obj_t *about_Page; @@ -52,13 +49,37 @@ lv_obj_t *wifi_Page; lv_obj_t *display_Page; lv_obj_t *lepton_Page; lv_obj_t *flash_Page; -lv_obj_t *usb_Page; lv_obj_t *settings_Menu; lv_obj_t *emissivity_Dropdown; -lv_obj_t *wifi_status_label; +lv_obj_t *usb_Page; lv_obj_t *usb_mode_switch; +lv_obj_t *ui_settings_wifi_status_label; +lv_obj_t *ui_settings_wifi_connect_btn; + +/** @brief Event handler for menu page changes to control Save button visibility. + * @note Hides Save button when USB or Flash settings are active because + * filesystem is locked during USB mode and Flash operations don't + * require explicit saving. + * @param e Pointer to the event + */ +static void on_Menu_PageChanged(lv_event_t *e) +{ + lv_obj_t *menu_obj = static_cast(lv_event_get_target(e)); + lv_obj_t *cur_page = lv_menu_get_cur_main_page(menu_obj); + + if (cur_page == NULL) { + return; + } + + /* Hide Save button on USB and Flash pages */ + if ((cur_page == usb_Page) || (cur_page == flash_Page)) { + lv_obj_add_flag(ui_Button_Menu_Save, LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_remove_flag(ui_Button_Menu_Save, LV_OBJ_FLAG_HIDDEN); + } +} -static lv_obj_t *create_menu_container(lv_obj_t *parent) +static lv_obj_t *ui_Settings_Create_Menu_Container(lv_obj_t *parent) { lv_obj_t *container = lv_obj_create(parent); lv_obj_clear_flag(container, LV_OBJ_FLAG_CLICKABLE); @@ -75,7 +96,7 @@ static lv_obj_t *create_menu_container(lv_obj_t *parent) return container; } -static lv_obj_t *create_row(lv_obj_t *parent, lv_flex_align_t main_align) +static lv_obj_t *ui_Settings_Create_Row(lv_obj_t *parent, lv_flex_align_t main_align) { lv_obj_t *row = lv_obj_create(parent); lv_obj_clear_flag(row, static_cast(LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_GESTURE_BUBBLE)); @@ -92,7 +113,7 @@ static lv_obj_t *create_row(lv_obj_t *parent, lv_flex_align_t main_align) return row; } -static lv_obj_t *create_compact_slider(lv_obj_t *parent, const char *label_text, +static lv_obj_t *ui_Settings_Create_Compact_Slider(lv_obj_t *parent, const char *label_text, int min_val, int max_val, int init_val, Slider_Widgets_t *widgets) { char Buffer[8]; @@ -101,7 +122,7 @@ static lv_obj_t *create_compact_slider(lv_obj_t *parent, const char *label_text, return NULL; } - lv_obj_t *label_row = create_row(parent, LV_FLEX_ALIGN_START); + lv_obj_t *label_row = ui_Settings_Create_Row(parent, LV_FLEX_ALIGN_START); lv_obj_t *label = lv_label_create(label_row); lv_label_set_text(label, label_text); lv_obj_set_width(label, LV_PCT(50)); @@ -122,7 +143,7 @@ static lv_obj_t *create_compact_slider(lv_obj_t *parent, const char *label_text, lv_obj_clear_flag(value_label, LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_style_margin_left(value_label, 10, 0); - lv_obj_t *slider_row = create_row(parent, LV_FLEX_ALIGN_CENTER); + lv_obj_t *slider_row = ui_Settings_Create_Row(parent, LV_FLEX_ALIGN_CENTER); lv_obj_t *slider = lv_slider_create(slider_row); lv_obj_clear_flag(slider, LV_OBJ_FLAG_GESTURE_BUBBLE); @@ -140,11 +161,11 @@ static lv_obj_t *create_compact_slider(lv_obj_t *parent, const char *label_text, return slider; } -static Menu_Page_Result_t create_menu_page_with_container(lv_obj_t *menu) +static Menu_Page_Result_t ui_Settings_Create_Menu_Page_With_Container(lv_obj_t *menu) { lv_obj_t *page = lv_menu_page_create(menu, NULL); lv_obj_t *section = lv_menu_section_create(page); - lv_obj_t *container = create_menu_container(section); + lv_obj_t *container = ui_Settings_Create_Menu_Container(section); lv_obj_set_scrollbar_mode(menu, LV_SCROLLBAR_MODE_OFF); @@ -168,7 +189,7 @@ static Menu_Page_Result_t create_menu_page_with_container(lv_obj_t *menu) return {container, page}; } -static lv_obj_t *create_text(lv_obj_t *parent, const char *txt) +static lv_obj_t *ui_Settings_Create_Text(lv_obj_t *parent, const char *txt) { lv_obj_t *label = NULL; @@ -214,29 +235,6 @@ static lv_obj_t *create_text(lv_obj_t *parent, const char *txt) return obj; } -/** @brief Event handler for menu page changes to control Save button visibility. - * @note Hides Save button when USB or Flash settings are active because - * filesystem is locked during USB mode and Flash operations don't - * require explicit saving. - * @param e Pointer to the event - */ -static void on_menu_page_changed(lv_event_t *e) -{ - lv_obj_t *menu_obj = static_cast(lv_event_get_target(e)); - lv_obj_t *cur_page = lv_menu_get_cur_main_page(menu_obj); - - if (cur_page == NULL) { - return; - } - - /* Hide Save button on USB and Flash pages */ - if ((cur_page == usb_Page) || (cur_page == flash_Page)) { - lv_obj_add_flag(ui_Button_Menu_Save, LV_OBJ_FLAG_HIDDEN); - } else { - lv_obj_remove_flag(ui_Button_Menu_Save, LV_OBJ_FLAG_HIDDEN); - } -} - /** @brief Creates the About page. * @param p_Menu Pointer to the menu object */ @@ -251,7 +249,7 @@ static lv_obj_t *ui_Settings_Create_About_Page(lv_obj_t *p_parent) lv_obj_t *sub_legal_info_page; char Buffer[64]; - about_result = create_menu_page_with_container(p_parent); + about_result = ui_Settings_Create_Menu_Page_With_Container(p_parent); about_container = about_result.Container; about_page = about_result.Page; @@ -262,20 +260,20 @@ static lv_obj_t *ui_Settings_Create_About_Page(lv_obj_t *p_parent) lv_obj_set_style_bg_color(section, lv_color_hex(0x1E1E1E), 0); lv_obj_set_style_bg_opa(section, 255, 0); lv_obj_set_style_pad_all(section, 8, 0); - create_text(section, "PyroVision Firmware"); + ui_Settings_Create_Text(section, "PyroVision Firmware"); memset(Buffer, 0, sizeof(Buffer)); snprintf(Buffer, sizeof(Buffer), "Version %u.%u.%u", 1, 0, 0); - create_text(section, Buffer); + ui_Settings_Create_Text(section, Buffer); memset(Buffer, 0, sizeof(Buffer)); snprintf(Buffer, sizeof(Buffer), "Platform: %s", CONFIG_IDF_TARGET); - create_text(section, Buffer); + ui_Settings_Create_Text(section, Buffer); memset(Buffer, 0, sizeof(Buffer)); snprintf(Buffer, sizeof(Buffer), "LVGL Version: %d.%d.%d\n", LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, LVGL_VERSION_PATCH); - create_text(section, Buffer); + ui_Settings_Create_Text(section, Buffer); sub_legal_info_page = lv_menu_page_create(p_parent, NULL); section = lv_menu_section_create(sub_legal_info_page); @@ -295,9 +293,9 @@ static lv_obj_t *ui_Settings_Create_About_Page(lv_obj_t *p_parent) lv_obj_set_style_text_align(license_label, LV_TEXT_ALIGN_LEFT, 0); lv_label_set_long_mode(license_label, LV_LABEL_LONG_WRAP); - cont = create_text(about_container, "Software information"); + cont = ui_Settings_Create_Text(about_container, "Software information"); lv_menu_set_load_page_event(p_parent, cont, sub_software_info_page); - cont = create_text(about_container, "Legal information"); + cont = ui_Settings_Create_Text(about_container, "Legal information"); lv_menu_set_load_page_event(p_parent, cont, sub_legal_info_page); return about_page; @@ -308,14 +306,14 @@ static lv_obj_t *ui_Settings_Create_About_Page(lv_obj_t *p_parent) */ static lv_obj_t *ui_Settings_Create_WiFi_Page(lv_obj_t *p_Menu) { - Menu_Page_Result_t WiFiResult = create_menu_page_with_container(p_Menu); + Menu_Page_Result_t WiFiResult = ui_Settings_Create_Menu_Page_With_Container(p_Menu); lv_obj_t *WiFiContainer = WiFiResult.Container; lv_obj_t *WiFiPage = WiFiResult.Page; App_Settings_WiFi_t WiFiSettings; SettingsManager_GetWiFi(&WiFiSettings); - lv_obj_t *wifi_row1 = create_row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *wifi_row1 = ui_Settings_Create_Row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); lv_obj_t *wifi_label = lv_label_create(wifi_row1); lv_label_set_text(wifi_label, "Autoconnect"); lv_obj_set_style_text_color(wifi_label, lv_color_white(), 0); @@ -331,26 +329,26 @@ static lv_obj_t *ui_Settings_Create_WiFi_Page(lv_obj_t *p_Menu) lv_obj_remove_state(wifi_switch, LV_STATE_CHECKED); } - lv_obj_t *wifi_row2 = create_row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *wifi_row2 = ui_Settings_Create_Row(WiFiContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); lv_obj_t *ssid_label = lv_label_create(wifi_row2); lv_label_set_text(ssid_label, "Status"); lv_obj_set_style_text_color(ssid_label, lv_color_white(), 0); - wifi_status_label = lv_label_create(wifi_row2); - lv_label_set_text(wifi_status_label, "Offline"); - lv_obj_set_style_text_color(wifi_status_label, lv_color_hex(0xFF9500), 0); + ui_settings_wifi_status_label = lv_label_create(wifi_row2); + lv_label_set_text(ui_settings_wifi_status_label, "Offline"); + lv_obj_set_style_text_color(ui_settings_wifi_status_label, lv_color_hex(0xFF9500), 0); /* WiFi Connect Button */ - lv_obj_t *wifi_btn_row = create_row(WiFiContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_t *wifi_btn_row = ui_Settings_Create_Row(WiFiContainer, LV_FLEX_ALIGN_CENTER); lv_obj_set_height(wifi_btn_row, LV_SIZE_CONTENT); lv_obj_set_style_pad_top(wifi_btn_row, 12, 0); lv_obj_set_style_pad_bottom(wifi_btn_row, 8, 0); - lv_obj_t *wifi_connect_btn = lv_btn_create(wifi_btn_row); - lv_obj_set_size(wifi_connect_btn, 140, 36); - lv_obj_set_style_bg_color(wifi_connect_btn, lv_color_hex(0xFF9500), LV_STATE_DEFAULT); - lv_obj_set_style_radius(wifi_connect_btn, 6, 0); - lv_obj_set_style_shadow_width(wifi_connect_btn, 0, 0); - lv_obj_add_event_cb(wifi_connect_btn, on_WiFi_Connect_Callback, LV_EVENT_CLICKED, NULL); - lv_obj_t *wifi_btn_label = lv_label_create(wifi_connect_btn); + ui_settings_wifi_connect_btn = lv_btn_create(wifi_btn_row); + lv_obj_set_size(ui_settings_wifi_connect_btn, 140, 36); + lv_obj_set_style_bg_color(ui_settings_wifi_connect_btn, lv_color_hex(0xFF9500), LV_STATE_DEFAULT); + lv_obj_set_style_radius(ui_settings_wifi_connect_btn, 6, 0); + lv_obj_set_style_shadow_width(ui_settings_wifi_connect_btn, 0, 0); + lv_obj_add_event_cb(ui_settings_wifi_connect_btn, on_WiFi_Connect_Callback, LV_EVENT_CLICKED, NULL); + lv_obj_t *wifi_btn_label = lv_label_create(ui_settings_wifi_connect_btn); lv_label_set_text(wifi_btn_label, "Connect WiFi"); lv_obj_set_style_text_color(wifi_btn_label, lv_color_white(), 0); lv_obj_center(wifi_btn_label); @@ -363,14 +361,14 @@ static lv_obj_t *ui_Settings_Create_WiFi_Page(lv_obj_t *p_Menu) */ static lv_obj_t *ui_Settings_Create_Display_Page(lv_obj_t *p_Menu) { - Menu_Page_Result_t DisplayResult = create_menu_page_with_container(p_Menu); + Menu_Page_Result_t DisplayResult = ui_Settings_Create_Menu_Page_With_Container(p_Menu); lv_obj_t *DisplayContainer = DisplayResult.Container; lv_obj_t *DisplayPage = DisplayResult.Page; App_Settings_Display_t DisplaySettings; SettingsManager_GetDisplay(&DisplaySettings); - lv_obj_t *brightness_slider = create_compact_slider(DisplayContainer, "Brightness", 0, 100, DisplaySettings.Brightness, + lv_obj_t *brightness_slider = ui_Settings_Create_Compact_Slider(DisplayContainer, "Brightness", 0, 100, DisplaySettings.Brightness, &brightness_widgets); lv_obj_add_event_cb(brightness_slider, on_Display_Brightness_Slider_Callback, LV_EVENT_VALUE_CHANGED, NULL); @@ -384,7 +382,7 @@ static lv_obj_t *ui_Settings_Create_Display_Page(lv_obj_t *p_Menu) static lv_obj_t *ui_Settings_Create_Lepton_Page(lv_obj_t *p_Menu) { std::string Buffer; - Menu_Page_Result_t LeptonResult = create_menu_page_with_container(p_Menu); + Menu_Page_Result_t LeptonResult = ui_Settings_Create_Menu_Page_With_Container(p_Menu); lv_obj_t *LeptonContainer = LeptonResult.Container; lv_obj_t *LeptonPage = LeptonResult.Page; App_Settings_Lepton_t LeptonSettings; @@ -395,13 +393,13 @@ static lv_obj_t *ui_Settings_Create_Lepton_Page(lv_obj_t *p_Menu) Buffer += LeptonSettings.EmissivityPresets[i].Description + std::string("\n"); } - lv_obj_t *emissivity_slider = create_compact_slider(LeptonContainer, "Emissivity", 0, 100, + lv_obj_t *emissivity_slider = ui_Settings_Create_Compact_Slider(LeptonContainer, "Emissivity", 0, 100, LeptonSettings.CurrentEmissivity, &emissivity_widgets); lv_obj_add_event_cb(emissivity_slider, on_Lepton_Emissivity_Slider_Callback, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_add_event_cb(emissivity_slider, on_Lepton_Emissivity_Slider_Callback, LV_EVENT_RELEASED, NULL); - lv_obj_t *dropdown_row = create_row(LeptonContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_t *dropdown_row = ui_Settings_Create_Row(LeptonContainer, LV_FLEX_ALIGN_CENTER); emissivity_Dropdown = lv_dropdown_create(dropdown_row); lv_obj_set_width(emissivity_Dropdown, LV_PCT(95)); lv_obj_set_style_bg_color(emissivity_Dropdown, lv_color_hex(0x3A3A3A), LV_PART_MAIN); @@ -425,7 +423,7 @@ static lv_obj_t *ui_Settings_Create_Lepton_Page(lv_obj_t *p_Menu) */ static lv_obj_t *ui_Settings_Create_USB_Page(lv_obj_t *p_Menu) { - Menu_Page_Result_t USBResult = create_menu_page_with_container(p_Menu); + Menu_Page_Result_t USBResult = ui_Settings_Create_Menu_Page_With_Container(p_Menu); lv_obj_t *USBContainer = USBResult.Container; lv_obj_t *USBPage = USBResult.Page; @@ -443,12 +441,12 @@ static lv_obj_t *ui_Settings_Create_USB_Page(lv_obj_t *p_Menu) lv_obj_set_style_pad_bottom(usb_desc_label, 8, 0); lv_obj_t *usb_warning_label = lv_label_create(USBContainer); - lv_label_set_text(usb_warning_label, "⚠️ App cannot save while USB is active!"); + lv_label_set_text(usb_warning_label, " App cannot save while USB is active!"); lv_obj_set_style_text_color(usb_warning_label, lv_color_hex(0xFF9500), 0); lv_obj_set_style_text_font(usb_warning_label, &lv_font_montserrat_10, 0); lv_obj_set_style_pad_bottom(usb_warning_label, 12, 0); - lv_obj_t *usb_switch_row = create_row(USBContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *usb_switch_row = ui_Settings_Create_Row(USBContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); lv_obj_set_style_pad_top(usb_switch_row, 4, 0); lv_obj_set_style_pad_bottom(usb_switch_row, 4, 0); @@ -471,7 +469,7 @@ static lv_obj_t *ui_Settings_Create_USB_Page(lv_obj_t *p_Menu) */ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) { - Menu_Page_Result_t FlashResult = create_menu_page_with_container(p_Menu); + Menu_Page_Result_t FlashResult = ui_Settings_Create_Menu_Page_With_Container(p_Menu); lv_obj_t *FlashContainer = FlashResult.Container; lv_obj_t *FlashPage = FlashResult.Page; @@ -488,7 +486,7 @@ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) lv_obj_set_style_text_font(nvs_desc_label, &lv_font_montserrat_12, 0); lv_obj_set_style_pad_bottom(nvs_desc_label, 8, 0); - lv_obj_t *nvs_btn_row = create_row(FlashContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_t *nvs_btn_row = ui_Settings_Create_Row(FlashContainer, LV_FLEX_ALIGN_CENTER); lv_obj_set_height(nvs_btn_row, LV_SIZE_CONTENT); lv_obj_set_style_pad_top(nvs_btn_row, 4, 0); lv_obj_set_style_pad_bottom(nvs_btn_row, 4, 0); @@ -519,7 +517,7 @@ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) lv_obj_set_style_pad_top(storage_section_label, 0, 0); lv_obj_set_style_pad_bottom(storage_section_label, 8, 0); - lv_obj_t *storage_info_row = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *storage_info_row = ui_Settings_Create_Row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); lv_obj_t *storage_used_label = lv_label_create(storage_info_row); lv_label_set_text(storage_used_label, "Used:"); lv_obj_set_style_text_color(storage_used_label, lv_color_white(), 0); @@ -527,7 +525,7 @@ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) lv_label_set_text(flash_storage_used_label, "-- KB"); lv_obj_set_style_text_color(flash_storage_used_label, lv_color_hex(0xB998FF), 0); - lv_obj_t *storage_free_row = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *storage_free_row = ui_Settings_Create_Row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); lv_obj_t *storage_free_label = lv_label_create(storage_free_row); lv_label_set_text(storage_free_label, "Free:"); lv_obj_set_style_text_color(storage_free_label, lv_color_white(), 0); @@ -535,7 +533,7 @@ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) lv_label_set_text(flash_storage_free_label, "-- KB"); lv_obj_set_style_text_color(flash_storage_free_label, lv_color_hex(0xB998FF), 0); - lv_obj_t *storage_btn_row = create_row(FlashContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_t *storage_btn_row = ui_Settings_Create_Row(FlashContainer, LV_FLEX_ALIGN_CENTER); lv_obj_set_height(storage_btn_row, LV_SIZE_CONTENT); lv_obj_set_style_pad_top(storage_btn_row, 8, 0); lv_obj_set_style_pad_bottom(storage_btn_row, 8, 0); @@ -566,7 +564,7 @@ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) lv_obj_set_style_pad_top(coredump_section_label, 0, 0); lv_obj_set_style_pad_bottom(coredump_section_label, 8, 0); - lv_obj_t *coredump_info_row = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *coredump_info_row = ui_Settings_Create_Row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); lv_obj_t *coredump_used_label = lv_label_create(coredump_info_row); lv_label_set_text(coredump_used_label, "Used:"); lv_obj_set_style_text_color(coredump_used_label, lv_color_white(), 0); @@ -574,7 +572,7 @@ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) lv_label_set_text(flash_coredump_used_label, "-- KB"); lv_obj_set_style_text_color(flash_coredump_used_label, lv_color_hex(0xB998FF), 0); - lv_obj_t *coredump_total_row = create_row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_t *coredump_total_row = ui_Settings_Create_Row(FlashContainer, LV_FLEX_ALIGN_SPACE_BETWEEN); lv_obj_t *coredump_total_label = lv_label_create(coredump_total_row); lv_label_set_text(coredump_total_label, "Total:"); lv_obj_set_style_text_color(coredump_total_label, lv_color_white(), 0); @@ -582,7 +580,7 @@ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) lv_label_set_text(flash_coredump_total_label, "-- KB"); lv_obj_set_style_text_color(flash_coredump_total_label, lv_color_hex(0xB998FF), 0); - lv_obj_t *coredump_btn_row = create_row(FlashContainer, LV_FLEX_ALIGN_CENTER); + lv_obj_t *coredump_btn_row = ui_Settings_Create_Row(FlashContainer, LV_FLEX_ALIGN_CENTER); lv_obj_set_height(coredump_btn_row, LV_SIZE_CONTENT); lv_obj_set_style_pad_top(coredump_btn_row, 8, 0); lv_obj_set_style_pad_bottom(coredump_btn_row, 16, 0); @@ -600,7 +598,7 @@ static lv_obj_t *ui_Settings_Create_Flash_Page(lv_obj_t *p_Menu) return FlashPage; } -void ui_settings_build(lv_obj_t *p_Parent) +void ui_settings_init(lv_obj_t *p_Parent) { settings_Menu = lv_menu_create(p_Parent); @@ -626,16 +624,16 @@ void ui_settings_build(lv_obj_t *p_Parent) lv_obj_set_style_bg_opa(section, 0, 0); lv_obj_set_style_pad_all(section, 8, 0); - cont = create_text(section, "WiFi"); + cont = ui_Settings_Create_Text(section, "WiFi"); lv_menu_set_load_page_event(settings_Menu, cont, wifi_Page); - cont = create_text(section, "Display"); + cont = ui_Settings_Create_Text(section, "Display"); lv_menu_set_load_page_event(settings_Menu, cont, display_Page); - cont = create_text(section, "Lepton"); + cont = ui_Settings_Create_Text(section, "Lepton"); lv_menu_set_load_page_event(settings_Menu, cont, lepton_Page); - cont = create_text(section, "Flash"); + cont = ui_Settings_Create_Text(section, "Flash"); lv_menu_set_load_page_event(settings_Menu, cont, flash_Page); lv_obj_add_event_cb(cont, [](lv_event_t *e) { if (lv_event_get_code(e) == LV_EVENT_CLICKED) { @@ -643,16 +641,16 @@ void ui_settings_build(lv_obj_t *p_Parent) } }, LV_EVENT_CLICKED, NULL); - cont = create_text(section, "USB"); + cont = ui_Settings_Create_Text(section, "USB"); lv_menu_set_load_page_event(settings_Menu, cont, usb_Page); - cont = create_text(section, "About"); + cont = ui_Settings_Create_Text(section, "About"); lv_menu_set_load_page_event(settings_Menu, cont, about_Page); lv_menu_set_sidebar_page(settings_Menu, root_page); /* Register event handler for menu page changes to control Save button visibility */ - lv_obj_add_event_cb(settings_Menu, on_menu_page_changed, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb(settings_Menu, on_Menu_PageChanged, LV_EVENT_VALUE_CHANGED, NULL); /* Initially check current page (root page doesn't need Save button hidden) */ lv_obj_remove_flag(ui_Button_Menu_Save, LV_OBJ_FLAG_HIDDEN); @@ -676,10 +674,11 @@ void ui_settings_deinit(lv_obj_t *p_Parent) void ui_settings_update_flash_usage(void) { + esp_err_t Error; MemoryManager_Usage_t Usage; if ((flash_storage_used_label != NULL) && (flash_storage_free_label != NULL)) { - esp_err_t Error = MemoryManager_GetStorageUsage(&Usage); + Error = MemoryManager_GetStorageUsage(&Usage); if (Error == ESP_OK) { if (Usage.TotalBytes >= (1024 * 1024)) { lv_label_set_text_fmt(flash_storage_used_label, "%.2f MB", Usage.UsedBytes / (1024.0f * 1024.0f)); @@ -695,7 +694,7 @@ void ui_settings_update_flash_usage(void) } if ((flash_coredump_used_label != NULL) && (flash_coredump_total_label != NULL)) { - esp_err_t Error = MemoryManager_GetCoredumpUsage(&Usage); + Error = MemoryManager_GetCoredumpUsage(&Usage); if (Error == ESP_OK) { lv_label_set_text_fmt(flash_coredump_used_label, "%u KB", Usage.UsedBytes / 1024); lv_label_set_text_fmt(flash_coredump_total_label, "%u KB", Usage.TotalBytes / 1024); diff --git a/main/Application/Tasks/GUI/UI/ui_Settings.h b/main/Application/Tasks/GUI/UI/ui_Settings.h index 299ef45..d78403d 100644 --- a/main/Application/Tasks/GUI/UI/ui_Settings.h +++ b/main/Application/Tasks/GUI/UI/ui_Settings.h @@ -1,5 +1,5 @@ /* - * ui_Settings.h + * ui_settings.h * * Copyright (C) Daniel Kampert, 2026 * Website: www.kampis-elektroecke.de @@ -28,12 +28,13 @@ #include -extern lv_obj_t *wifi_status_label; +extern lv_obj_t *ui_settings_wifi_status_label; +extern lv_obj_t *ui_settings_wifi_connect_btn; -/** @brief Builds the settings UI. +/** @brief Initializes the settings UI. * @param p_Parent Pointer to the parent object where the settings UI will be attached */ -void ui_settings_build(lv_obj_t *p_Parent); +void ui_settings_init(lv_obj_t *p_Parent); /** @brief Updates flash partition usage information in the Flash settings page. * Call this when the Flash settings page becomes visible to show diff --git a/main/Application/Tasks/GUI/UI/ui_messagebox.cpp b/main/Application/Tasks/GUI/UI/ui_messagebox.cpp new file mode 100644 index 0000000..73c7ef1 --- /dev/null +++ b/main/Application/Tasks/GUI/UI/ui_messagebox.cpp @@ -0,0 +1,78 @@ +/* + * ui_messagenbox.cpp + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: GUI task image save implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#include +#include + +#include "ui_messagebox.h" + +static const char *TAG = "ui_messagenbox"; + +static void MessageBox_on_Close(lv_timer_t *p_Timer) +{ + lv_obj_t *Box = (lv_obj_t *)lv_timer_get_user_data(p_Timer); + + lv_msgbox_close(Box); +} + +void MessageBox_Show(const char *p_Title, uint32_t AutoCloseDelay) +{ + lv_obj_t *Box = lv_msgbox_create(NULL); + + lv_msgbox_add_title(Box, p_Title); + + /* Auto-close message box after specified delay */ + lv_timer_t *Timer = lv_timer_create(MessageBox_on_Close, AutoCloseDelay * 1000, Box); + lv_timer_set_repeat_count(Timer, 1); +} + +void MessageBox_ImageSaveError(esp_err_t Error) +{ + lv_obj_t *Box = lv_msgbox_create(NULL); + + if (Error == ESP_OK) { + lv_msgbox_add_title(Box, "Image Saved"); + lv_msgbox_add_text(Box, "Thermal image saved to storage"); + + ESP_LOGI(TAG, "Thermal image saved successfully"); + } else if (Error == ESP_ERR_INVALID_STATE) { + lv_msgbox_add_title(Box, "USB Active"); + lv_msgbox_add_text(Box, "Cannot save - USB mode is active!\\nDisable USB first."); + + ESP_LOGW(TAG, "Cannot save image - USB mode active"); + } else if (Error == ESP_ERR_NO_MEM) { + lv_msgbox_add_title(Box, "No Frame"); + lv_msgbox_add_text(Box, "No thermal frame available"); + + ESP_LOGW(TAG, "No thermal frame available"); + } else { + lv_msgbox_add_title(Box, "Save Failed"); + lv_msgbox_add_text(Box, "Failed to save image"); + + ESP_LOGE(TAG, "Failed to save thermal image: %d!", Error); + } + + /* Auto-close message box after 2 seconds */ + lv_timer_t *Timer = lv_timer_create(MessageBox_on_Close, 2000, Box); + lv_timer_set_repeat_count(Timer, 1); +} diff --git a/main/Application/Tasks/GUI/UI/ui_messagebox.h b/main/Application/Tasks/GUI/UI/ui_messagebox.h new file mode 100644 index 0000000..8e6e7ed --- /dev/null +++ b/main/Application/Tasks/GUI/UI/ui_messagebox.h @@ -0,0 +1,42 @@ +/* + * ui_messagebox.h + * + * Copyright (C) Daniel Kampert, 2026 + * Website: www.kampis-elektroecke.de + * File info: Settings UI implementation. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Errors and commissions should be reported to DanielKampert@kampis-elektroecke.de + */ + +#ifndef UI_MESSAGEBOX_H_ +#define UI_MESSAGEBOX_H_ + +#include + +#include + +/** @brief Show a message box with the specified title and auto-close it after a delay. + * @param p_Title Title to show in the message box + * @param AutoCloseDelay Time in seconds after which the message box should auto-close (default: 1 second) + */ +void MessageBox_Show(const char *p_Title, uint32_t AutoCloseDelay = 1); + +/** @brief Show a message box indicating the result of a thermal image save operation. + * @param Error ESP_OK if the image was saved successfully, or an error code if it failed + */ +void MessageBox_ImageSaveError(esp_err_t Error); + +#endif /* UI_MESSAGEBOX_H_ */ \ No newline at end of file diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp b/main/Application/Tasks/GUI/UI/ui_settings_events.cpp similarity index 99% rename from main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp rename to main/Application/Tasks/GUI/UI/ui_settings_events.cpp index 17aac78..b2e2f91 100644 --- a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.cpp +++ b/main/Application/Tasks/GUI/UI/ui_settings_events.cpp @@ -25,11 +25,11 @@ #include "managers.h" -#include "ui_Settings_Events.h" +#include "ui_settings_events.h" static USB_Manager_Config_t USB_Config; -static const char *TAG = "ui_Settings_Events"; +static const char *TAG = "ui_settings_events"; void on_Lepton_Emissivity_Slider_Callback(lv_event_t *e) { diff --git a/main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h b/main/Application/Tasks/GUI/UI/ui_settings_events.h similarity index 100% rename from main/Application/Tasks/GUI/UI/Private/ui_Settings_Events.h rename to main/Application/Tasks/GUI/UI/ui_settings_events.h diff --git a/main/Application/Tasks/GUI/guiTask.cpp b/main/Application/Tasks/GUI/guiTask.cpp index f5409b8..bf541cf 100644 --- a/main/Application/Tasks/GUI/guiTask.cpp +++ b/main/Application/Tasks/GUI/guiTask.cpp @@ -44,6 +44,8 @@ #include "Application/Manager/Network/Server/server.h" #include "Private/guiHelper.h" #include "Private/guiImageSave.h" +#include "UI/ui_messagebox.h" +#include "UI/ui_settings.h" #include "lepton.h" @@ -68,6 +70,7 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int ESP_LOGI(TAG, "Thermal image saved successfully"); /* Show success message box */ + // TODO: Move to Messagebox module lv_obj_t *msgbox = lv_msgbox_create(NULL); lv_msgbox_add_title(msgbox, "Image Saved"); lv_msgbox_add_text(msgbox, "Thermal image saved successfully!"); @@ -79,6 +82,7 @@ static void on_GUI_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, int ESP_LOGE(TAG, "Thermal image save failed"); /* Show error message box */ + // TODO: Move to Messagebox module lv_obj_t *msgbox = lv_msgbox_create(NULL); lv_msgbox_add_title(msgbox, "Save Failed"); lv_msgbox_add_text(msgbox, "Failed to save thermal image!\\nCheck storage or USB mode."); @@ -313,7 +317,7 @@ static void on_Lepton_Event_Handler(void *p_HandlerArgs, esp_event_base_t Base, static void GUI_Update_Info(void) { uint8_t MAC[6]; - char Buffer[19]; + char Buffer[32]; esp_efuse_mac_get_default(MAC); snprintf(Buffer, sizeof(Buffer), "%02X:%02X:%02X:%02X:%02X:%02X", MAC[0], MAC[1], MAC[2], MAC[3], MAC[4], MAC[5]); @@ -447,7 +451,7 @@ static void GUI_Update_ROI(App_Settings_ROI_t ROI) static void UI_Canvas_AddTempGradient(void) { /* Generate gradient pixel by pixel */ - uint16_t *buffer = reinterpret_cast(_GUI_Task_State.GradientCanvasBuffer); + uint16_t *Buffer = reinterpret_cast(_GUI_Task_State.GradientCanvasBuffer); for (uint32_t y = 0; y < _GUI_Task_State.GradientImageDescriptor.header.h; y++) { uint32_t index; @@ -470,7 +474,7 @@ static void UI_Canvas_AddTempGradient(void) /* Fill entire row with same color */ for (uint32_t x = 0; x < _GUI_Task_State.GradientImageDescriptor.header.w; x++) { - buffer[y * _GUI_Task_State.GradientImageDescriptor.header.w + x] = (r5 << 11) | (g6 << 5) | b5; + Buffer[y * _GUI_Task_State.GradientImageDescriptor.header.w + x] = (r5 << 11) | (g6 << 5) | b5; } } } @@ -495,10 +499,11 @@ static void Touch_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data } if ((esp_lcd_touch_read_data(Touch) == ESP_OK) && - (esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])) == ESP_OK) && (Count > 0)) { + (esp_lcd_touch_get_data(Touch, Data, &Count, sizeof(Data) / sizeof(Data[0])) == ESP_OK) && + (Count > 0) + ) { p_Data->point.x = CONFIG_GUI_WIDTH - Data[0].x; p_Data->point.y = Data[0].y; - p_Data->state = LV_INDEV_STATE_PRESSED; ESP_LOGD(TAG, "Raw: (%d, %d)", Data[0].x, Data[0].y); @@ -512,10 +517,10 @@ static void Touch_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data } if (_GUI_Task_State.TouchDebugLabel != NULL) { - char buf[64]; + char Buffer[64]; - snprintf(buf, sizeof(buf), "Raw: %u,%u\nMap: %li,%li", Data[0].x, Data[0].y, p_Data->point.x, p_Data->point.y); - lv_label_set_text(_GUI_Task_State.TouchDebugLabel, buf); + snprintf(Buffer, sizeof(Buffer), "Raw: %u,%u\nMap: %li,%li", Data[0].x, Data[0].y, p_Data->point.x, p_Data->point.y); + lv_label_set_text(_GUI_Task_State.TouchDebugLabel, Buffer); lv_obj_clear_flag(_GUI_Task_State.TouchDebugLabel, LV_OBJ_FLAG_HIDDEN); } #endif @@ -540,6 +545,7 @@ static void Touch_LVGL_ReadCallback(lv_indev_t *p_Indev, lv_indev_data_t *p_Data */ void Task_GUI(void *p_Parameters) { + uint32_t Timeout; App_Context_t *App_Context; App_Settings_Lepton_t LeptonSettings; @@ -553,6 +559,7 @@ void Task_GUI(void *p_Parameters) /* Initialization process: */ /* - Loading the settings */ /* - Waiting for the Lepton */ + Timeout = 0; do { EventBits_t EventBits; @@ -570,7 +577,11 @@ void Task_GUI(void *p_Parameters) xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_CAMERA_ERROR); } - // TODO: Add timeout + if(Timeout >= 30000) { + esp_event_post(GUI_EVENTS, GUI_EVENT_INIT_ERROR, NULL, 0, portMAX_DELAY); + + break; + } lv_timer_handler(); vTaskDelay(100 / portTICK_PERIOD_MS); @@ -601,8 +612,8 @@ void Task_GUI(void *p_Parameters) /* Check for new thermal frame */ if (xQueueReceive(App_Context->Lepton_FrameEventQueue, &LeptonFrame, 0) == pdTRUE) { uint8_t *Dst; - uint32_t Image_Width; - uint32_t Image_Height; + uint32_t ImageWidth; + uint32_t ImageHeight; char Buffer[16]; /* Variables for Illuminance values for the scene label. @@ -637,25 +648,25 @@ void Task_GUI(void *p_Parameters) /* Scale from source (160x120) to destination (240x180) using bilinear interpolation */ Dst = _GUI_Task_State.ThermalCanvasBuffer; - Image_Width = lv_obj_get_width(ui_Image_Thermal); - Image_Height = lv_obj_get_height(ui_Image_Thermal); + ImageWidth = lv_obj_get_width(ui_Image_Thermal); + ImageHeight = lv_obj_get_height(ui_Image_Thermal); /* Skip if image widget not properly initialized yet */ - if ((Image_Width == 0) || (Image_Height == 0)) { - ESP_LOGW(TAG, "Image widget not ready yet (size: %ux%u), skipping frame", Image_Width, Image_Height); + if ((ImageWidth == 0) || (ImageHeight == 0)) { + ESP_LOGW(TAG, "Image widget not ready yet (size: %ux%u), skipping frame", ImageWidth, ImageHeight); continue; } - for (uint32_t y = 0; y < Image_Height; y++) { - uint32_t src_y_fixed = y * ((LeptonFrame.Height - 1) << 16) / Image_Height; + for (uint32_t y = 0; y < ImageHeight; y++) { + uint32_t src_y_fixed = y * ((LeptonFrame.Height - 1) << 16) / ImageHeight; uint32_t y0 = src_y_fixed >> 16; uint32_t y1 = ((y0 + 1) < LeptonFrame.Height) ? (y0 + 1) : y0; uint32_t y_frac = (src_y_fixed >> 8) & 0xFF; /* 8-bit fractional part */ uint32_t y_inv = 256 - y_frac; - for (uint32_t x = 0; x < Image_Width; x++) { - uint32_t src_x_fixed = x * ((LeptonFrame.Width - 1) << 16) / Image_Width; + for (uint32_t x = 0; x < ImageWidth; x++) { + uint32_t src_x_fixed = x * ((LeptonFrame.Width - 1) << 16) / ImageWidth; uint32_t x0 = src_x_fixed >> 16; uint32_t x1 = ((x0 + 1) < LeptonFrame.Width) ? (x0 + 1) : x0; uint32_t x_frac = (src_x_fixed >> 8) & 0xFF; /* 8-bit fractional part */ @@ -694,7 +705,7 @@ void Task_GUI(void *p_Parameters) * - x_rot = Image_Width - 1 - x (X axis is inverted due to rotation) * - y is used directly (Y axis matches label position directly) */ - uint32_t x_rot = Image_Width - 1 - x; + uint32_t x_rot = ImageWidth - 1 - x; /* Max Label */ if ((x_rot >= SceneLabel_x0[0]) && @@ -723,7 +734,7 @@ void Task_GUI(void *p_Parameters) SceneLabelCount[2]++; } - uint32_t dst_idx = (y * Image_Width) + x; + uint32_t dst_idx = (y * ImageWidth) + x; /* Convert to RGB565 - LVGL handles swapping with RGB565_SWAPPED */ uint16_t rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); @@ -768,7 +779,7 @@ void Task_GUI(void *p_Parameters) /* Trigger LVGL to redraw the image */ lv_obj_invalidate(ui_Image_Thermal); ESP_LOGD(TAG, "Updated thermal image display (src: %ux%u -> dst: %ux%u)", LeptonFrame.Width, LeptonFrame.Height, - Image_Width, Image_Height); + ImageWidth, ImageHeight); /* Save frame if requested */ if (_GUI_Task_State.SaveNextFrameRequested) { @@ -777,8 +788,8 @@ void Task_GUI(void *p_Parameters) /* Prepare frame data for save task (using scaled RGB565 buffer) */ App_Lepton_FrameReady_t SaveFrame; SaveFrame.Buffer = _GUI_Task_State.ThermalCanvasBuffer; /* Use scaled display buffer */ - SaveFrame.Width = Image_Width; - SaveFrame.Height = Image_Height; + SaveFrame.Width = ImageWidth; + SaveFrame.Height = ImageHeight; SaveFrame.Channels = 2; /* RGB565 = 2 bytes per pixel */ SaveFrame.Min = LeptonFrame.Min; SaveFrame.Max = LeptonFrame.Max; @@ -797,7 +808,7 @@ void Task_GUI(void *p_Parameters) /* Convert scaled RGB565 buffer to RGB888 for network transmission */ uint8_t *rgb888_dst = _GUI_Task_State.NetworkRGBBuffer; - for (uint32_t i = 0; i < (Image_Width * Image_Height); i++) { + for (uint32_t i = 0; i < (ImageWidth * ImageHeight); i++) { /* Read RGB565 value (little endian) */ uint16_t rgb565 = Dst[(i * 2) + 0] | (Dst[(i * 2) + 1] << 8); @@ -813,8 +824,8 @@ void Task_GUI(void *p_Parameters) } _GUI_Task_State.NetworkFrame.Buffer = _GUI_Task_State.NetworkRGBBuffer; - _GUI_Task_State.NetworkFrame.Width = Image_Width; - _GUI_Task_State.NetworkFrame.Height = Image_Height; + _GUI_Task_State.NetworkFrame.Width = ImageWidth; + _GUI_Task_State.NetworkFrame.Height = ImageHeight; _GUI_Task_State.NetworkFrame.Timestamp = esp_timer_get_time() / 1000; xSemaphoreGive(_GUI_Task_State.NetworkFrame.Mutex); @@ -863,25 +874,31 @@ void Task_GUI(void *p_Parameters) xEventGroupClearBits(_GUI_Task_State.EventGroup, BATTERY_CHARGING_STATUS_READY); } else if (EventBits & WIFI_CONNECTION_STATE_CHANGED) { if (_GUI_Task_State.WiFiConnected) { - char Buffer[16]; + char Buffer[32]; - snprintf(Buffer, sizeof(Buffer), "%lu.%lu.%lu.%lu", + memset(Buffer, 0, sizeof(Buffer)); + snprintf(Buffer, sizeof(Buffer), "IP: %lu.%lu.%lu.%lu", (_GUI_Task_State.IP_Info.IP >> 0) & 0xFF, (_GUI_Task_State.IP_Info.IP >> 8) & 0xFF, (_GUI_Task_State.IP_Info.IP >> 16) & 0xFF, (_GUI_Task_State.IP_Info.IP >> 24) & 0xFF); - lv_label_set_text(ui_Label_Info_IP, Buffer); + /* Skip "IP: " prefix for label */ + lv_label_set_text(ui_Label_Info_IP, &Buffer[4]); + lv_label_set_text(ui_settings_wifi_status_label, &Buffer[4]); lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0x00FF00), LV_PART_MAIN); - // TODO: Disable WiFi buttons in the menu - //lv_obj_remove_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); + MessageBox_Show(Buffer); + + /* Disable WiFi buttons in the settings menu */ + lv_obj_remove_flag(ui_settings_wifi_connect_btn, LV_OBJ_FLAG_CLICKABLE); } else { lv_label_set_text(ui_Label_Info_IP, "Not connected"); + lv_label_set_text(ui_settings_wifi_status_label, "Not connected"); lv_obj_set_style_text_color(ui_Image_Main_WiFi, lv_color_hex(0xFF0000), LV_PART_MAIN); - // TODO: Disable WiFi buttons in the menu - //lv_obj_add_flag(ui_Button_Main_WiFi, LV_OBJ_FLAG_CLICKABLE); + /* Disable WiFi buttons in the settings menu */ + lv_obj_add_flag(ui_settings_wifi_connect_btn, LV_OBJ_FLAG_CLICKABLE); } xEventGroupClearBits(_GUI_Task_State.EventGroup, WIFI_CONNECTION_STATE_CHANGED); @@ -935,17 +952,18 @@ void Task_GUI(void *p_Parameters) xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_PIXEL_TEMPERATURE_READY); } else if (EventBits & LEPTON_SCENE_STATISTICS_READY) { char Buffer[16]; + float Temp; - float temp_max_celsius = _GUI_Task_State.ROIResult.Max; - snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_max_celsius); + Temp = _GUI_Task_State.ROIResult.Max; + snprintf(Buffer, sizeof(Buffer), "%.1f °C", Temp); lv_label_set_text(ui_Label_Main_Thermal_Scene_Max, Buffer); - float temp_min_celsius = _GUI_Task_State.ROIResult.Min; - snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_min_celsius); + Temp = _GUI_Task_State.ROIResult.Min; + snprintf(Buffer, sizeof(Buffer), "%.1f °C", Temp); lv_label_set_text(ui_Label_Main_Thermal_Scene_Min, Buffer); - float temp_mean_celsius = _GUI_Task_State.ROIResult.Mean ; - snprintf(Buffer, sizeof(Buffer), "%.1f °C", temp_mean_celsius); + Temp = _GUI_Task_State.ROIResult.Mean ; + snprintf(Buffer, sizeof(Buffer), "%.1f °C", Temp); lv_label_set_text(ui_Label_Main_Thermal_Scene_Mean, Buffer); xEventGroupClearBits(_GUI_Task_State.EventGroup, LEPTON_SCENE_STATISTICS_READY); diff --git a/main/Application/application.h b/main/Application/application.h index ac59c68..7a477ca 100644 --- a/main/Application/application.h +++ b/main/Application/application.h @@ -67,6 +67,7 @@ enum { */ enum { GUI_EVENT_INIT_DONE, /**< GUI task initialization done. */ + GUI_EVENT_INIT_ERROR, /**< GUI task initialization error occurred. */ GUI_EVENT_APP_STARTED, /**< Application has started. */ GUI_EVENT_REQUEST_ROI, /**< Update the ROI rectangle on the GUI. Data is transmitted in a App_Settings_ROI_t structure. */ diff --git a/webserver/provision.html b/webserver/provision.html index 5347c85..8242921 100644 --- a/webserver/provision.html +++ b/webserver/provision.html @@ -172,15 +172,22 @@

PyroVision

- +
- -
- + +
+ + +
+
@@ -190,7 +197,7 @@

PyroVision

onclick="togglePasswordVisibility()">👁️
- +